import telebot
from queue_bot_token import bot_token

bot = telebot.TeleBot(bot_token)

@bot.message_handler(commands=['start', 'help'])
def send_welcome(message):
    bot.reply_to(message, "Howdy, how are you doing?")

state = 1

@bot.message_handler(func=lambda message: True)
def echo_all(message):
    global state
    if state == 0:
        print("ZERO STATE")
        text = "Hi, " + message.text + " !"
        bot.reply_to(message, text)
    elif state == 1:
        print("FIRST STATE")
        text = "aaaaaa " + message.text + " !"
        bot.reply_to(message, text)

bot.polling()


import datetime
import json
import boto3
import os

def lambda_handler(event, context):
    print('## ENVIRONMENT VARIABLES')
    print(os.environ['AWS_LAMBDA_LOG_GROUP_NAME'])
    print(os.environ['AWS_LAMBDA_LOG_STREAM_NAME'])

    DYNAMODB_ENDPOINT_URL = 'http://%s:4566' % os.environ['LOCALSTACK_HOSTNAME']
    print(DYNAMODB_ENDPOINT_URL)
    print('## EVENT')
    print(event)

    dynamodb = boto3.resource('dynamodb', endpoint_url=DYNAMODB_ENDPOINT_URL)
    print(dynamodb)
    #dynamodb = boto3.client('dynamodb', endpoint_url="http://localhost:4566")
    table = dynamodb.Table('GPS_data')
    print(table)

    for record in event['Records']:

        payload=record['body']
        print(payload)
        payload=json.loads(str(payload))

        player_id = payload['player_id']
        print("ciaooooo")
        measure_data = datetime.datetime.strptime(payload['timestamp'], "%Y-%m-%d %H:%M:%S")

        latitude = payload['latitude']
        longitude =payload['longitude']
        print(player_id)
        print(latitude)
        print(longitude)
        print(measure_data)
        game_id=payload['game_id']
        munition=payload['munition']
        item = {
            'player_id': player_id,
            'timestamp': str(measure_data),
            'latitude': latitude,
            'longitude': longitude,
            'game_id':game_id,
            'munition':munition
        }
        table.put_item(Item=item)

        print(item)


'''
Created on 30 ÎœÎ±Ï� 2017

@author: Sugar
'''

import json
import jsonpickle
from JSONoutputObjectDefinitions import *

def __assignDefaultInputs__(outObject):
    #outObject.platform="xgene2"
    outObject.board="UCY"
    outObject.chip="normal"
    outObject.total_dram_size=8

    dim_id1=dim_id()
    dim_id1.manufacturer="crucial"
    dim_id1.size=8
    dim_id1.model="CT102472BA1886D"
    dim_id1.part_number=""
    dim_ids=[]
    dim_ids.append(dim_id1)

    outObject.dim_ids=dim_ids

def generateDefaultInputs(out_file_name): #function for writting down an expOut object with some default inputs.. The output file can be automatically unboxed into a expOut object with importDefaultInputs funtion

    out_file=open(out_file_name,'w')

    outObject= expOut()
    __assignDefaultInputs__(outObject)
    frozen=jsonpickle.encode(outObject)

    out_file.write(frozen)

#def generateInputFile(out_file_name): #function for generating an expOut object that at the same time will bb used for input to the characterization framework.. The output file can be automatically unboxed into a expOut object with importInput funtion

#    out_file=open(out_file_name,'w')

#    outObject= expOut()
#    __assignDefaultInputs__(outObject)
#    outObject.w
#    frozen=jsonpickle.encode(outObject)

#    out_file.write(frozen)

def importInput(input_file):
    with open(input_file) as default_inputs:
        json_string=default_inputs.read().replace('\n',' ')
        #out=json.load(default_inputs)
    out=jsonpickle.decode(json_string)
    return out
    #for dim_id in out.dim_ids:
    #   print(dim_id.model)
    #print(out.dim_ids[0],)

def returnJsonAsString(json_obj):
    return(jsonpickle.encode(json_obj,unpicklable=False))

def __testJsonOutput__():
    with open("files/test") as f:
        lines = f.read().splitlines()

    jsonArray=[]
    print("[")
    for line in lines:
        #print("original line is " +line)
        newObject= expOut()
        newObject.board="UCY"
        newObject.chip="normal"
        cores=str(line).split(" ")[1]
        frequency=str(line).split(" ")[2]
        for core in str(cores).split(","):
            newObject.core_to_freq.append(int(frequency))
        newObject.core_vol=int(str(line).split(" ")[5])
        newObject.os_version="4.3.0-3.06.21+uniserver.161005.aarch64"
        newObject.soc_freq=2400
        newObject.soc_vol=980
        newObject.system_crash=True
        benchmark=str(str(line).split(" ")[7])#.split[1]
        workload_ins=workload()
        workload_ins.name=benchmark
        workload_ins.cores=cores.replace(","," ")
        workload_ins.inputs="native"
        newObject.workloads.append(workload_ins)
        frozen=jsonpickle.encode(newObject)
        print(frozen+",")
        #jsonArray.append(frozen)
    print("]")
    #frozen=jsonpickle.encode(jsonArray,unpicklable=False)
    #print(frozen)

#generateDefaultInputs("C:/Users/zhadji01/workspace/CharacterizationFramework/inputs/xg2_normal_1dim.json");
#importInput("C:/Users/zhadji01/workspace/CharacterizationFramework/inputs/xg2_normal_1dim.json")


# -*- coding: utf-8 -*-
# @Time    : 2023/5/19 10:54
# @Author  : CXRui
# @File    : 将日志同时输出控制台和文件.py
# @Description :
# 导入logging库
import logging
# 创建logger对象
logger = logging.getLogger("test_logger")
# 设置日志输出等级总开关
logger.setLevel(logging.DEBUG)
# 创建控制台实例
sh = logging.StreamHandler()

fh = logging.FileHandler("api.log", mode="a", encoding="utf-8")
# 设置控制台输出的日志级别
sh.setLevel(logging.DEBUG)
# 设置向文件输出的日志级别
fh.setLevel(logging.DEBUG)
# 统一设置日志的输出格式
formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
# 设置向控制台实例到logger对象中
logger.addHandler(sh)
# 加载文件实例到logger对象中
logger.addHandler(fh)

if __name__ == '__main__':
    logging.debug("-----调试信息[debug]-----")
    logging.info("-----调试信息[debug]-----")
    logging.warning("-----调试信息[debug]-----")
    logging.error("-----调试信息[debug]-----")
    logging.critical("-----调试信息[debug]-----")

将日志同时输出控制台和文件.py


#!/usr/bin/env python3
"""
asynchronously record "timeout" seconds of audio and output it again
"""
import pyaudio
import pycodec2
import time
import codec2_func

sound_card = 0
timeout = 30

def callback(in_data, frame_count, time_info, status):
    encoded = codec2_func.encode_codec2(in_data)
    snd_data = codec2_func.decode_codec2(encoded)
    return snd_data, pyaudio.paContinue

if __name__ == '__main__':
    p = pyaudio.PyAudio()
    # Create the Codec2 object
    c2 = pycodec2.Codec2(1200)

    print("please speak a word into the microphone")

    stream = p.open(format=pyaudio.paInt16,
                    channels=1,
                    rate=codec2_func.AUDIO_SAMPLE_RATE,
                    input=True,
                    input_device_index=sound_card,
                    output=True,
                    output_device_index=sound_card,
                    frames_per_buffer=codec2_func.chunk,
                    stream_callback=callback)
    t0 = time.perf_counter()
    while stream.is_active():
        if time.perf_counter() - t0 > timeout:
            break
    stream.stop_stream()
    stream.close()
    p.terminate()


from typing import Generator
from collections import defaultdict as dd
import numpy as np
import networkx as nx
import re, math, itertools

offsets = [(1, 0), (-1, 0), (0, 1), (0, -1)]

def sgn(x):
    return (1, -1)[x < 0]

def solve(input: str) -> Generator[any, None, None]:
    #     input = """R 5
    # U 8
    # L 8
    # D 3
    # R 17
    # D 10
    # L 25
    # U 20"""

    lines = [line.strip() for line in input.split("\n") if line]

    visited2 = dd(int)
    visited10 = dd(int)
    visited2[(0, 0)] = 1
    visited10[(0, 0)] = 1

    length = 10

    rope = [[0, 0] for _ in range(length)]

    for line_num, line in enumerate(lines):
        direction, amount = line.split(" ")
        amount = int(amount)

        # 0 = x, 1 = y
        axis = 0
        sign = 1

        if direction in ["L", "D"]:
            sign = -1
        if direction in ["U", "D"]:
            axis = 1

        for _ in range(amount):
            rope[0][axis] += sign
            for i in range(1, length):
                dx = rope[i][0] - rope[i - 1][0]
                dy = rope[i][1] - rope[i - 1][1]
                if dx == 0 or dy == 0:
                    if abs(dx) > 1:
                        rope[i][0] -= sgn(dx)
                    if abs(dy) > 1:
                        rope[i][1] -= sgn(dy)
                elif abs(dx) != 1 or abs(dy) != 1:
                    rope[i][0] -= sgn(dx)
                    rope[i][1] -= sgn(dy)

            visited2[tuple(rope[1])] += 1
            visited10[tuple(rope[9])] += 1

    yield len(visited2)
    yield len(visited10)


from question_model import Question
from data import question_data
from quiz_brain import Quiz

questions = []
for question in question_data:
    questions.append(Question(question["text"], question["answer"]))

quiz = Quiz(questions)
while quiz.has_questions():
    ques = quiz.next_question()
    ans = input(f"\n\nQ{quiz.question_number}:{ques} (True/False):").capitalize()
    if ans == quiz.check_answer():
        print("You got it right!")
        print(f"The correct answer was: {quiz.check_answer()}")
        print(f"Your current score is: {quiz.get_score()}/{quiz.question_number}")
    else:
        print("That's wrong.")
        print(f"The correct answer was: {quiz.check_answer()}")
        print(f"Your current score is: {quiz.points}/{quiz.question_number}")
print("\n\nYou've completed the quiz")
print(f"Your final sore was: {quiz.points}/{quiz.question_number}")


import os
from cli import run

def main():
	wins = 0
	losses = 0
	while True:
		print("===============================")
		print(f"   ————— Win/Loss: {wins}/{losses} —————")
		print("===============================")
		if run():
			wins += 1
		else:
			losses += 1
		inp = input("\nPlay again? Yes / No\n> ").lower()[0]
		if inp == "n":
			break
		os.system('cls' if os.name == 'nt' else 'clear')
	print(f"You won {int(wins/(wins+losses)*100)}% of the time")

if __name__ == "__main__":
	main()


import json
import random
import string
import uuid
from collections import Counter
from typing import List
import pymorphy2
import matplotlib.pyplot as plt
from nltk.corpus import stopwords
from nltk.tokenize import word_tokenize
from wordcloud import WordCloud

sw = set(stopwords.words('russian'))
table = str.maketrans(dict.fromkeys(string.punctuation))
stopgramms = ['NPRO', 'PREP', 'CONJ', 'PRCL', 'INTJ']
morph = pymorphy2.MorphAnalyzer(lang='ru')

# Читаем json переписки из телеграма и конвертируем его в тип dict
def read_json_tg() -> List[dict]:
    with open("result.json", encoding="utf-8", errors="ignore") as a:
        load_chat = [json.load(a)]
        return load_chat

# Считываем все данные типа messages
def get_messages(load_chat):
    for item in load_chat:
        if type(item) is dict:
            messages = item["messages"]
            return messages
    return []

# Чистим сообщения от не нужных знаков
def process(source: List[dict]) -> List[list]:
    messages = [normalize(read_message(message))
                for message in source if validation_message(message)]
    return messages

# Валидация сообщений
def validation_message(obj: dict) -> bool:
    if obj.get('type') != 'message':
        return False

    message_text = obj.get('text')
    response = type(message_text) is str and message_text != ''
    return response

# Читаем текст из сообщения
def read_message(obj: dict) -> str:
    message_text = obj.get('text')
    return message_text

# Убираем знаки пунктуации, союзы, предлоги
def normalize(text: str) -> [str]:
    text_with_punctuation = text.translate(table)
    tokens = []

    for w in word_tokenize(text_with_punctuation):
        p = morph.parse(w)[0]
        if p.tag.POS not in stopgramms:
            tokens.append(w)

    filtered_text = [w.lower() for w in tokens if not w.lower()
                     in sw and not w.isdigit()]
    return filtered_text

# Собираем список из всех слов переписки
def create_word_list(data: [[str]]) -> [str]:
    word_list = [item for sub in data for item in sub if len(item) != 0]
    return word_list

# Генерируем облако слов из списка слов переписки и создаем паттерн
def generate_cloud(word_list: [str], name_pattern: str) -> None:
    freq = Counter(word_list)

    if not name_pattern:
        name_pattern = str(uuid.uuid4())[:7]

    wc = WordCloud(width=1920, height=1080, max_words=20000, margin=10,
                   random_state=1).generate_from_frequencies(freq)
    plt.imshow(wc.recolor(random_state=int(random.random() * 256)),
               interpolation="bilinear")
    wc.to_file(name_pattern + '.png')
    plt.show()

def run(name_pattern: str) -> list and str:
    source = read_json_tg()
    user_chat = get_messages(source)
    processed_data = process(user_chat)
    data = create_word_list(processed_data)
    generate_cloud(data, name_pattern)

    return data, name_pattern

def run_saved_pattern(word_cloud: list) -> None:
    generate_cloud(word_cloud, "")


import cv2
import os
import numpy as np

def load_img(path):
    labelNameDict = {}
    labels = []
    faceImgs = []
    count = 0
    for root, dirs, files in os.walk(path):
        if root == path:
            continue

        name = root.split('\\')[-1]
        # print(name)
        labelNameDict[count] = name
        for f in files:
            grayImg = cv2.imread(os.path.join(root, f), cv2.IMREAD_GRAYSCALE)
            # faceDict[name].append(os.path.join(root, f))
            faceImgs.append(grayImg)
            labels.append(count)
        count += 1

    return faceImgs, labels, labelNameDict

if __name__ == "__main__":

    faceImgs, labels, labelNameDict = load_img(r'.\resources\faces')

    faceImgs = np.asarray(faceImgs)
    labels = np.asarray(labels)

    # eigenFaceModel
    # model = cv2.face.EigenFaceRecognizer_create()
    # FisherFaceModel
    # model = cv2.face.FisherFaceRecognizer_create()
    # LBPHFaceRecognizer
    model = cv2.face.LBPHFaceRecognizer_create()
    model.train(faceImgs, labels)

    # 使用另一半数据检测，并给出阈值范围
    # face_test = faceImgs[len(faceImgs)//2:]
    # label_test = labels[len(labels)//2:]
    # errorCount = 0
    # confList = []
    # for face, lab in zip(face_test, label_test):
    #     label, confidence = model.predict(face)
    #     if label != lab:
    #         # print('Error detection!!!')
    #         errorCount += 1
    #     else:
    #         confList.append(confidence)
    #
    # print('Total count:', len(face_test))
    # print('Total count2:', len(label_test))
    # print('Error count:', errorCount)
    # print('minimal confidence:', min(confList))
    # print('maximal confidence:', max(confList))
    # print('mean of confidence:', np.mean(confList))
    # print('median of confidence:', np.median(confList))
    # print('variance of confidence:', np.var(confList))

    path = r'.\resources\faces\lz'
    for root, dirs, files in os.walk(path):
        for f in files:
            grayImg = cv2.imread(os.path.join(root, f), cv2.IMREAD_GRAYSCALE)
            label, confidence = model.predict(grayImg)
            print('Predict label:{}; confidence:{}'.format(label, confidence))

    cap = cv2.VideoCapture(0)
    face_xml = cv2.CascadeClassifier(
        r'C:\Program Files\Python37\Lib\site-packages\cv2\data\haarcascade_frontalface_default.xml')

    while True:
        ret, frame = cap.read()
        gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
        faces = face_xml.detectMultiScale(gray, 1.3, 5)
        for (x, y, w, h) in faces:
            # EigenFace要求预测数据大小与训练集图片大小一致
            roi = gray[y:y + h, x:x + w]
            # roi = cv2.resize(roi, (200, 200))
            label, confidence = model.predict(roi)
            print('Predict label:{}; confidence:{}'.format(label, confidence))
            # labelNameDict[label]
            if confidence <= 50.0:
                cv2.putText(frame, labelNameDict[label], (x-5, y-5), fontFace=cv2.FONT_HERSHEY_COMPLEX,
                            fontScale=1, thickness=2, color=(0, 0, 255))
                cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 0, 255), 2)

        cv2.imshow('Display', frame)

        keyCode = cv2.waitKey(1)
        if keyCode == 27:
            break

    cap.release()
    cv2.destroyAllWindows()


import ldap
import ldap.modlist
from django.conf import settings

class LdapIapp(object):
    def __init__(self):
        self.ip = settings.AUTH_LDAP_SERVER_URI
        self.binddn = settings.AUTH_LDAP_BIND_DN
        self.bindpw= settings.AUTH_LDAP_BIND_PASSWORD
        self.scope = ldap.SCOPE_SUBTREE
        self.ldapvers = ldap.VERSION3

        try:
            self.lcon = ldap.initialize(self.ip)
            self.lcon.simple_bind_s(self.binddn, self.bindpw)
            self.lcon.protocol_version = self.ldapvers
        except ldap.LDAPError as e:
            return e

    def __del__(self):
        self.lcon.unbind()

    # allgemeingueltige suche, angabe aller parameter bei aufruf
    def getEntries(self, basedn, filters, attributes):
        r = self.lcon.search_s(basedn, self.scope, filters, attributes)
        if not r:
            return None
        result = []
        for values in r:
            result.append(values[1])
        return result

    # schreibt neuen Wert in LDAP
    def setEntries(self, dn, old, new):
        ldif = ldap.modlist.modifyModlist(old, new)
        self.lcon.modify_s(dn, ldif)
        return True

    # vorgefertigte suchanfragen
    def getPeople(self):
        result = self.getEntries(settings.LDAP_USER_DN, 'uid=*', ['uid', 'cn'])
        return self.sortPeopleUid(result)

    def getPeopleInfo(self, uid):
        result = self.getEntries(settings.LDAP_USER_DN, 'uid=' + uid, ['uid', 'cn'])
        return result[0]

    def getMaillist(self):
        entries = self.getEntries(settings.LDAP_MAILLIST_DN, 'cn=*', ['cn', ])
        list_entries = []
        for value in entries:
            list_entries.append(value['cn'][0])
        result = {'name' : list_entries, 'count' : len(list_entries)}
        return result

    def getMaillistInfo(self, list):
        maillist = self.getEntries(settings.LDAP_MAILLIST_DN, 'cn=' + list, ['cn', 'mail', 'owner', 'member'])
        peoples = self.getPeople()
        result = {'owner' : [], 'members' : []}
        for k, v in maillist[0].items():
            if k == 'member':
                for value in v:
                    user = value.split(',')
                    uid = user[0][4:]
                    if uid in peoples:
                        result['members'].append(peoples[uid]['cn'])
                    else:
                        pass
            elif k == 'owner':
                for value in v:
                    user = value.split(',')
                    uid = user[0][4:]
                    if uid in peoples:
                        result['owner'].append(peoples[uid]['cn'])
                    else:
                        pass
            elif k == 'mail':
                result['mail'] = v
            elif k == 'cn':
                result['cn'] = v
            else:
                #errorhandlig
                pass
        return result

    # Sortierung der Informationen aller Art
    def sortPeopleUid(self, people):
        result = {}
        for values in people:
            if 'cn' in values:
                result[values['uid'][0]] = {'uid' : values['uid'][0], 'cn' : values['cn'][0]}
            else:
                continue
        return result

def entry_from_ldap(entry, search_result, attributes):
    kwargs = {}
    get_all = False
    if len(attributes) == 0:
        get_all = True
    for key, value in search_result.items():
        if not key in entry.MULTIVALUE_ATTRS:
            value = value[0]
        if not get_all and key in attributes:
            kwargs[key] = value
            attributes = [x for x in attributes if x != key]
        else:
            kwargs[key] = value
        for key in attributes:
            kwargs[key] = ''
    return entry(**kwargs)


# Import packages
import os
import cv2
import numpy as np
import tensorflow as tf
import math
import time

# Import utilites
from utils import label_map_util
from utils import visualization_utils as vis_util
import filter_def

f_list = []

def load_models() :
    # load models 시작시간
    code_start = time.time()
    config= tf.compat.v1.ConfigProto()
    config.gpu_options.allow_growth = True
    session= tf.compat.v1.Session(config=config)

    # Name of the directory containing the object detection module we're using
    MODEL_NAME = 'models'
    LABELMAP_NAME = 'labelmap'

    # 결과 출력(cv.imwrite)해서 확인하려면 output 경로 수정
    # output_dir = "test_images_output\\"

    # Grab path to current working directory
    CWD_PATH = os.getcwd()

    model_list = os.listdir(CWD_PATH+"\\"+MODEL_NAME)
    labelmap_list = os.listdir(CWD_PATH+"\\"+LABELMAP_NAME)

    # =========================================================================
    # model 에 따라서 바뀌는 값들 배열
    sess = {}
    detection_graph = {}
    categories = {}
    category_index = {}
    i = 0
    # 모델 불러오는 부분 => 반복 (여러 모델 불러오기)
    for model, labelmap in zip(model_list, labelmap_list):
        # print(str(len(model_list))+"개 중에 "+str(i+1)+"번째 모델 불러오는 중")
        # print(model+", "+labelmap)

        # Path to frozen detection graph .pb file, which contains the model that is used for object detection.
        PATH_TO_CKPT = os.path.join(CWD_PATH, MODEL_NAME, model)
        # print("model_path : "+PATH_TO_CKPT)

        # Path to label map file
        PATH_TO_LABELS = os.path.join(CWD_PATH, LABELMAP_NAME, labelmap)
        # print("label_path : "+PATH_TO_LABELS)

        # Number of classes the object detector can identify
        # max_num_classes 를 지정해주는 값
        # 최대 라벨 개수로 지정해주면 될 것 같음
        # label class 개수보다 작은 값이 들어가면 N/A 라고 나옴
        NUM_CLASSES = 2

        # Load the label map.
        # Label maps map indices to category names
        # Here we use internal utility functions, but anything that returns a
        # dictionary mapping integers to appropriate string labels would be fine
        label_map = label_map_util.load_labelmap(PATH_TO_LABELS)
        categories[i] = label_map_util.convert_label_map_to_categories(label_map, max_num_classes=NUM_CLASSES,
                                                                    use_display_name=True)
        category_index[i] = label_map_util.create_category_index(categories[i])
        # print(category_index[i])

        # Load the Tensorflow model into memory.
        # Tensorflow 모델을 메모리에 로드
        # detection_graph 배열로 만들어서 이름 바꿔주면서 image 넣기
        detection_graph[i] = tf.Graph()
        with detection_graph[i].as_default():
            od_graph_def = tf.compat.v1.GraphDef()
            with tf.io.gfile.GFile(PATH_TO_CKPT, 'rb') as fid:
                # print(PATH_TO_CKPT)
                serialized_graph = fid.read()
                od_graph_def.ParseFromString(serialized_graph)
                tf.import_graph_def(od_graph_def, name='')

            sess[i] = tf.Session(graph=detection_graph[i])
        i = i + 1
    # print("모델 불러오는데 걸리는 시간 : "+str(round(time.time() - code_start,5)))
    # ==========================================================================

    return sess, detection_graph, category_index

def detect_fake(face_list, video, number,count, sess, detection_graph, category_index) :
    code_start = time.time()

    # Name of the directory containing the object detection module we're using
    MODEL_NAME = 'models'
    # Grab path to current working directory
    CWD_PATH = os.getcwd()
    model_list = os.listdir(CWD_PATH + "\\" + MODEL_NAME)

    PATH_TO_VIDEO = video
    # Open video file
    f_list = face_list
    # print(str(len(f_list)))
    # print("load_models : " + str(f_list))

    video = cv2.VideoCapture(PATH_TO_VIDEO)
    face_num = 0
    num = number
    c= count
    print("flist : "+str(len(f_list)))
    # f_num =0
    while (video.isOpened()):
        # 몇번째 프레임인지 출력
        # print(face_num)
        # Acquire frame and expand frame dimensions to have shape: [1, None, None, 3]
        # 프레임을 획득하고 모양을 갖도록 프레임 크기를 확장합니다. [1, None, None, 3]
        # i.e. a single-column array, where each item in the column has the pixel RGB value
        # 즉, 열의 각 항목에 픽셀 RGB 값이있는 단일 열 배열
        ret, frame = video.read()
        # f_num += f_list[face_num][0]
        # print(f_num)
        # if f_num == 0:
        #     print('얼굴없다 탈주!')
        #     break
        frame_expanded = np.expand_dims(frame, axis=0)
        if (int(video.get(1)) % num == c ):

            # 모델 개수만큼 반복
            for j in range(len(sess)):
                # print(j)
                if f_list is None : break
                # 얼굴 좌표 찾기
                (left, right, top, bottom) = f_list[face_num]
                # 소수점 올림, 내림 /  ceil 올림, floor 내림
                left = math.floor(left)
                right = math.ceil(right)
                top = math.floor(top)
                bottom = math.ceil(bottom)
                height = bottom - top
                width = right - left
                # print(left, right, top, bottom)

                # left > 0인 경우 얼굴 좌표가 있는 것
                # 얼굴이 있는 경우 모델 통과
                if left != 0 and height>0 and width>0:
                    # (left, right, top, bottom)
                    # print(top - int(round(height / 6)), bottom+int(round(height / 6)))
                    # print(left - int(round(width / 6)), right + int(round(width / 6)))
                    # print(model_list[j])
                    model_name = model_list[j].split('.')[0]
                    # image = frame[int(top - 50):int(bottom + 50), int(left - 50):int(right + 50)]
                    # 각 부위별로 크롭하고
                    # 필터를 거침
                    # image = frame
                    # image = frame[int(top):int(bottom), int(left):int(right)]
                    image = frame[int(top - int(round(height / 6))):int(bottom+int(round(height / 6))),
                             int(left - int(round(width / 6))):int(right + int(round(width / 6)))]
                    if 'face' in model_name :
                        #image = frame[int(top-50):int(bottom+50), int(left-50):int(right+50)]
                        if 'noise' in model_name:
                            f_image = filter_def.face_noise(image)
                        # elif 'black' in model_name :
                        #     image = filter_def.face_black_area_color(image)
                    elif 'eye' in model_name:
                        # image = frame[int(top):int(bottom -int(round(height/2))),
                        #             int(left):int(right)]
                        # if 'brow_2_line' in model_name:
                        #     image = filter_def.eyebrow_doubleline(image)
                        if 'line_1' in model_name:
                            f_image = filter_def.eyebrow_vertical_line(image)
                    elif 'nose' in model_name:
                        # image = frame[int(top + int(round(height / 4))):int(bottom - int(round(height / 4))),
                        #             int(left):int(right)]
                                    # int(left + int(round(width / 4))):int(right - int(round(width / 4)))]
                        if 'noise' in model_name:
                            f_image = filter_def.nose_noise(image)
                        elif 'in_b' in model_name:
                            f_image = filter_def.nose_in_b(image)
                    elif 'mouth' in model_name:
                        # image = frame[int(top + int(round(height / 2))):int(bottom),
                        #             int(left):int(right)]
                        if 'ul' in model_name:
                            f_image = filter_def.mouth_h_b(image)

                    # 크롭, 필터까지 다 거친 이미지 배열
                    image_np_expanded = np.expand_dims(f_image, axis=0)

                    image_tensor = detection_graph[j].get_tensor_by_name('image_tensor:0')
                    # Each box represents a part of the image where a particular object was detected.
                    # 각 상자는 특정 물체가 감지된 이미지의 일부를 나타냅니다.
                    boxes = detection_graph[j].get_tensor_by_name('detection_boxes:0')
                    # Each score represent how level of confidence for each of the objects.
                    # 각 점수는 각 객체에 대한 신뢰 수준을 나타냅니다.
                    # Score is shown on the result image, together with the class label.
                    # 점수는 클래스 라벨과 함께 결과 이미지에 표시됩니다.
                    scores = detection_graph[j].get_tensor_by_name('detection_scores:0')
                    classes = detection_graph[j].get_tensor_by_name('detection_classes:0')
                    num_detections = detection_graph[j].get_tensor_by_name('num_detections:0')

                    # Perform the actual detection by running the model with the image as input
                    # 이미지를 입력으로 하여 모델을 실행하여 실제 감지 수행
                    # 여기서 모델을 거친다
                    # start_time = time.time()
                    (boxes, scores, classes, num_detections) = sess[j].run(
                        [boxes, scores, classes, num_detections],
                        # feed_dict = {image_tensor: frame_expanded})
                        feed_dict={image_tensor:image_np_expanded})

                    # elapsed_time = time.time() - start_time
                    # label_str = ""
                    # Draw the results of the detection (aka 'visualize the results')
                    # 탐지 결과 그리기 (일명 '결과 시각화')
                    label_str = vis_util.visualize_boxes_and_labels_on_image_array(
                        image,
                        np.squeeze(boxes),
                        np.squeeze(classes).astype(np.int32),
                        np.squeeze(scores),
                        category_index[j],
                        use_normalized_coordinates=True,
                        line_thickness=4,
                        min_score_thresh=0.1)
                    # 모델 거친 결과 출력
                    if label_str!= "": print(label_str)
                # print('inference time cost: {}'.format(elapsed_time))
                # else : print('얼굴이 전부 없거나 얼굴이 없음')
                # 박스 확인용 이미지 출력
                # output_dir = './test_videos/'+model_name+'/'
                # if not os.path.exists('./test_videos/'):
                #     os.mkdir('./test_videos/')
                # if not os.path.exists(output_dir):
                #     os.mkdir(output_dir)
                # # print(output_dir+model_name+"_"+str(face_num)+'.jpg')
                # cv2.imwrite(output_dir+model_name+"_"+str(face_num)+'.jpg', image)
                # else : print('얼굴 없음')
            # 300 프레임, 프레임 개수 만큼만 반복
            # if(face_num != 299) :
            face_num += 1
            if face_num >= len(face_list) : break

            # All the results have been drawn on the frame,
            # so it's time to display it.
            # 프레임에 그림을 그리고 이미지로 보여줌
            cv2.imshow('Object detector', frame)
            cv2.imwrite('./test_videos/frame/' + str(face_num) + '.jpg', frame)

            # Press 'q' to quit
            if cv2.waitKey(1) == ord('q'):
                break

    # Clean up
    video.release()
    cv2.destroyAllWindows()
    load_model_time = time.time() - code_start
    # print()

    return load_model_time


import json
import logging
from threading import Thread

import backoff
import monotonic

from posthog.request import APIError, DatetimeSerializer, batch_post

try:
    from queue import Empty
except ImportError:
    from Queue import Empty

MAX_MSG_SIZE = 900 * 1024  # 900KiB per event

# The maximum request body size is currently 20MiB, let's be conservative
# in case we want to lower it in the future.
BATCH_SIZE_LIMIT = 5 * 1024 * 1024

class Consumer(Thread):
    """Consumes the messages from the client's queue."""

    log = logging.getLogger("posthog")

    def __init__(
        self,
        queue,
        api_key,
        flush_at=100,
        host=None,
        on_error=None,
        flush_interval=0.5,
        gzip=False,
        retries=10,
        timeout=15,
    ):
        """Create a consumer thread."""
        Thread.__init__(self)
        # Make consumer a daemon thread so that it doesn't block program exit
        self.daemon = True
        self.flush_at = flush_at
        self.flush_interval = flush_interval
        self.api_key = api_key
        self.host = host
        self.on_error = on_error
        self.queue = queue
        self.gzip = gzip
        # It's important to set running in the constructor: if we are asked to
        # pause immediately after construction, we might set running to True in
        # run() *after* we set it to False in pause... and keep running
        # forever.
        self.running = True
        self.retries = retries
        self.timeout = timeout

    def run(self):
        """Runs the consumer."""
        self.log.debug("consumer is running...")
        while self.running:
            self.upload()

        self.log.debug("consumer exited.")

    def pause(self):
        """Pause the consumer."""
        self.running = False

    def upload(self):
        """Upload the next batch of items, return whether successful."""
        success = False
        batch = self.next()
        if len(batch) == 0:
            return False

        try:
            self.request(batch)
            success = True
        except Exception as e:
            self.log.error("error uploading: %s", e)
            success = False
            if self.on_error:
                self.on_error(e, batch)
        finally:
            # mark items as acknowledged from queue
            for item in batch:
                self.queue.task_done()
            return success

    def next(self):
        """Return the next batch of items to upload."""
        queue = self.queue
        items = []

        start_time = monotonic.monotonic()
        total_size = 0

        while len(items) < self.flush_at:
            elapsed = monotonic.monotonic() - start_time
            if elapsed >= self.flush_interval:
                break
            try:
                item = queue.get(block=True, timeout=self.flush_interval - elapsed)
                item_size = len(json.dumps(item, cls=DatetimeSerializer).encode())
                if item_size > MAX_MSG_SIZE:
                    self.log.error("Item exceeds 900kib limit, dropping. (%s)", str(item))
                    continue
                items.append(item)
                total_size += item_size
                if total_size >= BATCH_SIZE_LIMIT:
                    self.log.debug("hit batch size limit (size: %d)", total_size)
                    break
            except Empty:
                break

        return items

    def request(self, batch):
        """Attempt to upload the batch and retry before raising an error"""

        def fatal_exception(exc):
            if isinstance(exc, APIError):
                # retry on server errors and client errors
                # with 429 status code (rate limited),
                # don't retry on other client errors
                if exc.status == "N/A":
                    return False
                return (400 <= exc.status < 500) and exc.status != 429
            else:
                # retry on all other errors (eg. network)
                return False

        @backoff.on_exception(backoff.expo, Exception, max_tries=self.retries + 1, giveup=fatal_exception)
        def send_request():
            batch_post(self.api_key, self.host, gzip=self.gzip, timeout=self.timeout, batch=batch)

        send_request()


import sys
from collections import deque

def bfs(graph,n,visited):
    visited[n] = True
    box.appendleft(n)
    while len(box) !=0 :
        v = box.popleft()
        print(v,end=' ')
        for i in graph[v]:
            if not(visited[i]):
                box.append(i)
                visited[i] = True
box = deque([])

graph = [
    [],
    [2,3,8],
    [1,7],
    [1,4,5],
    [3,5],
    [3,4],
    [7],
    [2,6,8],
    [1,7]
]

visited = [False]*len(graph)

bfs(graph,1,visited)


#imports
from typing import Callable, Union, Type, Tuple
from gemd.entity.link_by_uid import LinkByUID
from gemd.entity.dict_serializable import DictSerializable
from gemd.entity.template import PropertyTemplate, ParameterTemplate, ConditionTemplate
from gemd.entity.template import MaterialTemplate, ProcessTemplate, MeasurementTemplate
from gemd.entity.object import MaterialSpec, ProcessSpec, IngredientSpec, MeasurementSpec
from gemd.entity.object import MaterialRun, ProcessRun, IngredientRun, MeasurementRun

######### THE FUNCTION BELOW IS COPIED/PASTED FROM GEMD CODE #########
def cached_isinstance_generator(class_or_tuple: Union[Type, Tuple[Type]]) -> Callable[[object], bool]:
    """
    Generate a function that checks and caches an isinstance(obj, class_or_tuple) call.

    Parameters
    ----------
    class_or_tuple: Union[Type, Tuple[Type]]
        A single type or a tuple of types

    Returns
    -------
    Callable[[object], bool]
        function with signature function(obj), returning isinstance(obj, class_or_tuple)

    """
    cache = dict()

    def func(obj):
        obj_type = type(obj)
        if obj_type not in cache:
            cache[obj_type] = isinstance(obj, class_or_tuple)
        return cache[obj_type]

    return func

#Some cached isinstance functions to reduce overhead
isinstance_template = cached_isinstance_generator((PropertyTemplate, ParameterTemplate, ConditionTemplate,
                                                   MaterialTemplate, ProcessTemplate, MeasurementTemplate))
isinstance_attribute_template = cached_isinstance_generator((PropertyTemplate, ParameterTemplate, ConditionTemplate))
isinstance_object_template = cached_isinstance_generator((MaterialTemplate, ProcessTemplate, MeasurementTemplate))
isinstance_spec = cached_isinstance_generator((MaterialSpec,ProcessSpec,IngredientSpec,MeasurementSpec))
isinstance_run = cached_isinstance_generator((MaterialRun,ProcessRun,IngredientRun,MeasurementRun))
isinstance_material_run = cached_isinstance_generator(MaterialRun)
isinstance_ingredient_run = cached_isinstance_generator(IngredientRun)
isinstance_link_by_uid = cached_isinstance_generator(LinkByUID)
isinstance_list_or_tuple = cached_isinstance_generator((list, tuple))
isinstance_dict_serializable = cached_isinstance_generator(DictSerializable)


import torch
import torch.nn as nn
import torchvision.models as models
from get_loader import get_loader

device = torch.device("cuda" if torch.cuda.is_available() else "cpu")

class Encoder(nn.Module):
    def __init__(self, encode_image_size=14, fine_tune=False):
        super(Encoder, self).__init__()
        resnet50 = models.resnet50(pretrained=True)# aux_logits: special parameters of inception
        #Remove linear and pool layers
        modules = list(resnet50.children())[:-2]
        self.resnet50 = nn.Sequential(*modules)

        # AdaptiveAvgPool2d-->自适应池化层，将输入尺寸变换为 encode_image_size * encode_image_size
        self.adaptive_pool = nn.AdaptiveAvgPool2d((encode_image_size,encode_image_size))

        # 是否训练resnet50
        self.fine_tune(fine_tune)

    def forward(self,images):

        out = self.resnet50(images)  # (batch_size, 2048, image_size/32, image_size/32)
        out = self.adaptive_pool(out)  # (batch_size, 2048, encoded_image_size, encoded_image_size)
        out = out.permute(0, 2, 3, 1)  # (batch_size, encoded_image_size, encoded_image_size, 2048)
        return out

    def fine_tune(self, fine_tune=False):
        """
        Allow or prevent the computation of gradients for convolutional blocks 2 through 4 of the encoder.

        :param fine_tune: Allow?
        """
        for p in self.resnet50.parameters():
            p.requires_grad = False
        # If fine-tuning, only fine-tune convolutional blocks 2 through 4
        for c in list(self.resnet50.children())[5:]:
            for p in c.parameters():
                p.requires_grad = fine_tune

class Attention(nn.Module):
    def __init__(self, feature_dim, hidden_size, attention_dim):
        """
        :param feature_dim: feature channels of encoded images
        :param hidden_size: hidden size of decoder's RNN
        :param attention_dim: size of the attention network
        """
        super(Attention, self).__init__()
        self.encoder_att = nn.Linear(feature_dim, attention_dim)  # linear layer to transform encoded image
        self.decoder_att = nn.Linear(hidden_size, attention_dim)  # linear layer to transform decoder's output
        self.full_att = nn.Linear(attention_dim, 1)  # linear layer to calculate values to be softmax-ed
        self.relu = nn.ReLU()
        self.softmax = nn.Softmax(dim=1)  # softmax layer to calculate weights

    def forward(self, encoder_out, decoder_hidden):
        """
        Forward propagation.

        :param encoder_out: encoded images, a tensor of dimension (batch_size, num_pixels, encoder_dim)
        :param decoder_hidden: previous decoder output, a tensor of dimension (batch_size, decoder_dim)
        :return: attention weighted encoding, weights
        """  #encoder_out (2,196,2048), decoder_hidden(2,512)
        att1 = self.encoder_att(encoder_out)  # (batch_size, num_pixels, attention_dim)(2,196,512)
        att2 = self.decoder_att(decoder_hidden)  # (batch_size, attention_dim)(2,512)
        att = self.full_att(self.relu(att1 + att2.unsqueeze(1))).squeeze(2)  # (batch_size, num_pixels) (2,196)
        alpha = self.softmax(att)  # (batch_size, num_pixels) (2,196)
        attention_weighted_encoding = (encoder_out * alpha.unsqueeze(2)).sum(dim=1)  # (batch_size, encoder_dim) (2,2048)

        return attention_weighted_encoding, alpha

class DecoderWithAttention(nn.Module):

    def __init__(self, attention_dim, embed_dim, hidden_size, vocab_size, feature_dim=2048, dropout=0.5):
        """
        :param attention_dim: size of attention network
        :param embed_dim: embedding size
        :param hidden_size: hidden size of decoder's RNN
        :param vocab_size: size of vocabulary
        :param feature_dim: feature size of encoded images
        :param dropout: dropout
        """
        super(DecoderWithAttention, self).__init__()

        self.feature_dim = feature_dim
        self.attention_dim = attention_dim
        self.embed_dim = embed_dim
        self.hidden_size = hidden_size
        self.vocab_size = vocab_size
        self.dropout = dropout

        self.attention = Attention(feature_dim, hidden_size, attention_dim)  # attention network

        self.embedding = nn.Embedding(vocab_size, embed_dim)  # embedding layer
        self.dropout = nn.Dropout(p=self.dropout)
        self.decode_step = nn.LSTMCell(embed_dim + feature_dim, hidden_size, bias=True)  # decoding LSTMCell
        self.init_h = nn.Linear(feature_dim, hidden_size)  # linear layer to find initial hidden state of LSTMCell
        self.init_c = nn.Linear(feature_dim, hidden_size)  # linear layer to find initial cell state of LSTMCell
        self.f_beta = nn.Linear(hidden_size, feature_dim)  # linear layer to create a sigmoid-activated gate
        self.sigmoid = nn.Sigmoid()
        self.fc = nn.Linear(hidden_size, vocab_size)  # linear layer to find scores over vocabulary
        self.init_weights()  # initialize some layers with the uniform distribution

    def init_weights(self):
        """
        Initializes some parameters with values from the uniform distribution, for easier convergence.
        """
        self.embedding.weight.data.uniform_(-0.1, 0.1)
        self.fc.bias.data.fill_(0)
        self.fc.weight.data.uniform_(-0.1, 0.1)

    def load_pretrained_embeddings(self, embeddings):
        """
        Loads embedding layer with pre-trained embeddings.

        :param embeddings: pre-trained embeddings
        """
        self.embedding.weight = nn.Parameter(embeddings)

    def fine_tune_embeddings(self, fine_tune=True):
        """
        Allow fine-tuning of embedding layer? (Only makes sense to not-allow if using pre-trained embeddings).

        :param fine_tune: Allow?
        """
        for p in self.embedding.parameters():
            p.requires_grad = fine_tune

    def init_hidden_state(self, encoder_out):
        """
        Creates the initial hidden and cell states for the decoder's LSTM based on the encoded images.

        :param encoder_out: encoded images, a tensor of dimension (batch_size, num_pixels, encoder_dim)
        :return: hidden state, cell state
        """
        mean_encoder_out = encoder_out.mean(dim=1)
        h = self.init_h(mean_encoder_out)  # (batch_size, decoder_dim)
        c = self.init_c(mean_encoder_out)
        return h, c

    def forward(self, encoder_out, encoded_captions):
        """
        Forward propagation.

        :param encoder_out: encoded images, a tensor of dimension (batch_size, enc_image_size, enc_image_size, encoder_dim)
        :param encoded_captions: encoded captions, a tensor of dimension (batch_size, max_caption_length)
        :return: scores for vocabulary, sorted encoded captions, decode lengths, weights, sort indices
        """
        #encoder_out (2,14,14,2048), encoded_captions (2,20)
        batch_size = encoder_out.size(0)
        feature_dim = encoder_out.size(-1)
        vocab_size = self.vocab_size # 10000

        # Flatten image
        encoder_out = encoder_out.view(batch_size, -1, feature_dim)  # (batch_size, num_pixels, encoder_dim) (2,196,2048)
        num_pixels = encoder_out.size(1) #14*14=196

        # Embedding
        embeddings = self.embedding(encoded_captions)  # (batch_size, max_caption_length, embed_dim) [2,20,512]

        # Initialize LSTM state
        h, c = self.init_hidden_state(encoder_out)  # (batch_size, decoder_dim) (2,512)

        # Create tensors to hold word predicion scores and alphas
        predictions = torch.zeros(batch_size, encoded_captions.shape[1], vocab_size).to(device) #shape [2,20,10000]
        alphas = torch.zeros(batch_size, encoded_captions.shape[1], num_pixels).to(device) #shape [2,20,196]

        # At each time-step, decode by
        # attention-weighing the encoder's output based on the decoder's previous hidden state output
        # then generate a new word in the decoder with the previous word and the attention weighted encoding
        for t in range(encoded_captions.shape[1]):
            attention_weighted_encoding, alpha = self.attention(encoder_out, h)
            gate = self.sigmoid(self.f_beta(h))  # gating scalar, (batch_size_t, encoder_dim) （2，2048）
            attention_weighted_encoding = gate * attention_weighted_encoding #（2，2048）
            h, c = self.decode_step(torch.cat([embeddings[:, t, :], attention_weighted_encoding], dim=1),(h, c))  # (batch_size_t, decoder_dim)
            preds = self.fc(self.dropout(h))  # (batch_size_t, vocab_size) （2，10000）
            predictions[:, t, :] = preds
            alphas[:, t, :] = alpha

        return predictions, encoded_captions,alphas

if __name__=='__main__':
    vocab_size = 10000
    emb_dim = 512  # dimension of word embeddings
    attention_dim = 512  # dimension of attention linear layers
    hidden_size = 512  # dimension of decoder RNN, 其实就是hidden_size
    dropout = 0.5
    decoder = DecoderWithAttention(attention_dim=attention_dim,
                                       embed_dim=emb_dim,
                                       hidden_size=hidden_size,
                                       vocab_size=vocab_size,
                                     dropout=dropout)
    encoder = Encoder()
    decoder = decoder.to('cuda')
    encoder = encoder.to('cuda')
    img = torch.ones(2,3,448,448).to('cuda')
    cap = torch.ones(2,20,dtype=int).to('cuda')
    img = encoder(img) #(1,3,448,448)--->(2,14,14,2048)
    scores, caps_sorted, alphas = decoder(img, cap)


"""Utility class for numerical operations."""

from __future__ import annotations

from typing import Union

__author__ = "730531580"

class Simpy:
    """Simps for NumPy."""
    values: list[float]

    def __init__(self, values: list[float]):
        """Helper to initialize attributes."""
        self.values = values

    def __str__(self) -> str:
        """"Initializes name as a string."""
        result: str = "Simpy(["
        for i in range(len(self.values)):
            value: str = str(self.values[i])
            # If it's the last value we don't want to concate ', '.
            if i == len(self.values) - 1:
                result += f"{value}])"
            else:
                value: str = str(self.values[i])
                result += f"{value}, "
        return result

    def fill(self, recurring: float, how_many: int) -> None:
        """Function that adds a recurring value to a list."""
        self.values = []
        i: int = 0
        while i < how_many:
            self.values.append(recurring)
            i += 1

    def arange(self, start: float, stop: float, step: float = 1.0) -> None:
        """Fills a list of floats within a range of numbers."""
        self.values: list[float] = []
        assert step != 0.0
        i: float = start
        while i < stop:
            self.values.append(i)
            i += step

    def sum(self) -> float:
        """Sum all values in values attribute."""
        result: float = 0.0
        for value in self.values:
            result += value
        return result

    def __add__(self, rhs: Union[Simpy, float]) -> Simpy:
        """Overload add operator for Simpy class."""
        # Conditional to determine the type of the rhs.
        result = Simpy([])
        if isinstance(rhs, Simpy):
            assert len(rhs.values) == len(self.values)
            for i in range(len(self.values)):
                result.values.append(self.values[i] + rhs.values[i])
        elif isinstance(rhs, float):
            for value in self.values:
                result.values.append(value + rhs)
        return result

    def __pow__(self, rhs: Union[Simpy, float]) -> Simpy:
        """Overload the power operator for Simpy class."""
        result = Simpy([])
        if isinstance(rhs, Simpy):
            assert len(rhs.values) == len(self.values)
            for i in range(len(self.values)):
                result.values.append(self.values[i] ** rhs.values[i])
        # Personally had to add this reduancy to make jupyter not produce an error.
        elif isinstance(rhs, float):
            for value in self.values:
                result.values.append(value ** rhs)
        return result

    def __eq__(self, rhs: Union[Simpy, float]) -> list[bool]:
        """Overload the equals operator for Simpy class."""
        result: list[bool] = []
        if isinstance(rhs, Simpy):
            assert len(rhs.values) == len(self.values)
            for i in range(len(self.values)):
                result.append(self.values[i] == rhs.values[i])
        # Personally had to add this reduancy to make jupyter not produce an error.
        elif isinstance(rhs, float):
            for value in self.values:
                result.append(value == rhs)
        return result

    def __gt__(self, rhs: Union[Simpy, float]) -> list[bool]:
        """Overload the greater than operator for Simpy class."""
        result: list[bool] = []
        if isinstance(rhs, Simpy):
            assert len(rhs.values) == len(self.values)
            for i in range(len(self.values)):
                result.append(self.values[i] > rhs.values[i])
        # Personally had to add this reduancy to make jupyter not produce an error.
        elif isinstance(rhs, float):
            for value in self.values:
                result.append(value > rhs)
        return result

    def __getitem__(self, rhs: Union[int, list[bool]]) -> Union[float, Simpy]:
        """Overload the subscription operator for Simpy class."""
        if isinstance(rhs, int):
            assert len(self.values) > rhs
            return self.values[rhs]
        else:
            result: Simpy = Simpy([])
            assert len(rhs) == len(self.values)
            for i in range(len(rhs)):
                if rhs[i]:
                    result.values.append(self.values[i])
            return result


# -*- coding: utf-8 -*-
# @Time    : 2019/12/25 11:32
# @Author  : 张茹飞
# @Email   : 1106815482@qq.com
# @File    : teachers.py
# @Software: PyCharm

from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import QApplication
import sys
import sql_class
data=sql_class.Mysqlpython()
answer_question=[]
account_n=0
# self.dialog=Dialog
class Ui_Dialog(object):
    def setupUi(self, Dialog):
        Dialog.setObjectName("Dialog")
        Dialog.resize(1266, 850)
        self.dialog=Dialog
        self.gridLayout = QtWidgets.QGridLayout(Dialog)
        self.gridLayout.setObjectName("gridLayout")
        self.horizontalLayout_3 = QtWidgets.QHBoxLayout()
        self.horizontalLayout_3.setObjectName("horizontalLayout_3")
        spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Minimum)
        self.horizontalLayout_3.addItem(spacerItem)
        self.textBrowser = QtWidgets.QTextBrowser(Dialog)
        self.textBrowser.setMinimumSize(QtCore.QSize(400, 600))
        self.textBrowser.setMaximumSize(QtCore.QSize(400, 600))
        font = QtGui.QFont()
        font.setPointSize(18)
        self.textBrowser.setFont(font)
        self.textBrowser.setObjectName("textBrowser")
        self.horizontalLayout_3.addWidget(self.textBrowser)
        spacerItem1 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Minimum)
        self.horizontalLayout_3.addItem(spacerItem1)
        self.textEdit = QtWidgets.QTextEdit(Dialog)
        self.textEdit.setMinimumSize(QtCore.QSize(400, 600))
        self.textEdit.setMaximumSize(QtCore.QSize(400, 600))
        font = QtGui.QFont()
        font.setPointSize(18)
        self.textEdit.setFont(font)
        self.textEdit.setObjectName("textEdit")
        self.horizontalLayout_3.addWidget(self.textEdit)
        spacerItem2 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Minimum)
        self.horizontalLayout_3.addItem(spacerItem2)
        self.gridLayout.addLayout(self.horizontalLayout_3, 2, 0, 1, 2)
        self.horizontalLayout = QtWidgets.QHBoxLayout()
        self.horizontalLayout.setObjectName("horizontalLayout")
        spacerItem3 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
        self.horizontalLayout.addItem(spacerItem3)
        self.pushButton_2 = QtWidgets.QPushButton(Dialog)
        self.pushButton_2.setMinimumSize(QtCore.QSize(120, 25))
        self.pushButton_2.setMaximumSize(QtCore.QSize(120, 30))
        font = QtGui.QFont()
        font.setPointSize(18)
        self.pushButton_2.setFont(font)
        self.pushButton_2.setObjectName("pushButton_2")
        self.horizontalLayout.addWidget(self.pushButton_2)
        self.pushButton = QtWidgets.QPushButton(Dialog)
        self.pushButton.setMinimumSize(QtCore.QSize(120, 25))
        self.pushButton.setMaximumSize(QtCore.QSize(120, 30))
        font = QtGui.QFont()
        font.setPointSize(18)
        self.pushButton.setFont(font)
        self.pushButton.setObjectName("pushButton")
        self.horizontalLayout.addWidget(self.pushButton)
        self.pushButton_5 = QtWidgets.QPushButton(Dialog)
        self.pushButton_5.setMinimumSize(QtCore.QSize(120, 25))
        self.pushButton_5.setMaximumSize(QtCore.QSize(120, 30))
        font = QtGui.QFont()
        font.setPointSize(18)
        self.pushButton_5.setFont(font)
        self.pushButton_5.setObjectName("pushButton_5")
        self.horizontalLayout.addWidget(self.pushButton_5)
        self.pushButton_6 = QtWidgets.QPushButton(Dialog)
        self.pushButton_6.setMinimumSize(QtCore.QSize(120, 25))
        self.pushButton_6.setMaximumSize(QtCore.QSize(120, 30))
        font = QtGui.QFont()
        font.setPointSize(18)
        self.pushButton_6.setFont(font)
        self.pushButton_6.setObjectName("pushButton_6")
        self.horizontalLayout.addWidget(self.pushButton_6)
        spacerItem4 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
        self.horizontalLayout.addItem(spacerItem4)
        self.pushButton_3 = QtWidgets.QPushButton(Dialog)
        self.pushButton_3.setMinimumSize(QtCore.QSize(120, 25))
        self.pushButton_3.setMaximumSize(QtCore.QSize(120, 30))
        font = QtGui.QFont()
        font.setPointSize(18)
        self.pushButton_3.setFont(font)
        self.pushButton_3.setObjectName("pushButton_3")
        self.horizontalLayout.addWidget(self.pushButton_3)
        spacerItem5 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
        self.horizontalLayout.addItem(spacerItem5)
        self.pushButton_4 = QtWidgets.QPushButton(Dialog)
        self.pushButton_4.setMinimumSize(QtCore.QSize(120, 25))
        self.pushButton_4.setMaximumSize(QtCore.QSize(120, 30))
        font = QtGui.QFont()
        font.setPointSize(18)
        self.pushButton_4.setFont(font)
        self.pushButton_4.setObjectName("pushButton_4")
        self.horizontalLayout.addWidget(self.pushButton_4)
        spacerItem6 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
        self.horizontalLayout.addItem(spacerItem6)
        self.gridLayout.addLayout(self.horizontalLayout, 4, 0, 1, 2)
        self.label = QtWidgets.QLabel(Dialog)
        font = QtGui.QFont()
        font.setPointSize(24)
        self.label.setFont(font)
        self.label.setAlignment(QtCore.Qt.AlignCenter)
        self.label.setObjectName("label")
        self.gridLayout.addWidget(self.label, 0, 0, 1, 2)
        spacerItem7 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Maximum)
        self.gridLayout.addItem(spacerItem7, 1, 1, 1, 1)
        spacerItem8 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Fixed)
        self.gridLayout.addItem(spacerItem8, 3, 0, 1, 1)
        spacerItem9 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Fixed)
        self.gridLayout.addItem(spacerItem9, 5, 0, 1, 1)

        self.retranslateUi(Dialog)
        QtCore.QMetaObject.connectSlotsByName(Dialog)

    def retranslateUi(self, Dialog):
        _translate = QtCore.QCoreApplication.translate
        Dialog.setWindowTitle(_translate("Dialog", "Dialog"))
        self.pushButton_2.setText(_translate("Dialog", "上一条"))
        self.pushButton.setText(_translate("Dialog", "下一条"))
        self.pushButton_5.setText(_translate("Dialog", "同意"))
        self.pushButton_6.setText(_translate("Dialog", "不同意"))
        self.pushButton_3.setText(_translate("Dialog", "提交答案"))
        self.pushButton_4.setText(_translate("Dialog", "退    出"))
        self.label.setText(_translate("Dialog", "教师答疑"))
        answer_question.clear()
        self.obtin()
        if len(answer_question)!=0:

            if answer_question[0][1] == None:
                self.textBrowser.setText(
                    "第" + str(account_n + 1) + "条，" + "共" + str(len(answer_question)) + "条" + '\n' +
                    "题目:       " + answer_question[account_n][0] + '\n' + "答案:       " + "无人作答")
            else:
                self.textBrowser.setText(
                    "第" + str(account_n + 1) + "条，" + "共" + str(len(answer_question)) + "条" + '\n' +
                    "题目:       " + answer_question[account_n][0] + '\n' + "答案:       " + answer_question[account_n][1])

        self.pushButton_4.clicked.connect(self.go_main)
        self.pushButton_2.clicked.connect(self.previous)
        self.pushButton.clicked.connect(self.Next)
        self.pushButton_5.clicked.connect(self.agree)
        self.pushButton_6.clicked.connect(self.reject)
        self.pushButton_3.clicked.connect(self.submit)

    #todo 获取所有faq的数据，并显示结果，
    def obtin(self):
        global answer_question
        answer_question.clear()
        sql_account = data.Search("SELECT question,answer FROM faq")
        regedit_information = list(sql_account)
        for i in regedit_information:
            answer_question.append(list(i))
        print(answer_question)
    def previous(self):
        global account_n
        if len(answer_question)!=0:
            if account_n != 0:
                account_n -= 1
                if answer_question[account_n][1]==None:
                    self.textBrowser.setText("第"+str(account_n+1)+"条，"+"共"+str(len(answer_question))+"条"+'\n'+
                        "题目:       " + answer_question[account_n][0] + '\n' + "答案:       " + "无人作答")
                else:
                    self.textBrowser.setText("第"+str(account_n+1)+"条，"+"共"+str(len(answer_question))+"条"+'\n'+
                        "题目:       " + answer_question[account_n][0] + '\n' + "答案:       " + answer_question[account_n][1])
            else:
                pass
    def Next(self):
        global  account_n
        if len(answer_question) != 0:
            if account_n < len(answer_question)-1:
                account_n += 1
                if answer_question[account_n][1]==None:
                    self.textBrowser.setText("第"+str(account_n+1)+"条，"+"共"+str(len(answer_question))+"条"+'\n'+
                        "题目:       " + answer_question[account_n][0] + '\n' + "答案:       " + "无人作答")
                else:
                    self.textBrowser.setText("第"+str(account_n+1)+"条，"+"共"+str(len(answer_question))+"条"+'\n'+
                        "题目:       " + answer_question[account_n][0] + '\n' + "答案:       " + answer_question[account_n][1])
            else:
                pass
    def agree(self):

        global account_n
        if len(answer_question) != 0:
            sql = "INSERT INTO questionbank(question,ansswer) VALUES ('%s','%s')" % (answer_question[account_n][0],answer_question[account_n][1] )

            print(sql)
            data.Operation(sql)

            sql = "DELEte FROM faq where question = '%s'" % answer_question[account_n][0]
            print(sql)
            data.Operation(sql)
            # 添加后刷新
            answer_question.clear()
            self.obtin()
            account_n = 0
            if len(answer_question) != 0:
                if answer_question[account_n][1] == None:
                    self.textBrowser.setText(
                        "第" + str(account_n + 1) + "条，" + "共" + str(len(answer_question)) + "条" + '\n' +
                        "题目:       " + answer_question[account_n][0] + '\n' + "答案:       " + "无人作答")
                else:
                    self.textBrowser.setText(
                        "第" + str(account_n + 1) + "条，" + "共" + str(len(answer_question)) + "条" + '\n' +
                        "题目:       " + answer_question[account_n][0] + '\n' + "答案:       " +
                        answer_question[account_n][1])
            else:
                self.textBrowser.setText("无消息")
        else:
            self.textBrowser.setText("无消息")
    def reject(self):
        global account_n
        if len(answer_question) != 0:
            sql = "DELEte FROM faq where question = '%s'" % answer_question[account_n][0]
            print(sql)
            data.Operation(sql)
            #删除后刷新
            answer_question.clear()
            self.obtin()
            account_n=0
            if len(answer_question)!=0:
                if answer_question[account_n][1] == None:
                    self.textBrowser.setText("第" + str(account_n + 1) + "条，" + "共" + str(len(answer_question)) + "条" + '\n' +
                                             "题目:       " + answer_question[account_n][0] + '\n' + "答案:       " + "无人作答")
                else:
                    self.textBrowser.setText("第" + str(account_n + 1) + "条，" + "共" + str(len(answer_question)) + "条" + '\n' +
                                             "题目:       " + answer_question[account_n][0] + '\n' + "答案:       " +
                                             answer_question[account_n][1])
            else:
                self.textBrowser.setText("无消息")
        else:
            self.textBrowser.setText("无消息")
    def submit(self):
        global account_n

        if answer_question:

                #有答案，覆盖

                if self.textEdit.toPlainText():
                    print("zhunb")
                    sql = "INSERT INTO questionbank(question,ansswer) VALUES ('%s','%s')" % ( answer_question[account_n][0], self.textEdit.toPlainText())
                    data.Operation(sql)
                    sql = "DELEte FROM faq where question = '%s'" % answer_question[account_n][0]
                    data.Operation(sql)
                    # 删除后刷新
                    answer_question.clear()
                    self.obtin()
                    account_n = 0
                    if len(answer_question) != 0:
                        if answer_question[account_n][1] == None:
                            self.textBrowser.setText(
                                "第" + str(account_n + 1) + "条，" + "共" + str(len(answer_question)) + "条" + '\n' +
                                "题目:       " + answer_question[account_n][0] + '\n' + "答案:       " + "无人作答")
                        else:
                            self.textBrowser.setText(
                                "第" + str(account_n + 1) + "条，" + "共" + str(len(answer_question)) + "条" + '\n' +
                                "题目:       " + answer_question[account_n][0] + '\n' + "答案:       " +
                                answer_question[account_n][1])
                    else:
                        self.textBrowser.setText("无消息")
                else:
                    self.textBrowser.setText("无消息")
    def go_main(self):
        self.dialog.close()
if __name__ == "__main__":
    app = QApplication(sys.argv)
    form = QtWidgets.QDialog()
    form.setWindowFlags(
        QtCore.Qt.WindowMinimizeButtonHint | QtCore.Qt.WindowCloseButtonHint | QtCore.Qt.WindowMaximizeButtonHint)
    ui = Ui_Dialog()
    ui.setupUi(form)
    form.show()
    sys.exit(app.exec_())


from flask import Flask, render_template, request
from data import DATA_FILE

app = Flask("MyApp")

@app.route("/")

def index():
	return render_template('index.html')

@app.route("/location_route", methods=["POST"])

def location_route():
	form_data = request.form
	print (form_data["location"])
	return "All OK"

@app.route("/location", methods=['POST'])

def location():
	if request.form["location"]:
	  return render_template('location.html', location=request.form["location"], data=DATA_FILE)
	else:
	  return 'Hey'

app.run(debug=True)


#https://stackoverflow.com/questions/45419723/python-timer-with-asyncio-coroutine

import asyncio

class Timer:
    def __init__(self, timeout, callback, args):
        self._timeout = timeout
        self._callback = callback
        self._task = asyncio.ensure_future(self._job(args))

    async def _job(self, args):
        await asyncio.sleep(self._timeout)
        await self._callback(*args)

    def cancel(self):
        self._task.cancel()


import streamlit as st

"""Framework para executar vÃ¡rios aplicativos Streamlit
   como um Ãºnico aplicativo."""

class MultiApp:

    def __init__(self):
        self.apps = []

    """
    Framework for combining multiple streamlit applications.
    Usage:
        def foo():
            st.title("Hello Foo")
        def bar():
            st.title("Hello Bar")
        app = MultiApp()
        app.add_app("Foo", foo)
        app.add_app("Bar", bar)
        app.run()
    It is also possible keep each application in a separate file.
        import foo
        import bar
        app = MultiApp()
        app.add_app("Foo", foo.app)
        app.add_app("Bar", bar.app)
        app.run()
    """

    def add_app(self, title, func):
        """Adds a new application.
        Parameters
        ----------
        func:
            the python function to render this app.
        title:
            title of the app. Appears in the dropdown in the sidebar.
        """
        self.apps.append({
            "title": title,
            "function": func
        })

    def run(self):
        # COMANDOS DA BARRA LATERAL
        padding = 0
        st.sidebar.markdown(f""" <style>
        .reportview-container .main .block-container{{
            padding-top: {padding}rem;
            padding-bottom: {padding}rem;
        }} </style> """, unsafe_allow_html=True)

        st.sidebar.title("ðŸš€ Veritas")
        #st.sidebar.title("Menu")
        st.sidebar.markdown("---")

        app = st.sidebar.radio(
            '',
            self.apps,
            format_func=lambda veritas: veritas['title'])

        app['function']()

        st.sidebar.markdown("---")

        if st.sidebar.button("Fale com a gente!", key="5"):
            st.sidebar.markdown('''
                Grupo Tera

               moxÃº - dairenkonmajime@gmail.com

               felipe - fmonteirogabriel@gmail.com

               lauro - lauro.namiki@gmail.com

               mel - meliza.caug@gmail.com

               rodolpho - rodolphoya@gmail.com

                ''')
            pass


#!/usr/bin/env python3

import os, sys, glob, argparse, shutil, multiprocessing
import pandas as pd
import numpy as np
from Bio import SeqIO
from collections import defaultdict
from itertools import groupby
from datetime import datetime
from contextlib import suppress

scriptlocation = os.path.dirname(os.path.realpath(__file__))

def cpu_threads(max_threads):
    if multiprocessing.cpu_count() > max_threads:
        return max_threads
    else:
        return multiprocessing.cpu_count()

# Import arguments
parser = argparse.ArgumentParser()
parser.add_argument("--species", help="define species (required)", required=('--input') in sys.argv and len(sys.argv) != 1)
parser.add_argument("--input", help="directory with input fasta files (required)", required=('--species') in sys.argv and len(sys.argv) != 1)
parser.add_argument("--specieslist", help="list of available species models", action="store_true", default=False)
parser.add_argument("--jelly", help="run jellyfish as kmer-count (faster)", action="store_true", default=False)
parser.add_argument("--out", help="specify output directory", default=False)
parser.add_argument("--debug", help="no cleanup of intermediate files", action="store_true", default=False)
parser.add_argument("--training", help="trainings mode Random Forest", action="store_true", default=False)
parser.add_argument("--threads", help="specify number of threads to be used, default is max available threads up to 16 threads", default=cpu_threads(16), type=int)
parser.add_argument("--version", help="print version number", action="store_true")

args = parser.parse_args()
species_import = args.species
input_directory = args.input
species_file = os.path.join(scriptlocation, "specieslist.txt")
df_species = pd.read_csv(species_file, header=None, sep=' ', names=['species', 'level'])
level_import = next(iter(df_species.loc[df_species['species'] == species_import, 'level']), 'no match')
species_list = df_species['species'].tolist()

# version
version = "1.0"
if args.version:
	print('RFPlasmid version %s' % version)
	sys.exit()

if args.specieslist:
    print('Available species models: \n{}'.format(df_species.species.to_csv(index=False, header=False)))
    sys.exit()

if len(sys.argv) <= 1:
    print("Error; no arguments. Required to specificy --input and --species")
    parser.print_help(sys.stderr)
    sys.exit()

# check if input is directory
if not os.path.isdir(input_directory):
    print('%r is not a directory. Please use directory as input.' % input_directory)
    sys.exit()

if len(sys.argv) == 1:
    parser.print_help(sys.stderr)
    sys.exit()

# check if species exist in list
if not args.species in species_list:
    print('Error: species classification model is not available')
    print('Available species models: \n{}'.format(df_species.species.to_csv(index=False, header=False)))
    sys.exit()

print('Start RFPlasmid, version %s' % version)

#make output folder
if args.out:
    new_dir = args.out
    if not os.path.exists(new_dir):
        os.mkdir(new_dir)
    else:
        now = datetime.now().strftime('%Y%m%d_%H%M%S')
        new_dir = new_dir + '_' + now
        os.mkdir(new_dir)
if not args.out:
    now = datetime.now().strftime('%Y%m%d_%H%M%S')
    new_dir = 'RFPlasmid_output' + '_' + now
    os.mkdir(new_dir)

# copy original contigIDs
print('copy original contig names')
for fasta_file in glob.glob(os.path.join(input_directory, '*.fasta')):
    basename = os.path.splitext(os.path.basename(fasta_file))[0]
    with open(fasta_file, 'r') as f_fasta:
        i = 0
        records = SeqIO.parse(f_fasta, 'fasta')
        for record in records:
            i = i + 1
            contig_id = basename + '\t' + str(i) + '\t' + record.description
            with open(new_dir+'/contigID.out', 'a') as ID_file:
                ID_file.write(contig_id + '\n')

# cleanup fasta files
print('cleanup contig names')
for fasta_file in glob.glob(os.path.join(input_directory, '*.fasta')):
    basename = os.path.splitext(os.path.basename(fasta_file))[0]
    new_file = os.path.join(new_dir, basename+'.fasta')
    i = 0
    with open(fasta_file, 'r') as file_fasta, open(new_file, 'w') as new:
        for i, seq_record in enumerate(SeqIO.parse(file_fasta, "fasta")):
            seq_record.id = str(i + 1)
            seq_record.description = ""
            SeqIO.write(seq_record, new, "fasta")

# change working directory to new directory
os.chdir(new_dir)

# Checkm
print('start Checkm')
if args.species == 'Generic':
    species_import = 'Bacteria'
os.system('checkm taxonomy_wf {} {} . checkm_output -x fasta --nt -t 16 > checkm_output.tsv'.format(level_import, species_import))

# check if Checkm files are made
if not os.path.isfile("./checkm_output/{file}.ms".format(file=species_import)):
    print("\nError: Checkm is not working properly.\nHave you installed the Checkm databases according to the github page of Checkm https://ecogenomics.github.io/CheckM/?")
    sys.exit()

# check if contigs contain ORFs
for fasta_file in glob.glob('*.fasta'):
    basename = os.path.splitext(os.path.basename(fasta_file))[0]
    if not os.path.isfile("./checkm_output/bins/{contig}/hmmer.analyze.txt".format(contig=basename)):
        print('Error: File {} is too short for prediction'.format(basename))
        sys.exit()
print('Checkm done')

# Blast plasmiddb genes
print('start blast plasmiddb')
plasmiddb_total_file = os.path.join(scriptlocation, "plasmiddb_total")

for root, dirs, files in os.walk(os.getcwd()):
    filepath = os.path.join(root, 'genes.faa')
    basename = os.path.basename(os.path.dirname(filepath))
    if os.path.isfile(filepath):
        output_file = os.path.join(root, 'blast_plasmiddb_output.txt')
        os.system('diamond blastp -d {} -q {} -e 1E-30 -k 1 > {}'.format(plasmiddb_total_file, filepath, output_file))
    else:
        continue

for root, dirs, files in os.walk(os.getcwd()):
    filepath = os.path.join(root, 'blast_plasmiddb_output.txt')
    if os.path.isfile(filepath):
        with open(filepath, 'r') as f1:
            with suppress(ValueError):
                df1 = pd.read_csv(f1, header=None, delim_whitespace=True, usecols=[0,2], names=['contig_gene', 'hit'])
                df1['hit'] = df1['hit'].round(0).astype(int)
                df1 = df1.loc[df1['hit'] > 80]
                df1['contig_gene'] = df1['contig_gene'].drop_duplicates()
                df1[['contig', 'gene']] = df1['contig_gene'].str.split('_', n=1, expand=True)
                df2 = df1.groupby(['contig']).size().reset_index(name='counts')
                output_file = os.path.join(root, 'plasmiddbgenes_per_contig.txt')
                with open(output_file, 'w') as out_file:
                    df2.to_csv(out_file, sep=' ', index=False, header=False)
    else:
        continue
print('blast plasmid genes done')

# Start blast cge genes
print('start blast cge')
cgedb_file = os.path.join(scriptlocation, "plasmiddb_cge")

for fasta_file in glob.glob('*.fasta'):
    basename = os.path.splitext(os.path.basename(fasta_file))[0]
    output_file = basename + '_blast_plasmidcge_output.txt'
    os.system('diamond blastx -d {} -q {} -e 1E-30 -k 1 > {}'.format(cgedb_file, fasta_file, output_file))

for cge_file in glob.glob('*_blast_plasmidcge_output.txt'):
    with open(cge_file, 'r') as f1:
        with suppress(ValueError):
            genome_name = str(cge_file).split('_blast')[:-1][0]
            df1 = pd.read_csv(f1, header=None, delim_whitespace=True, usecols=[0,2], names=['contig', 'hit'])
            df1['hit'] = df1['hit'].astype(float)
            df1 = df1.loc[df1.groupby('contig')['hit'].idxmax()]
            df1['genome'] = genome_name
            df1.to_csv('blast_plasmid_cge_outputpercontig.out', index=False, header=False, sep=' ', mode='a')

print('blast cge genes done')

# Start count genes per contig
for root, dirs, files in os.walk(os.getcwd()):
    filepath = os.path.join(root, 'genes.faa')
    basename = os.path.basename(os.path.dirname(filepath))
    if os.path.isfile(filepath):
        with open(filepath, 'r') as faa_file:
            id = []
            for gene in faa_file:
                if gene.startswith(">"):
                    gene = gene.split(' ')[0]
                    id.append(gene[1:])
            df = pd.DataFrame({'id': id})
            df[['contig', 'gene']] = df['id'].str.split('_', n=1, expand=True)
            df2 = df['contig'].value_counts()
            output_file = os.path.join(root, 'genespercontig.txt')
            with open(output_file, 'w') as out_file:
                df2.to_csv(out_file, sep=' ', index=True, header=False)
print('count genes per contig done')

# Start count SCMs per contig
for root, dirs, files in os.walk(os.getcwd()):
    filepath = os.path.join(root, 'hmmer.analyze.txt')
    basename = os.path.basename(os.path.dirname(filepath))
    if os.path.isfile(filepath):
        with open(filepath, 'r') as scm_file:
            with suppress(ValueError):
                df = pd.read_csv(scm_file, header=None, delim_whitespace=True, usecols=[0], names=['contig_gene'])
                df = df[~df['contig_gene'].str.contains("#")]
                df['contig_gene'] = df['contig_gene'].drop_duplicates()
                df[['contig', 'gene']] = df['contig_gene'].str.split('_', n=1, expand=True)
                df2 = df.groupby(['contig']).size().reset_index(name='counts')
                output_file = os.path.join(root, 'SCMpercontig.txt')
                with open(output_file, 'w') as out_file:
                    df2.to_csv(out_file, sep=' ', index=False, header=False)
print('count SCMs per contig done')

print('Start kmer count')
if args.jelly:
    print('You have selected kmer-counting with jellyfish')
    kmer_dir = 'fasta_split'
    os.mkdir(kmer_dir)
    for fasta_file in glob.glob('*.fasta'):
        basename = os.path.splitext(os.path.basename(fasta_file))[0]
        for record in SeqIO.parse(fasta_file,"fasta"):
            id = record.id
            id_file = basename + '_' + id + '.fasta'
            with open(os.path.join(kmer_dir, id_file), 'w') as out:
                out.write('>'+record.id+'\n'+str(record.seq + 'NN' + record.seq.reverse_complement() + '\n'))
    os.chdir(kmer_dir)
    for split_fasta in glob.glob('*.fasta'):
        basename = os.path.splitext(os.path.basename(split_fasta))[0]
        os.system('cat {} | jellyfish count /dev/fd/0 -m 5 -c 20 -s 1000000 -t 16 -o /dev/fd/1 |jellyfish dump -c -t /dev/fd/0 |while read kmer ; do echo {} $kmer ; done >> ../kmers.out'.format(split_fasta, basename))
    os.chdir("../")
    print('Jellyfish kmer-count done')
if not (args.jelly):
    print('Standard kmer-counting method')
    kmer_dir = 'fasta_split'
    os.mkdir(kmer_dir)

    def count_kmers(read, k):
        counts = defaultdict(list)
        num_kmers = len(read) - k + 1
        for i in range(num_kmers):
            kmer = read[i:i+k]
            if kmer not in counts:
                counts[kmer] = 0
            counts[kmer] += 1
        return(counts)

    for fasta_file in glob.glob('*.fasta'):
        basename = os.path.splitext(os.path.basename(fasta_file))[0]
        with open(fasta_file) as f_fasta:
            for k, g in groupby(f_fasta, lambda x: x.startswith('>')):
                if k:
                    sequence = next(g).strip('>\n')
                else:
                    d1 = list(''.join(line.strip() for line in g))
                    d1 = [item.upper() for item in d1]
                    d2 = ''.join(d1)
                    complement = {'A': 'T', 'C': 'G', 'G': 'C', 'T': 'A', 'N': 'N', 'U': 'N', 'M': 'N', 'R': 'N', 'W': 'N', 'S': 'N', 'Y': 'N', 'K': 'N', 'V': 'N', 'H': 'N', 'D': 'N', 'B': 'N', 'X': 'N'}
                    reverse_complement = ''.join(complement.get(base, base) for base in reversed(d2))
                    d3 = (d2+'NN'+reverse_complement)
                    counting = count_kmers(d3, 5)
                    for item in counting:
                        output = basename, sequence, item, counting[item]
                        with open('kmer.out', 'a') as text_file:
                            text_file.write("%s %s %s %s\n" % output)
    print('Kmer count standard method ready')

print('Count contig length')
for fasta_file in glob.glob('*.fasta'):
    basename = os.path.splitext(os.path.basename(fasta_file))[0]
    with open(fasta_file) as f_fasta:
        for k, g in groupby(f_fasta, lambda x: x.startswith('>')):
            if k:
                sequence = next(g).strip('>\n')
            else:
                d1 = list(''.join(line.strip() for line in g))
                d2 = ''.join(d1)
                data = sum(1 for ch in d2)
                output = basename, sequence, data
                with open('count_contiglength.out', 'a') as out_file:
                    out_file.write("%s %s %s\n" % output)
print('count contig length ; done')

# next step: Work on files in different folders and merge to separate dfs
print('Start merging contig files')

import warnings
warnings.simplefilter(action='ignore', category=pd.errors.PerformanceWarning)

for root, dirs, files in os.walk(os.getcwd()):
    filepath = os.path.join(root, 'genespercontig.txt')
    if os.path.isfile(filepath):
        with open(filepath, 'r') as f1:
            df1 = pd.read_csv(f1, header=None, delim_whitespace=True, names=['contig', 'genes'])
            df1['genome'] = os.path.basename(os.path.dirname(filepath))
    else:
        continue

    filepath = os.path.join(root, 'SCMpercontig.txt')
    if os.path.isfile(filepath):
       	with open(filepath, 'r') as f2:
            df2 = pd.read_csv(f2, header=None, delim_whitespace=True, names=['contig', 'SCM'])
            df2['genome'] = os.path.basename(os.path.dirname(filepath))
    if not os.path.isfile(filepath):
        df2 = df1
        df2 = df2.rename(columns={'genes': 'SCM'})
        df2['SCM'] = np.NaN

    filepath = os.path.join(root, 'plasmiddbgenes_per_contig.txt')
    if os.path.isfile(filepath):
        with open(filepath, 'r') as f3:
            df3 = pd.read_csv(f3, header=None, delim_whitespace=True, names=['contig', 'plasmid_genes'])
            df3['genome'] = os.path.basename(os.path.dirname(filepath))
    if not os.path.isfile(filepath):
        df3 = df1
        df3 = df3.rename(columns={'genes': 'plasmid_genes'})
        df3['plasmid_genes'] = np.NaN

    # merge dataframes for each folder
    df_merge1 = pd.merge(df1, df2, left_on=['genome', 'contig'], right_on=['genome', 'contig'], how='left')
    df_merge2 = pd.merge(df_merge1, df3, on=['genome', 'contig'], how='left')
    df_merge2.to_csv(os.path.join(root,'outputgenesdf.csv'))
print('Create df_files ; done')

# next step: concatenate csv files
dfList = []

for root, dirs, files in os.walk(os.getcwd()):
    filepath = os.path.join(root, 'outputgenesdf.csv')
    if os.path.isfile(filepath):
        with open(filepath, 'r') as fnew:
            frame = pd.read_csv(fnew, converters={'genome': lambda x: str(x)})
            dfList.append(frame)

df1a = pd.concat(dfList)
df1a['contig'] = df1a['contig'].astype(object)

#import contigIDnumbers
df1b = pd.read_csv('contigID.out', header=None, sep='\t', names=['genome', 'contig', 'contigID'])
df1b['contig'] = df1b['contig'].astype(object)
df1 = pd.merge(df1a, df1b, how='right', left_on=['genome','contig'], right_on=['genome','contig'])
df1['contig'] = df1['contig'].astype(int)
df1['source'] = df1.genome.astype(str).str.cat(df1.contig.astype(str), sep='_')
df1 = df1.set_index('source')

print('Start to add blast output to dataframe')

# next step; make dataframe

# import kmers
kmer_file = os.path.join(scriptlocation, "kmer.txt")
df2 = pd.read_csv(kmer_file, delim_whitespace=True, header=None)
# use row as columnheaders
df2.columns = df2.iloc[0]
df2 = df2.loc[:-1]

# samenvoegen dfs
df3 = pd.concat([df1, df2], axis=1)
df3['source'] = df3.genome.astype(str).str.cat(df3.contig.astype(str), sep='_')
df3 = df3.set_index('source')

# import kmers
if args.jelly:
    df4 = pd.read_csv('kmers.out', sep=' ', low_memory=False, header=None, names=['source', 'gene', 'bitscore'])
    df4[['genome', 'contig']] = df4['source'].str.rsplit('_', n=1, expand=True)
if not (args.jelly):
    df4 = pd.read_csv('kmer.out', sep=' ', low_memory=False, header=None, names=['genome', 'contig', 'gene', 'bitscore'])
    df4['source'] = df4.genome.astype(str).str.cat(df4.contig.astype(str), sep='_')

# combine df3 and df4
df5 = df4.pivot_table(index='source', columns='gene', values='bitscore').reindex(index=df3.index, columns=df3.columns).fillna(df3)
df5['genome'] = df5['genome'].astype(object)
df5['contig'] = df5['contig'].astype(object)

# import blastcge_outputpercontig
df5aa = pd.read_csv('blast_plasmid_cge_outputpercontig.out', header=None, delim_whitespace=True, names=["contig", "plasmidcge_id", "genome"])
df5aa['source'] = df5aa.genome.astype(str).str.cat(df5aa.contig.astype(str), sep='_')
df5aa = df5aa.set_index('source')
df5aa['plasmidcge_id'] = df5aa['plasmidcge_id'].astype(object)
df5aa['contig'] = df5aa['contig'].astype(object)
df5aa['genome'] = df5aa['genome'].astype(object)
df5a = pd.merge(df5, df5aa, how='outer')
df5a['source'] = df5a.genome.astype(str).str.cat(df5a.contig.astype(str), sep='_')
df5a['contig'] = df5a['contig'].astype(object)

# import contig length
df5bb = pd.read_csv('count_contiglength.out', header=None, delim_whitespace=True, names=["genome", "contig", "contig_length"])
df5bb['source'] = df5bb.genome.astype(str).str.cat(df5bb.contig.astype(str), sep='_')
df5bb = df5bb.set_index('source')
df5bb['genome'] = df5bb['genome'].astype(object)
df5bb['contig'] = df5bb['contig'].astype(object)
df5bb['contig_length'] = df5bb['contig_length'].astype(object)
df5b = pd.merge(df5a, df5bb, how='outer')
df5b.fillna(int(0), inplace=True)

# add column with kmer_numbers
df5b['kmer_number'] = df5b.contig_length - 4
df5b['kmer_number'] = df5b.kmer_number * 2

# add column with genes/SCM en round to 2 decimals
df5b['SCM_genes'] = df5b['SCM']/df5b['genes']
df5b['SCM_genes'] = df5b['SCM_genes'].fillna(0)

# add column with genes/plasmid_genes en round to 2 decimals
df5b['plasmid_genes_genes'] = df5b['plasmid_genes']/df5b['genes']
df5b['plasmid_genes_genes'] = df5b['plasmid_genes_genes'].fillna(0)

# ID contig column to first position
cols = list(df5b.columns.values)
cols.pop(cols.index('source'))
cols.pop(cols.index('contigID'))
cols.pop(cols.index('contig_length'))
cols.pop(cols.index('kmer_number'))
cols.pop(cols.index('plasmid_genes_genes'))
cols.pop(cols.index('SCM_genes'))
cols.pop(cols.index('contig'))
cols.pop(cols.index('genome'))
cols.pop(cols.index('plasmidcge_id'))
df5b = df5b[['source', 'contigID', 'genome', 'contig', 'contig_length', 'SCM_genes', 'plasmid_genes_genes', 'plasmidcge_id', 'kmer_number']+cols]
df5b.drop('Unnamed: 0', axis=1, inplace=True)

df5da = df5b.loc[:, 'source':'plasmidcge_id']
df5db = df5b.loc[:, 'kmer_number':'TTTTT'].astype(int)

df6 = pd.concat([df5da, df5db], axis=1)

# kmer fraction
df6[['kmer{}'.format(i) for i in range(1, 1+(2002-979)+1)]] = df6.loc[:, 'AAAAA':'TTTTT'].div(df6['kmer_number'], axis=0)
df6.loc[:, 'kmer1':'kmer1024'] = df6.loc[:, 'kmer1':'kmer1024'].applymap('{:.2e}'.format)

# delete some columns
df6.drop(df6.columns.to_series()["AAAAA":"TTTTT"], axis=1, inplace=True)
df6.drop(['contig','genes'], axis=1, inplace=True)

df6.to_csv('outputdataframe.csv', index=False)

print('CSV file from dataframe ready in file outputdataframe.csv')

if args.debug:
    print('debug mode, no cleaning up')
if not (args.debug):
    print('Cleaning-up intermediate files')
    shutil.rmtree(kmer_dir)
    shutil.rmtree('checkm_output')
    for file in glob.glob('*.txt'):
        os.remove(file)
    for file in glob.glob('*.out'):
        os.remove(file)
    for file in glob.glob('*.fasta'):
        os.remove(file)
    os.remove('checkm_output.tsv')

print('Start R')

if args.training:
    print('You have selected training mode')
    trainings_location = os.path.join(scriptlocation, "training.R")
    os.system('R --vanilla < {}'.format(trainings_location))
    print('training done')
if not (args.training):
    print('RFPlasmid prediction mode started')
    classification_location = os.path.join(scriptlocation, "classification.R")
    if args.species == 'Generic':
        species_import = 'Generic'
    os.system('R --vanilla --args {} {} < {}'.format(species_import, scriptlocation, classification_location))
    print('Prediction done')
print('RFPlasmid output can be found in directory %s' %new_dir)

print('If you like this tool, please cite:')
print('van der Graaf-van Bloois, L., Wagenaar, J. A. & Zomer, A. L. RFPlasmid: predicting plasmid sequences from short read assembly data using machine learning. Microb. Genom. 7 (2021), doi.org/10.1099/mgen.0.000683')


import PIL
from PIL import Image
import os
import sqlite3

def drawmap(db, dst_dir):
    org_dir = os.getcwd()
    pic_dir = org_dir + '/pic/'
    mapimg = Image.open(pic_dir + 'map.png')
    #Uk victory
    uksupplyimg = Image.open(pic_dir + 'uk_supply.png')
    if db.execute("select location from card where cardid = 225;").fetchall()[0][0] == "played":
        mapimg.paste(uksupplyimg, (174-14, 130-15), uksupplyimg)
    if db.execute("select location from card where cardid = 226;").fetchall()[0][0] == "played":
        mapimg.paste(uksupplyimg, (649-14, 185-15), uksupplyimg)
    #Fr home/victory
    frhomeimg = Image.open(pic_dir + 'fr_home.png')
    if (db.execute("select location from card where cardid = 222;").fetchall()[0][0] == "played") and (db.execute("select control from space where spaceid = 12;").fetchall()[0][0] == "Axis"):
        mapimg.paste(frhomeimg, (470-14, 172-15), frhomeimg)
    else:
        mapimg.paste(frhomeimg, (503-14, 264-15), frhomeimg)

    if db.execute("select location from card where cardid = 228;").fetchall()[0][0] == "played":
        frsupplyimg = Image.open(pic_dir + 'fr_supply.png')
        mapimg.paste(frsupplyimg, (576-14, 491-15), frsupplyimg)
    #Su home
    if db.execute("select location from card where cardid = 277;").fetchall()[0][0] == "played":
        suhomeimg = Image.open(pic_dir + 'su_home.png')
        sunohomeimg = Image.open(pic_dir + 'su_nohome.png')
        mapimg.paste(suhomeimg, (1002-14, 82-15), suhomeimg)
        mapimg.paste(sunohomeimg, (803-14, 170-15), sunohomeimg)
    #Ch home
    chhomeimg = Image.open(pic_dir + 'ch_home.png')
    if db.execute("select location from card where cardid = 345;").fetchall()[0][0] == "played":
        mapimg.paste(chhomeimg, (1009-14, 311-15), chhomeimg)
    else:
        mapimg.paste(chhomeimg, (1127-14, 316-15), chhomeimg)

    '''if db.execute("select location from card where cardid = 209;").fetchall()[0][0] == "played":
        usvictoryimg = Image.open('us_victory.png')
        usvictoryimg = usvictoryimg.resize((45, 39), Image.ANTIALIAS)
        mapimg.paste(usvictoryimg, (977, 290), usvictoryimg)'''
    geaimg = Image.open(pic_dir + 'ge_army.png')
    jpaimg = Image.open(pic_dir + 'jp_army.png')
    itaimg = Image.open(pic_dir + 'it_army.png')
    ukaimg = Image.open(pic_dir + 'uk_army.png')
    suaimg = Image.open(pic_dir + 'su_army.png')
    usaimg = Image.open(pic_dir + 'us_army.png')
    fraimg = Image.open(pic_dir + 'fr_army.png')
    chaimg = Image.open(pic_dir + 'ch_army.png')
    ukaimg = ukaimg.transpose(Image.FLIP_LEFT_RIGHT)
    suaimg = suaimg.transpose(Image.FLIP_LEFT_RIGHT)
    usaimg = usaimg.transpose(Image.FLIP_LEFT_RIGHT)
    fraimg = fraimg.transpose(Image.FLIP_LEFT_RIGHT)
    chaimg = chaimg.transpose(Image.FLIP_LEFT_RIGHT)
    genimg = Image.open(pic_dir + 'ge_navy.png')
    jpnimg = Image.open(pic_dir + 'jp_navy.png')
    itnimg = Image.open(pic_dir + 'it_navy.png')
    uknimg = Image.open(pic_dir + 'uk_navy.png')
    sunimg = Image.open(pic_dir + 'su_navy.png')
    usnimg = Image.open(pic_dir + 'us_navy.png')
    frnimg = Image.open(pic_dir + 'fr_navy.png')
    uknimg = uknimg.transpose(Image.FLIP_LEFT_RIGHT)
    sunimg = sunimg.transpose(Image.FLIP_LEFT_RIGHT)
    usnimg = usnimg.transpose(Image.FLIP_LEFT_RIGHT)
    frnimg = frnimg.transpose(Image.FLIP_LEFT_RIGHT)
    gefimg = Image.open(pic_dir + 'ge_air.png')
    jpfimg = Image.open(pic_dir + 'jp_air.png')
    itfimg = Image.open(pic_dir + 'it_air.png')
    ukfimg = Image.open(pic_dir + 'uk_air.png')
    sufimg = Image.open(pic_dir + 'su_air.png')
    usfimg = Image.open(pic_dir + 'us_air.png')
    frfimg = Image.open(pic_dir + 'fr_air.png')
    chfimg = Image.open(pic_dir + 'ch_air.png')
    gefimg = gefimg.rotate(-45)
    jpfimg = jpfimg.rotate(-45)
    itfimg = itfimg.rotate(-45)
    ukfimg = ukfimg.rotate(-45)
    sufimg = sufimg.rotate(-45)
    usfimg = usfimg.rotate(-45)
    frfimg = frfimg.rotate(-45)
    chfimg = chfimg.rotate(-45)
    width = gefimg.size[0]
    height = gefimg.size[1]
    gefimg = gefimg.resize((int(width*2/3), int(height*2/3)), Image.ANTIALIAS)
    jpfimg = jpfimg.resize((int(width*2/3), int(height*2/3)), Image.ANTIALIAS)
    itfimg = itfimg.resize((int(width*2/3), int(height*2/3)), Image.ANTIALIAS)
    ukfimg = ukfimg.resize((int(width*2/3), int(height*2/3)), Image.ANTIALIAS)
    sufimg = sufimg.resize((int(width*2/3), int(height*2/3)), Image.ANTIALIAS)
    usfimg = usfimg.resize((int(width*2/3), int(height*2/3)), Image.ANTIALIAS)
    frfimg = frfimg.resize((int(width*2/3), int(height*2/3)), Image.ANTIALIAS)
    chfimg = chfimg.resize((int(width*2/3), int(height*2/3)), Image.ANTIALIAS)
    ukfimg = ukfimg.transpose(Image.FLIP_LEFT_RIGHT)
    sufimg = sufimg.transpose(Image.FLIP_LEFT_RIGHT)
    usfimg = usfimg.transpose(Image.FLIP_LEFT_RIGHT)
    frfimg = frfimg.transpose(Image.FLIP_LEFT_RIGHT)
    chfimg = chfimg.transpose(Image.FLIP_LEFT_RIGHT)
    army = {'ge':geaimg,'jp':jpaimg,'it':itaimg,'uk':ukaimg,'su':suaimg,'us':usaimg,'fr':fraimg,'ch':chaimg}
    navy = {'ge':genimg,'jp':jpnimg,'it':itnimg,'uk':uknimg,'su':sunimg,'us':usnimg,'fr':frnimg}
    air_force = {'ge':gefimg,'jp':jpfimg,'it':itfimg,'uk':ukfimg,'su':sufimg,'us':usfimg,'fr':frfimg,'ch':chfimg}
    land_list = db.execute("select distinct location from piece where type = 'army' and location != 'none';").fetchall()
    sea_list = db.execute("select distinct location from piece where type = 'navy' and location != 'none';").fetchall()
    air_list = db.execute("select distinct location from piece where type = 'air' and location != 'none';").fetchall()
    for land in land_list:
        piece_list = db.execute("select control from piece where type = 'army' and location = :space and control not in (select control from piece where type = 'air' and location = :space);", {'space':land[0]}).fetchall()
        posx = db.execute("select distinct posx from space where spaceid = :space;", {'space':land[0]}).fetchall()[0][0]-27
        posy = db.execute("select distinct posy from space where spaceid = :space;", {'space':land[0]}).fetchall()[0][0]-16
        for piece in piece_list:
            mapimg.paste(army[piece[0]], (posx, posy), army[piece[0]])
            posy -= 20
        if land in air_list:
            piece_list = db.execute("select control from piece where type = 'air' and location = :space;", {'space':land[0]}).fetchall()
            posx = db.execute("select distinct posx from space where spaceid = :space;", {'space':land[0]}).fetchall()[0][0]-20
            for piece in piece_list:
                mapimg.paste(air_force[piece[0]], (posx, posy), air_force[piece[0]])
                posy -= 20
    for sea in sea_list:
        piece_list = db.execute("select control from piece where type = 'navy' and location = :space and control not in (select control from piece where type = 'air' and location = :space);", {'space':sea[0]}).fetchall()
        posx = db.execute("select distinct posx from space where spaceid = :space;", {'space':sea[0]}).fetchall()[0][0]-35
        posy = db.execute("select distinct posy from space where spaceid = :space;", {'space':sea[0]}).fetchall()[0][0]-16
        for piece in piece_list:
            mapimg.paste(navy[piece[0]], (posx, posy), navy[piece[0]])
            posy += 20
        if sea in air_list:
            piece_list = db.execute("select control from piece where type = 'air' and location = :space;", {'space':sea[0]}).fetchall()
            posx = db.execute("select distinct posx from space where spaceid = :space;", {'space':sea[0]}).fetchall()[0][0]-20
            for piece in piece_list:
                mapimg.paste(air_force[piece[0]], (posx, posy), air_force[piece[0]])
                posy += 20

    pos = {'x':120, 'y':780}
    for country in ['ge', 'jp', 'it', 'uk', 'su', 'us', 'fr', 'ch']:
        remain_army_count = db.execute("select count(*) from piece where control = :country and type = 'army' and location = 'none';", {'country':country}).fetchall()[0][0]
        remain_navy_count = db.execute("select count(*) from piece where control = :country and type = 'navy' and location = 'none';", {'country':country}).fetchall()[0][0]
        remain_air_count = db.execute("select count(*) from piece where control = :country and type = 'air' and location = 'none';", {'country':country}).fetchall()[0][0]
        for i in range(remain_army_count):
            mapimg.paste(army[country].resize((int(width*1/2), int(height*1/2)), Image.ANTIALIAS), (pos['x'], pos['y']), army[country].resize((int(width*1/2), int(height*1/2)), Image.ANTIALIAS))
            pos['y'] -= 15
        for i in range(remain_navy_count):
            mapimg.paste(navy[country].resize((int(width*1/2), int(height*1/2)), Image.ANTIALIAS), (pos['x'], pos['y']), navy[country].resize((int(width*1/2), int(height*1/2)), Image.ANTIALIAS))
            pos['y'] -= 15
        for i in range(remain_air_count):
            mapimg.paste(air_force[country].resize((int(width*1/2), int(height*1/2)), Image.ANTIALIAS), (pos['x'], pos['y']), air_force[country].resize((int(width*1/2), int(height*1/2)), Image.ANTIALIAS))
            pos['y'] -= 15
        pos['x'] += 30
        pos['y'] = 780

    mapimg.save(dst_dir + "/tmp.jpg", format="JPEG")