# -*- coding: utf-8 -*-
#########################################################
# python
import os
import traceback
import time
import threading
import json
import datetime
import re
import requests

# third-party
from sqlalchemy import desc
from sqlalchemy import or_, and_, func, not_
from sqlalchemy.sql.expression import null

# sjva 공용
from framework import db, scheduler, path_app_root, SystemModelSetting, celery, app, Util
from framework.job import Job
from framework.common.rss import RssUtil
import framework.common.celery as celery_task

# 패키지
from .plugin import logger, package_name
from .model import ModelSetting, ModelOffcloud2Account, ModelOffcloud2Job,  ModelOffcloud2Item, ModelOffcloud2Cache
from .offcloud_api import Offcloud

#########################################################

class LogicRss(object):

    @staticmethod
    def process_insert_feed():
        try:
            job_list = ModelOffcloud2Job.get_list()
            for job in job_list:
                try:
                    logger.debug('Offcloud job:%s', job.id)
                    feed_list = RssUtil.get_rss(job.rss_url)
                    if not feed_list:
                        continue
                    flag_commit = False
                    count = 0
                    #
                    try:
                        values = [x.strip() for x in job.rss_regex.split('\n')]
                        regex_list = Util.get_list_except_empty(values)
                    except:
                        regex_list = []
                    #logger.warning(regex_list)
                    #logger.warning(job.rss_mode)
                    for feed in reversed(feed_list):
                        if db.session.query(ModelOffcloud2Item).filter_by(job_id=job.id, link=feed.link).first() is None:
                            # 2021-05-21
                            if job.rss_mode: #화이트리스트
                                flag_append = False
                                try:
                                    for regex in regex_list:
                                        if re.compile(regex).search(feed.title):
                                            flag_append = True
                                            break
                                except Exception as e:
                                    logger.error(e)
                                    logger.error(traceback.format_exc())
                                if flag_append == False:
                                    continue
                            else: #블랙리스트
                                flag_append = True
                                try:
                                    for regex in regex_list:
                                        if re.compile(regex).search(feed.title):
                                            flag_append = False
                                            break
                                except Exception as e:
                                    logger.error(e)
                                    logger.error(traceback.format_exc())
                            if flag_append == False:
                                continue

                            r = ModelOffcloud2Item()
                            r.title = u'%s' % feed.title
                            r.link = feed.link
                            #db.session.add(r)
                            job.rss_list.append(r)
                            flag_commit = True
                            count += 1
                    if flag_commit:
                        db.session.commit()
                    logger.debug('Offcloud job:%s flag_commit:%s count:%s', job.id, flag_commit, count)
                except Exception as e:
                    logger.error(e)
                    logger.error(traceback.format_exc())
        except Exception as e:
            logger.error(e)
            logger.error(traceback.format_exc())

    # 캐쉬 상태를 확인하는 리퀘스트
    @staticmethod
    def process_cached_list(rss_list):
        magnet_list = []
        for r in rss_list:
            if r.link.startswith('magnet'):# and r.oc_cached is not True:
                try:
                    magnet_list.append(r.link[20:60])
                except:
                    logger.error(e)
                    logger.error(traceback.format_exc())
        cached_list = Offcloud.get_cache_list(ModelSetting.get('apikey'), magnet_list)
        return cached_list

    # Cache 확인되고 다운로드 요청한 피드 처리
    @staticmethod
    def process_cached_feed(feed):
        try:
            # 이미 봇으로 받았던거면 패스
            entity = ModelOffcloud2Cache.get_by_magnet(feed.link)
            if entity is not None:
                return
            if feed.link_to_notify_status is not None and feed.link_to_notify_status == '1':
                return
            # sjva server에게만 알리는 것으로 변경. 서버가 대신 뿌림
            telegram = {
                'title' : feed.title,
                'magnet' : feed.link,
                'who' : SystemModelSetting.get('id')
            }
            telegram_text = json.dumps(telegram, indent=2)
            try:
                import requests
                sjva_server_url = 'https://server.sjva.me/ss/api/off_cache2'
                data = {'data':telegram_text}
                res = requests.post(sjva_server_url, data=data)
                tmp = res.text
                feed.link_to_notify_status = '1'
                db.session.add(feed)
                db.session.commit()
                if res.text == 'append':
                    return True
                elif res.text == 'exist':
                    return False
            except Exception as e:
                logger.error('Exception:%s', e)
                logger.error(traceback.format_exc())
            return True
        except Exception as e:
            logger.error(e)
            logger.error(traceback.format_exc())

    @staticmethod
    def scheduler_function():
        try:
            if app.config['config']['use_celery']:
                result = LogicRss.scheduler_function2.apply_async()
                result.get()
            else:
                result = LogicRss.scheduler_function2()
        except Exception as e:
            logger.error('Exception:%s', e)
            logger.error(traceback.format_exc())

    @staticmethod
    @celery.task
    def scheduler_function2():
        # LogicRss.additional()
        if ModelSetting.get_bool('dedupe_on_remote'):
            LogicRss.scheduler_function_remove_duplicated_job('remote')
        if ModelSetting.get_bool('dedupe_on_cloud'):
            LogicRss.scheduler_function_remove_duplicated_job('cloud')
        LogicRss.scheduler_function_rss_request()
        LogicRss.scheduler_function_tracer()
        if ModelSetting.get_bool('remove_history_on_web'):
            LogicRss.scheduler_function_remove_history()
        if ModelSetting.get_bool('remove_cloud_history_on_web'):
            LogicRss.scheduler_function_remove_cloud_history('cloud')

    # status
    # 0 : 초기 값
    # 1 : 마그넷. 캐쉬. 오버
    # 2 : 마그넷. 노캐쉬. 오버
    # 3 : 일반파일. 오버
    # 4 : 수동요청. 오버
    # 6 : 마그넷. 캐쉬. 요청 성공
    # 7 : 마그넷. 노캐쉬. 요청 성공
    # 8 : 일반파일. 요청 성공
    # 9 : 수동요청 성공
    # 11 : 완료
    # 12 : job 모드 캐시확인만. 마그넷. 캐시확인 완료.
    # 13 : error
    # 14 : NOSTATUS
    # 15 : Cloud로 추가 완료

    @staticmethod
    def scheduler_function_remove_history():
        try:
            apikey = ModelSetting.get('apikey')
            # cloud_history, history_status, requestIds, removeList = Offcloud.get_history(apikey, target)

            remote_history = requests.get("https://offcloud.com/api/remote/history?apikey=" + apikey)
            remote_history = remote_history.json()
            #logger.debug("===================== offcloud 작업 json 임포트 완료 ")

            for remote_item in remote_history:
                remote_magnet = str(remote_item.get('originalLink'))
                query = db.session.query(ModelOffcloud2Item) \
                    .filter(ModelOffcloud2Item.link.like(remote_magnet))
                    #.filter(ModelOffcloud2Item.oc_status == 'downloaded' ) \
                items = query.all()

                if items:
                    for idx, feed in enumerate(items):
                        if feed.oc_status != 'downloaded':#offcloud 에서 완료된 아이템 삭제전 DB에 downloaded 상태로 업데이트
                            Offcloud.refresh_status(apikey, feed)

                        if feed.oc_status == 'downloaded':
                            remote_remove_req = "https://offcloud.com/remote/remove/" + str(remote_item.get('requestId')) + "?apikey=" + apikey
                            # logger.debug("================ 마그넷 링크 매치됨, 리모트 작업 삭제 리퀘스트 전송")
                            # logger.debug('remote_remove_req : %s', remote_remove_req)
                            remote_remove_req_result = requests.get(remote_remove_req)
                            remote_remove_req_result = remote_remove_req_result.json()
                            if remote_remove_req_result.get('success'):
                                remote_remove_req_result = "offcloud 완료 | " + str(feed.title) + " | " + str(feed.link) + " | " + str(feed.oc_requestId) + " | " + str(remote_remove_req) + " | 결과: " + str(remote_remove_req_result)
                                logger.debug(remote_remove_req_result)

        except Exception as e:
            logger.error(e)
            logger.error(traceback.format_exc())

    @staticmethod
    def scheduler_function_remove_cloud_history(target):
        try:
            apikey = ModelSetting.get('apikey')
            # cloud_history, history_status, requestIds, removeList, errorList = Offcloud.get_history(apikey, target)
            history_status = Offcloud.get_history(apikey, target)
            history_status = history_status['history_status']

            for cloud_item in history_status:
                cloud_magnet = str(cloud_item.get('originalLink'))
                query = db.session.query(ModelOffcloud2Item) \
                    .filter( or_(ModelOffcloud2Item.oc_status == 'downloaded' , ModelOffcloud2Item.oc_status == 'uploading' , ModelOffcloud2Item.oc_status == 'NOSTATUS' )) \
                    .filter(ModelOffcloud2Item.oc_cached == True ) \
                    .filter(ModelOffcloud2Item.link.like(cloud_magnet))
                items = query.all()

                if items:
                    for idx, feed in enumerate(items):
                        cloud_remove_req_result = Offcloud.remove(apikey, target, cloud_item.get('requestId'))
                        cloud_remove_req_result = str(target) + " history 삭제 | " + str(feed.title) + " | " + str(feed.link) + " | " + str(feed.oc_requestId) + " | 결과: " + str(cloud_remove_req_result)
                        logger.debug(cloud_remove_req_result)

        except Exception as e:
            logger.error(e)
            logger.error(traceback.format_exc())

    @staticmethod
    def scheduler_function_remove_duplicated_job(target):

        try:
            apikey = ModelSetting.get('apikey')
            removeList = Offcloud.get_history(apikey, target)
            removeList = removeList['removeList']

            if len(removeList) == 0:
                # logger.debug('Nothing to dedupe on ' + target + ' ============================================')
                return

            result = Offcloud.remove(apikey, target, removeList)
            logger.debug(result)
            logger.debug('dedupe on ' + target + 'end ============================================')

        except Exception as e:
            logger.error(e)
            logger.error(traceback.format_exc())

    @staticmethod
    def scheduler_function_extra_request():
        # cloud에서 완료되면 캐쉬 체크 기간을 무시하고 remote에 추가
        try:
            apikey = ModelSetting.get('apikey')
            cloud_history = requests.get("https://offcloud.com/api/" + "cloud" + "/history?apikey=" + apikey)
            cloud_history = cloud_history.json()
            uniqueList = []
            dupeList = []
            dupe_remove_req = []

            logger.debug(("https://offcloud.com/api/" + target + "/history?apikey=" + apikey))
            logger.debug(cloud_history)

            for cloud_item in cloud_history:
                logger.debug(cloud_item.get('originalLink'))
                if cloud_item.get('originalLink') not in uniqueList:
                    uniqueList.append(cloud_item.get('originalLink'))
                else:
                    if cloud_item.get('fileNmae') is None or cloud_item.get('status') == 'created':
                        dupeList.append(cloud_item.get('originalLink'))
                        dupe_remove_req.append("https://offcloud.com/" + target + "/remove/" + str(cloud_item.get('requestId')) + "?apikey=" + apikey)
                        logger.debug(dupe_remove_req)

            for req in dupe_remove_req:
                requests.get(req)
                logger.debug(req)

            logger.debug('end========================================================')

        except Exception as e:
            logger.error(e)
            logger.error(traceback.format_exc())

    @staticmethod
    def scheduler_function_rss_request():
        logger.debug('1. RSS to DB')
        LogicRss.process_insert_feed()

        try:
            over_flag = False
            apikey = ModelSetting.get('apikey')
            job_list = ModelOffcloud2Job.get_list()
            # cloud_history = Offcloud.get_history(apikey, 'cloud')
            # cloud_history = cloud_history['history_status']
            # remote_history = Offcloud.get_history(apikey, 'remote')
            # remote_history = remote_history['history_status']

            for job in job_list:
                # logger.debug('============ 클라우드로 추가 기능 테스트 %s', job.add_to_cloud)
                # logger.debug('============ 클라우드로 추가 기능 테스트 %s', type(job.add_to_cloud))
                account = ModelOffcloud2Account.get(job.username)
                rss_list = ModelOffcloud2Item.get_rss_list_by_scheduler(job)
                cached_list = LogicRss.process_cached_list(rss_list)
                logger.debug('2. job name:%s count:%s, cache count:%s', job.name, len(rss_list), len(cached_list))

                i = 0 # 계정 분산처리를 위한 인덱스
                for feed in rss_list:
                    try:
                        i = i + 1
                        if job.username2:
                            # logger.debug('======= 계정 분산처리 =======')
                            # account2 = ModelOffcloud2Account.get(job.username2)
                            account2 = [x.strip().replace(' ', '').strip() for x in job.username2.replace('\n', '||').split('||')]
                            account2 = Util.get_list_except_empty(account2)
                            ii = i % len(account2)
                            account = ModelOffcloud2Account.get(account2[ii])
                        # 요청 안한 것들. 6미만은 요청안 한 것, 15는 cloud로 추가기능을 위해 새로 추가함
                        #  15는 캐쉬 생성을 위해 cloud로만 추가한 상태이므로 다운로드 요청상태가 아님
                        if feed.status < 6 or feed.status == 15:
                            feed.oc_folderid = job.folderid
                            if feed.link.startswith('magnet'):
                                if feed.link[20:60] in cached_list:
                                # 현재 아이템의 캐쉬가 있으면
                                    LogicRss.process_cached_feed(feed)
                                    feed.oc_cached = True

                                    if job.mode == '0' or job.mode == '1':
                                        if over_flag:
                                            feed.status = 1
                                        else:
                                            feed.remote_time = datetime.datetime.now()
                                            ret = Offcloud.add_remote(apikey, feed, account.option_id)
                                            if feed.job.use_tracer:
                                                feed.make_torrent_info()
                                            #logger.debubg("요청 : %s", feed.title)
                                            if ret == 'over':
                                                over_flag = True
                                                feed.status = 1
                                            else:
                                                feed.status = 6
                                    elif job.mode == '2': #Cache 확인만
                                        feed.status = 12
                                else:
                                    # Cache 안되어 있을때
                                    if job.mode == '1': # Cache 안되어 있어도 받는 모드
                                        if over_flag:
                                            feed.status = 2
                                        else:
                                            feed.remote_time = datetime.datetime.now()
                                            ret = Offcloud.add_remote(apikey, feed, account.option_id)
                                            if feed.job.use_tracer:
                                                feed.make_torrent_info()
                                            if ret == 'over':
                                                over_flag = True
                                                feed.status = 2
                                            else:
                                                feed.status = 7

                                    # Cache가 없는 feed를 cloud로 추가
                                    try:
                                        if feed.status < 6 and feed.status > -1:
                                            if job.add_to_cloud is not None and isinstance(job.add_to_cloud, int):
                                                if datetime.datetime.now() > feed.created_time + datetime.timedelta(hours=int(job.add_to_cloud)):
                                                    # logger.debug('============ 피드 생성시간 %s', feed.created_time)
                                                    # logger.debug('============ 피드 생성시간 + 지연시간 %s', feed.created_time + datetime.timedelta(hours=job.add_to_cloud))
                                                    res_add_to_cloud = "https://offcloud.com/api/cloud?apikey=" + apikey + "&url=" + feed.link
                                                    res_add_to_cloud = requests.get(res_add_to_cloud)
                                                    # "https://offcloud.com/api/cloud?apikey=Q8wFNqlCWGjNEB2xicIb8RpiIPRONfSR&url={{url}}"
                                                    logger.debug('Cloud로 추가: %s %s', res_add_to_cloud, feed.link)
                                                    if 'success' in res_add_to_cloud.json():
                                                        logger.debug(res_add_to_cloud.json())
                                                        logger.debug(datetime.datetime.now() + datetime.timedelta(hours=job.add_to_cloud))
                                                        feed.status = -1 # Cloud로 추가 완료
                                                    elif 'not_available' in res_add_to_cloud.json():
                                                        logger.debug('Cloud로 추가 실패')

                                    except Exception as e:
                                        logger.error('Exception:%s', e)
                                        logger.error(traceback.format_exc())

                            elif feed.link.startswith('http'):
                                if ModelSetting.get_bool('request_http_start_link'):
                                    if not feed.link.endswith('=.torrent'):
                                        feed.remote_time = datetime.datetime.now()
                                        ret = Offcloud.add_remote(apikey, feed, account.option_id)
                                        if ret == 'over':
                                            over_flag = True
                                            feed.status = 3
                                        else:
                                            feed.status = 8
                        else:
                            if feed.oc_status == 'created' or feed.oc_status == 'uploading' or feed.oc_status == 'downloading':
                                Offcloud.refresh_status(apikey, feed)

                            if feed.oc_status == 'downloaded':
                                feed.status = 11
                                feed.completed_time = datetime.datetime.now()
                            if feed.oc_status == 'error':
                                feed.status = 13
                            if feed.oc_status == 'NOSTATUS':
                                feed.status = 14

                    except Exception as e:
                        logger.error(e)
                        logger.error(traceback.format_exc())
                    finally:
                        db.session.add(feed)
            db.session.commit()
        except Exception as e:
            logger.error(e)
            logger.error(traceback.format_exc())
        finally:
            logger.debug('==================================')

    '''
    1. 실패된 작업 삭제/개별 리스트를 만들어 관리
        중복작업 삭제
        완료나 실패된 작업 일정시간 지난뒤 강제 삭제
    2. 일정 수준 이상 다운시 클라우드에서 리모트로 미리 이동 - 클라우드 용량 full 방지
    3. cloud에서 완료됐지만 DB에 없는 작업 자동 분류 regex 이용
    4. cloud에서 완료 됐지만 캐쉬 확인기간이 지나서 remote로 추가하지 않는 경우 강제로 추가
    5. RSS수신시 일정시간 지연후 cloud로 먼저 추가 - 바로추가도 가능
        x시간 이상 지난 작업을 cloud로 추가하는 용도로도 쓰일 수 있음
    6. sjva에 의해 추가된 작업이 아니면 requestId등 정보가 DB에 없기 때문에 sjva가 관리를 하지 못하므로 DB에 업데이트
    7. 캐쉬 수신시 캐쉬 확인 기간이 지난 건도 추가
    8. 작업추가시 이전에 추가 한적 있는지 검사 후 추가
        검사후 작업이 존재하면 중복으로 요청하지 않도로 status 업데이트
    9. 작업추가시 현재 중복 작업이 있는지 검사 후 추가
    10.
    '''
    @staticmethod
    def additional():
        try:
            apikey = ModelSetting.get('apikey')
            target = 'cloud'
            history = Offcloud.get_history(apikey, target)
            # errorList = errorList['errorList']

            # 실패한 작업 삭제
            for item in history['errorList']:
                result = Offcloud.remove(apikey, target, item)
                logger.debug('removed - requestId: %s === %s', result, item)
                # logger.debug('remove error item on ' + target + 'end ============================================')

            # 완료된 작업 강제 삭제
            for item in history['history_status']:
                if item['status'] == 'downloaded':
                    result = Offcloud.remove(apikey, target, item)
                    logger.debug('removed - requestId: %s === %s', result, item)
                    # logger.debug('remove error item on ' + target + 'end ============================================')

        except Exception as e:
            logger.debug('Exception:%s', e)
            logger.debug(traceback.format_exc())

    @staticmethod
    def add_remote(req):
        try:
            rss_id = req.form['id']
            apikey = db.session.query(ModelSetting).filter_by(key='apikey').first().value
            feed = db.session.query(ModelOffcloud2Item).filter_by(id=rss_id).with_for_update().first()
            account = ModelOffcloud2Account.get(feed.job.username)

            feed.remote_time = datetime.datetime.now()
            ret = Offcloud.add_remote(apikey, feed, account.option_id)
            if feed.job.use_tracer:
                feed.make_torrent_info()
            if ret == 'over':
                feed.status = 4
            else:
                feed.status = 9
            db.session.commit()
            return True
        except Exception as e:
            logger.debug('Exception:%s', e)
            logger.debug(traceback.format_exc())
            return False

    @staticmethod
    def scheduler_function_tracer():
        try:
            job_list = ModelOffcloud2Job.get_list()
            for job in job_list:
                if not job.use_tracer:
                    continue

                # 토렌트 인포가 실패할수도 있고, 중간에 추가된 경우도 있기 때문에...
                query = db.session.query(ModelOffcloud2Item) \
                    .filter(ModelOffcloud2Item.job_id == job.id ) \
                    .filter(ModelOffcloud2Item.oc_status != '' ) \
                    .filter(ModelOffcloud2Item.created_time > datetime.datetime.now() + datetime.timedelta(days=ModelSetting.get_int('tracer_max_day')*-1)) \
                    .filter(ModelOffcloud2Item.torrent_info == None) \
                    .filter(ModelOffcloud2Item.link.like('magnet%'))
                items = query.all()
                if items:
                    for idx, feed in enumerate(items):
                        if feed.make_torrent_info():
                            db.session.add(feed)

                            db.session.commit()
                        #logger.debug('%s/%s %s', idx, len(items), feed.title)
                #######################################################

                lists = os.listdir(job.mount_path)
                for target in lists:
                    try:
                        #logger.debug(target)
                        if target == 'SJVA':
                            continue
                        fullpath = os.path.join(job.mount_path, target)

                        # 자막파일은 바로 이동
                        if os.path.splitext(target.lower())[1] in ['.smi', '.srt', 'ass']:
                            celery_task.move_exist_remove(fullpath, job.move_path, run_in_celery=True)
                            continue
                        if os.path.splitext(target.lower())[1] == '.aria2__temp':
                            target_folder = os.path.join(job.mount_path, 'SJVA', u'기타')
                            if not os.path.exists(target_folder):
                                os.makedirs(target_folder)
                            celery_task.move_exist_remove(fullpath, target_folder, run_in_celery=True)
                            continue

                        if os.path.splitext(target.lower())[1] == '.torrent':
                            target_folder = os.path.join(job.mount_path, 'SJVA', u'torrent')
                            if not os.path.exists(target_folder):
                                os.makedirs(target_folder)
                            celery_task.move_exist_remove(fullpath, target_folder, run_in_celery=True)
                            continue

                        # 해쉬 변경
                        match = re.match(r'\w{40}', target)
                        if match:
                            feeds = db.session.query(ModelOffcloud2Item).filter(ModelOffcloud2Item.link.like('%' + target)).all()
                            if len(feeds) == 1:
                                #logger.debug(feeds[0].dirname)
                                #logger.debug(len(feeds[0].dirname))
                                #logger.debug(feeds[0].filename)

                                if feeds[0].dirname != '':
                                    new_fullpath = os.path.join(job.mount_path, feeds[0].dirname)
                                else:
                                    new_fullpath = os.path.join(job.mount_path, feeds[0].filename)
                                if not os.path.exists(new_fullpath):
                                    celery_task.move(fullpath, new_fullpath, run_in_celery=True)
                                    #logger.debug('Hash %s %s', fullpath, new_fullpath)
                                    fullpath = new_fullpath
                                    target = os.path.basename(new_fullpath)
                                else:
                                    logger.debug('HASH NOT MOVED!!!!!!!')

                        if os.path.isdir(fullpath):
                            #feeds = db.session.query(ModelOffcloud2Item).filter(ModelOffcloud2Item.dirname == target).all()
                            feeds = db.session.query(ModelOffcloud2Item).filter(ModelOffcloud2Item.dirname.like(target+'%')).all()
                        else:
                            feeds = db.session.query(ModelOffcloud2Item).filter(ModelOffcloud2Item.filename == target).all()
                        logger.debug('Feeds count : %s, %s, %s', len(feeds), os.path.isdir(fullpath), target)

                        # 이규연의 스포트라이트 _신천지 위장단체와 정치_.E237.200319.720p-NEXT
                        # 이규연의 스포트라이트 (신천지 위장단체와 정치).E237.200319.720p-NEXT.mp4
                        # 특수문자를 _으로 변경하는 경우 있음. 일단.. 파일만
                        if len(feeds) == 0:

                            if os.path.isdir(fullpath):
                                pass
                            else:
                                query = db.session.query(ModelOffcloud2Item)
                                for t in target.split('_'):
                                    query = query.filter(ModelOffcloud2Item.filename.like('%'+t+'%' ))
                                feeds = query.all()
                                if len(feeds) == 1:
                                    #rename
                                    new_fullpath = os.path.join(job.mount_path, feeds[0].filename)
                                    celery_task.move_exist_remove(fullpath, new_fullpath, run_in_celery=True)
                                    fullpath = new_fullpath
                                #else:
                                #    logger.debug('EEEEEEEEEEEEEEEEEEEEEEE')

                        for feed in feeds:
                            #logger.debug('제목 : %s, %s', feed.title, feed.filecount)
                            flag = True
                            for tmp in feed.torrent_info['files']:
                                #logger.debug('PATH : %s', tmp['path'])
                                #logger.debug(os.path.split(tmp['path']))
                                if os.path.split(tmp['path'])[0] != '':
                                    tmp2 = os.path.join(job.mount_path, os.path.sep.join(os.path.split(tmp['path'])))
                                else:
                                    tmp2 = os.path.join(job.mount_path, tmp['path'])
                                #logger.debug('변환 : %s', tmp2)
                                #if os.path.exists(tmp2):
                                #    logger.debug('File Exist : True')
                                #else:
                                #    logger.debug('파일 없음!!')
                                #    flag = False
                                #    break
                                if not os.path.exists(tmp2):
                                    logger.debug('NOT FIND :%s', tmp2)
                                    flag = False
                                    break

                            #2020-06-26
                            #생성이 추적기간 끝나면 이동
                            if flag == False:
                                try:
                                    ctime = int(os.path.getctime(fullpath))
                                    delta = datetime.datetime.now() - datetime.datetime.fromtimestamp(ctime)
                                    if delta.days >= ModelSetting.get_int('tracer_max_day'):
                                        flag = True
                                        logger.debug('TRACER_MAX_DAY OVER')
                                except Exception as e:
                                    logger.error('Exception:%s', e)
                                    logger.error(traceback.format_exc())

                            if flag:
                                dest_fullpath = os.path.join(job.move_path, target)
                                if os.path.exists(dest_fullpath):
                                    dup_folder = os.path.join(job.mount_path, 'SJVA', u'중복')
                                    if not os.path.exists(dup_folder):
                                        os.makedirs(dup_folder)
                                    dest_folder = dup_folder
                                else:
                                    dest_folder = job.move_path
                                #logger.debug('이동 전: %s' % fullpath)
                                celery_task.move_exist_remove(fullpath, dest_folder, run_in_celery=True)
                                logger.debug('이동 완료: %s, %s' % (fullpath, dest_folder))
                            #else:
                            #    logger.debug('대기 : %s' % fullpath)
                    except Exception as e:
                        logger.error('Exception:%s', e)
                        logger.error(traceback.format_exc())

        except Exception as e:
            logger.error('Exception:%s', e)
            logger.error(traceback.format_exc())
            return False


import unittest
import zencad

class Ops3dProbe(unittest.TestCase):
    def setUp(self):
        zencad.lazy.encache = False
        zencad.lazy.decache = False
        zencad.lazy.fastdo = True

    def test_linear_extrude(self):
        proto = zencad.ngon(r=3, n=12)
        zencad.linear_extrude(shp=proto, vec=3)
        zencad.linear_extrude(shp=proto, vec=(3, 1, 3))
        zencad.linear_extrude(proto, 3)
        zencad.linear_extrude(proto, (3, 1, 3))

    def test_pipe(self):
        proto = zencad.circle(20)
        path = zencad.interpolate([(0, 0, 0), (0, 0, 10), (0, 10, 20)])
        zencad.pipe(proto, path)
        zencad.pipe(shp=proto, spine=path)

    def test_pipe_shell(self):
        proto0 = zencad.circle(20, wire=True)
        proto1 = zencad.circle(30, wire=True).up(10)
        proto2 = zencad.circle(30, wire=True).up(20)
        path = zencad.interpolate([(0, 0, 0), (0, 0, 10), (0, 10, 20)])
        zencad.pipe_shell([proto0, proto1, proto2], path)
        zencad.pipe_shell(arr=[proto0, proto1, proto2], spine=path)

    # def test_sweep(self):
    #    proto = zencad.circle(20, wire=True)
    #    path = zencad.interpolate([(0, 0, 0), (0, 0, 10), (0, 10, 20)])
    #    zencad.sweep(proto, path)
    #    zencad.sweep(proto=proto, path=path)

    def test_loft(self):
        arr = [
            zencad.circle(20, wire=True),
            zencad.circle(20, wire=True).up(10),
            zencad.square(20, wire=True, center=True).up(20),
        ]
        zencad.loft(arr)
        zencad.loft(arr, True)
        zencad.loft(arr=arr, smooth=True)

    def test_revol(self):
        zencad.revol(zencad.ngon(r=10, n=10).rotateX(zencad.deg(90)).right(30))
        zencad.revol(
            zencad.ngon(r=10, n=10).rotateX(zencad.deg(90)).right(30),
            yaw=zencad.deg(120),
        )

    def test_thinksolid(self):
        zencad.thicksolid(zencad.box(10), -1, [(5, 0, 5)])
        zencad.thicksolid(proto=zencad.box(10), refs=[(5, 0, 5)], t=-1)
        zencad.thicksolid(zencad.box(10), 1, [(5, 0, 5)])
        zencad.thicksolid(proto=zencad.box(10), refs=[(5, 0, 5)], t=1)

    def test_fillet(self):
        zencad.box(20).fillet(1)
        zencad.box(20).fillet(r=1)
        zencad.fillet(shp=zencad.box(20), r=1)

        zencad.box(20).fillet(1, [(5, 0, 0)])
        zencad.box(20).fillet(refs=[(5, 0, 0)], r=1)
        zencad.fillet(shp=zencad.box(20), refs=[(5, 0, 0)], r=1)

    def test_chamfer(self):
        zencad.box(20).chamfer(1)
        zencad.box(20).chamfer(r=1)
        zencad.chamfer(shp=zencad.box(20), r=1)

        zencad.box(20).chamfer(1, [(5, 0, 0)])
        zencad.box(20).chamfer(refs=[(5, 0, 0)], r=1)
        zencad.chamfer(shp=zencad.box(20), refs=[(5, 0, 0)], r=1)

    def test_ruled(self):
        zencad.ruled(
            zencad.segment((0, 0, 0), (10, 10, 10)),
            zencad.segment((10, 0, 0), (20, 10, 10)))

    def test_triangulation(self):
        zencad.triangulate(zencad.box(10), 0.1)


# -*- coding: utf-8 -*-
from jinja2 import Template
import requests
import json
import re

def check_inex_data_search(login):
    data = {"login":login, "actionsearch": '/auth/login', "status": '401'}
    headers = {"Authorization": ""}
    r = requests.post('https://', headers = headers, json=data, timeout=20)
    respons = json.loads(r.text)
    return respons

def get_answer(check_inex_data_data):
    with open("tamplate/check_inex_data.txt", "r", encoding="utf-8") as template:
        read_template = template.read()
    read_template = Template(read_template, trim_blocks=True)
    answer = read_template.render(check_inex_data_data)
    return answer

def check_inex_data(login):
    login = str(login)
    sj_data = check_inex_data_search(login)[0]
    error = sj_data['error']
    login = sj_data['login']
    email = sj_data['email']
    inex_email = re.findall(r'[^\s]+$', error)[0]
    check_inex_data_data = {
        'error': error,
        'login': login,
        'email': email,
        'inex_email': inex_email
        }
    check_inex_answer = get_answer(check_inex_data_data)
    return check_inex_answer


evenFactor = 2

#PARAMETER: inputValue is float type

def determineNumber(inputValue) :
    if (inputValue / evenFactor).is_integer() :
        return("Even")
    else :
        return("Odd")

    if inputValue / 1 == 0 :
        return("True")
    else :
        return("False")

#driver
print(determineNumber(11))


from django.shortcuts import render
from .models import *
from django.db.models import Q
# Create your views here.

def Index(request):
    if 'each' in request.GET:
        each = request.GET['each']
        data = Data.objects.filter(last_name__icontains=each)
        all_data = Q(Q(first_name__icontains=each) | Q(last_name__icontains=each) | Q(age__icontains=each))
        data= Data.objects.filter(all_data)
    else:
        data = Data.objects.all()
    context = {
        'data': data
    }
    return render(request,'index.html',{"data":data})

def Nav(request):
    return render(request,'nav.html')


from sys import stdin, stdout
import sys

# a a b a b a
# a a b a b
# a a b b
#
# 1. if a has less or equal than half + 1
#   a a x a x a x a
# 2. if a has more than half + 1
#       2.1 only two chars
#       b a a a a a a a b b
#       2.2 more than two chars
#       a b a a a a a a c b b c c
# 3. if x has one cnt
#   x a a a a b b b c c c

# uttttttttttttttttttuuuuuuuuvvvvv
# tutttttttttttttttttvuuuuuuuuvvvv
def solve(s):

    r = []
    c_a = [0] * 26
    i = ord(s[0]) - ord('a')

    for c in s:
        c_a[ord(c) - ord('a')] += 1
        i = min(i, ord(c) - ord('a'))

    k = get1cnt(c_a)
    if k != -1:
        r.append(chr(k + ord('a')))
        c_a[k] -= 1

    elif c_a[i] <= len(s) // 2 + 1:
        r.append(chr(i + ord('a')))
        c_a[i] -= 1
        m = i + 1

        while c_a[i] > 0:
            r.append(chr(i + ord('a')))
            c_a[i] -= 1
            while m < 26 and c_a[m] == 0:
                m += 1
            if m == 26:
                break
            r.append(chr(m + ord('a')))
            c_a[m] -= 1

    else:
        nxt = getnext(i, c_a)
        if nxt == -1:
            r.append(chr(i + ord('a')))
            c_a[i] -= 1
        elif getnext(nxt, c_a) == -1:
            r.append(chr(i + ord('a')))
            c_a[i] -= 1
            for _ in range(c_a[nxt]):
                r.append(chr(nxt + ord('a')))
                c_a[nxt] -= 1
        else:
            nnxt = getnext(nxt, c_a)
            r.append(chr(i + ord('a')))
            c_a[i] -= 1
            r.append(chr(nxt + ord('a')))
            c_a[nxt] -= 1
            for _ in range(c_a[i]):
                r.append(chr(i + ord('a')))
                c_a[i] -= 1
            r.append(chr(nnxt + ord('a')))
            c_a[nnxt] -= 1

    for l in range(26):
        for _ in range(c_a[l]):
            r.append(chr(l + ord('a')))
    return r

def get1cnt(c_a):
    for i in range(len(c_a)):
        if c_a[i] == 1:
            return i
    return -1

def getnext(i, c_a):
    for j in range(i+1, len(c_a)):
        if c_a[j] > 1:
            return j
    return -1

try:
    t = int(stdin.readline())
    for _ in range(t):
        s = str(stdin.readline().strip())
        r = solve(s)
        stdout.write(''.join(r) + '\n')
except:
    print(sys.exc_info())


# import scipy.io as scio
import numpy as np
# import pandas as pd
import matplotlib.pyplot as plt

def readData(filepath="Capacity.txt"):
    with open(filepath,"r") as f:
        rawdata=f.read()
        rawdata=rawdata[:-1].split(" ")

    data=[]
    for capacity in rawdata:
        if capacity!="":
            data.append(eval(capacity))
    return data

if __name__=="__main__":
    data=readData()
    # print(data)
    x=np.arange(0,len(data))
    failure=np.repeat(1.38,len(data))
    plt.plot(x,data)
    plt.plot(x,failure,color="r")
    plt.show()


#!/usr/bin/env python
"""
Created on Tue Nov  3 15:38:50 2015

@author: John Swoboda
"""
import glob,os
from ioclass import h5file
import scipy as sp
from SimISR.radarData import lagdict2ionocont
from SimISR.utilFunctions import makeparamdicts, makesumrule, makeconfigfile, dict2h5
from SimISR.IonoContainer import IonoContainer
from SimISR.const.physConstants import v_Boltz
import pdb

def SRIparams2iono(filename):

    fullfile = h5file(filename)
    fullfiledict = fullfile.readWholeh5file()

    #Size = Nrecords x Nbeams x Nranges x Nions+1 x 4 (fraction, temperature, collision frequency, LOS speed)
    fits = fullfiledict['/FittedParams']['Fits']
    (nt,nbeams,nrng,nspecs,nstuff) = fits.shape
    nlocs = nbeams*nrng
    fits = fits.transpose((1,2,0,3,4))
    fits = fits.reshape((nlocs,nt,nspecs,nstuff))
    #  Nrecords x Nbeams x Nranges
    Ne = fullfiledict['/FittedParams']['Ne']
    Ne = Ne.transpose((1,2,0))
    Ne = Ne.reshape((nlocs,nt))
    param_lists =sp.zeros((nlocs,nt,nspecs,2))
    param_lists[:,:,:,0] = fits[:,:,:,0]
    param_lists[:,:,:,1] = fits[:,:,:,1]
    param_lists[:,:,-1,0]=Ne
    Velocity = fits[:,:,0,3]

    if fullfiledict['/FittedParams']['IonMass']==16:
        species = ['O+','e-']
        pnames = sp.array([['Ni','Ti'],['Ne','Te']])

    time= fullfiledict['/Time']['UnixTime']
    time = time
    rng = fullfiledict['/FittedParams']['Range']
    bco = fullfiledict['/']['BeamCodes']
    angles = bco[:,1:3]
    (nang,nrg) = rng.shape

    allang = sp.tile(angles[:,sp.newaxis],(1,nrg,1))
    all_loc = sp.column_stack((rng.flatten(),allang.reshape(nang*nrg,2)))
    lkeep = ~ sp.any(sp.isnan(all_loc),1)
    all_loc = all_loc[lkeep]
    Velocity = Velocity[lkeep]
    param_lists = param_lists[lkeep]
    all_loc[:,0]=all_loc[:,0]*1e-3
    iono1 = IonoContainer(all_loc,param_lists,times=time,ver = 1,coordvecs = ['r','theta','phi'],
                          paramnames = pnames,species=species,velocity=Velocity)

    # MSIS
    tn = fullfiledict['/MSIS']['Tn']
    tn = tn.transpose((1,2,0))
    tn = tn.reshape((nlocs,nt))

    startparams = sp.ones((nlocs,nt,2,2))
    startparams[:,:,0,1] = tn
    startparams[:,:,1,1] = tn
    startparams = startparams[lkeep]
    ionoS = IonoContainer(all_loc,startparams,times=time,ver = 1,coordvecs = ['r','theta','phi'],
                          paramnames = pnames,species=species)
    return iono1,ionoS

def SRIRAW2iono(flist,outdir,desrange=[100.,650.],inttime=5*60.,timelim=1200.):
    """
        This will take a list of files and save out radar data
        Inputs
            flist - A list of files that will read and turned into the format
                for the simulator.
            outdir - The directory that that will hold the data in the format
                from radardatasim. A directory will be created called RadarData
                and the data will be saved there.
            inttime - The number of seconds for the integration time.
    """

    # make directory structure
    if not os.path.isdir(outdir):
        os.mkdir(outdir)
    radardatadir = os.path.join(outdir,'Radardata')

    if not os.path.isdir(radardatadir):
        os.mkdir(radardatadir)
    pulsetimes=[]
    outfilelist = []
    pulsenumbers = []
    beam_list_all = []
    noisetimes=[]
    for ifile,filename in enumerate(flist):
        outdict={}
        fullfile = h5file(filename)
        fullfiledict = fullfile.readWholeh5file()

        if fullfiledict['/Site']['Name'] =='Resolute North':
            radarname='risr'
            Pcal=fullfiledict['/Rx']['Bandwidth']*fullfiledict['/Rx']['CalTemp']*v_Boltz
        else:
            radarname='pfisr'
            Pcal=fullfiledict['/Rx']['Bandwidth']*fullfiledict['/Rx']['CalTemp']*v_Boltz

        bco = fullfiledict['/S/Data']['Beamcodes']
        beamlist = bco[0]
        if ifile==0:
            bstart = sp.zeros(len(beamlist),dtype=sp.int32)
        time= fullfiledict['/Time']['UnixTime']
#
        fullfile = h5file(filename)
        fullfiledict = fullfile.readWholeh5file()
        print('Main file being operated on: '+os.path.split(filename)[-1])

        acflags = fullfiledict['/S/Data/Acf']['Lags'].flatten()
        nlags = len(acflags)
        lagdown = sp.arange(-sp.floor(float(nlags-1)/2.),0).astype(int)
        lagup = sp.arange(1,sp.ceil(float(nlags+1)/2.)).astype(int)
        # Get the raw samples
        all_data = fullfiledict['/Raw11/Raw/Samples']['Data']
        rawrange = fullfiledict['/Raw11/Raw/Samples']['Range'][0]*1e-3
        rngkeep= sp.where(sp.logical_and(rawrange>=desrange[0],rawrange<desrange[1]))[0]

        rngkeep = sp.hstack((lagdown+rngkeep[0],rngkeep,lagup+rngkeep[-1]))
        rawrange=rawrange[rngkeep]
        pulse_times = fullfiledict['/Raw11/Raw/RadacHeader']['RadacTime']
        rawsamps = all_data[:,:,:,0]+1j*all_data[:,:,:,1]
        rawsamps = rawsamps[:,:,rngkeep]
        (nrecs,  np_rec,nrng)=rawsamps.shape

        all_beams_mat = fullfiledict['/Raw11/Raw/RadacHeader']['BeamCode']
#
        pwidth = float(fullfiledict['/S/Data']['Pulsewidth'])
#
#        # Pull in call and noise material because these will needed for fitting
        beamcodes_cal = fullfiledict['/S/Cal']['Beamcodes']
        cal_pint = fullfiledict['/S/Cal']['PulsesIntegrated']
        caldata = fullfiledict['/S/Cal/Power']['Data']
        noise_pint = fullfiledict['/S/Noise']['PulsesIntegrated']
        noise_pwer = fullfiledict['/S/Noise/Power']['Data']
        noise_data =fullfiledict['/S/Noise/Acf']['Data']
        noise_acf = noise_data[:,:,:,:,0]+1j*noise_data[:,:,:,:,1]
        noise_acf2 = sp.transpose(noise_acf,(0,1,3,2))
        (nbeams,nnrng,nlags)=noise_acf2.shape[1:]
#
        # use median to avoid large jumps. The difference between the mean and median estimator
        # goes to zero after enough pulses have been originally integrated. From what Im seeing you're
        # close to 64 pulses integrated you this will be off by only a 1/2 % of the true value.
        n_pow_e = sp.nanmedian(noise_pwer,axis=-1)/noise_pint

        c_pow_e = sp.nanmedian(caldata,axis=-1)/cal_pint

        # Need to adjust for cal and noise
        powmult = Pcal/(c_pow_e-n_pow_e)
        noise_mult = sp.tile(powmult[:,:,sp.newaxis,sp.newaxis],noise_acf2.shape[2:])
        npint_mat = sp.tile(noise_pint[:,:,sp.newaxis,sp.newaxis],noise_acf2.shape[2:])
        noise_acf_out = noise_acf2*noise_mult/npint_mat
        datamult = sp.zeros_like(rawsamps)

        for irec,ibeamlist in enumerate(beamcodes_cal):
            for ibpos,ibeam in enumerate(ibeamlist):
                b_idx = sp.where(ibeam==all_beams_mat[irec])[0]
                datamult[irec,b_idx]=sp.sqrt(powmult[irec,ibpos])

        outraw= rawsamps*datamult
        timep =  pulse_times.reshape(nrecs*np_rec)
        beamn = all_beams_mat.reshape(nrecs*np_rec)
        beamnrs = sp.zeros_like(beamn)
        pulsen = sp.ones(beamn.shape,dtype=sp.int32)
        for ibn, ibeam in enumerate(beamlist):
            curlocs = sp.where(beamn==ibeam)[0]
            beamnrs[curlocs] = ibn
            curtime = timep[curlocs]
            cursort = sp.argsort(curtime)
            curlocs_sort = curlocs[cursort]
            pulsen[curlocs_sort]= sp.arange(len(curlocs)) +bstart[ibn]
            bstart[ibn]=bstart[ibn]+len(curlocs)

        outdict['RawData']=outraw.reshape(nrecs*np_rec,nrng)
        outdict['RawDatanonoise'] = outdict['RawData']
        outdict['AddedNoise'] = (1./sp.sqrt(2.))*(sp.randn(*outdict['RawData'].shape)+1j*sp.randn(*outdict['RawData'].shape))
        outdict['NoiseDataACF'] = noise_acf_out
        outdict['BeamsNoise'] = bco[0]
        outdict['Beams']= beamnrs
        outdict['Time'] =timep
        outdict['NoiseTime'] = time
        outdict['Pulses']= pulsen
#
        fname = '{0:d} RawData.h5'.format(ifile)
        newfn = os.path.join(radardatadir,fname)
        outfilelist.append(newfn)
        pulsetimes.append(timep)
        pulsenumbers.append(pulsen)
        noisetimes.append(time)
        beam_list_all.append(beamnrs)
        dict2h5(newfn,outdict)
#    # save the information file
    infodict = {'Files':outfilelist,'Time':pulsetimes,'Beams':beam_list_all,'Pulses':pulsenumbers,'NoiseTime':noisetimes,'Range':rawrange}
    dict2h5(os.path.join(radardatadir,'INFO.h5'),infodict)
#
    ts = fullfiledict['/Rx']['SampleTime']
    sumrule = makesumrule('long',fullfiledict['/S/Data']['Pulsewidth'],ts)
#    minrg = -sumrule[0].min()
#    maxrg = len(rng_vec)-sumrule[1].max()
    maxrg = len(rawrange)+sumrule[0].min()
    minrg = sumrule[1].max()
    rng_lims = [rawrange[minrg],rawrange[maxrg]]# limits of the range gates
    IPP = .0087 #interpulse period in seconds
#
    simparams =   {'IPP':IPP, #interpulse period
                   'TimeLim':timelim, # length of simulation
                   'RangeLims':rng_lims, # range swath limit
#                   'Pulse':pulse, # pulse shape
                   'Pulselength':pwidth,
                   'FitType' :'acf',
                   't_s': ts,
                   'Pulsetype':'long', # type of pulse can be long or barker,
                   'Tint':inttime, #Integration time for each fitting
                   'Fitinter':inttime, # time interval between fitted params
                   'NNs': nnrng+nlags-1,# number of noise samples per pulse
                   'NNp':100, # number of noise pulses
                   'dtype':sp.complex128, #type of numbers used for simulation
                   'ambupsamp':1, # up sampling factor for ambiguity function
                   'species':['O+','e-'], # type of ion species used in simulation
                   'numpoints':128,
                   'startfile':'startfile.h5'
                   } # number of points for each spectrum
    makeconfigfile(os.path.join(outdir,'sriconfig1.ini'),beamlist,radarname,simparams)
def SRIACF2iono(flist):
    """
        This will take the ACF files and save them as Ionofiles
    """

    for iflistn, iflist in enumerate(flist):

        for ifile,filename in enumerate(iflist):
            fullfile = h5file(filename)
            fullfiledict = fullfile.readWholeh5file()

            if fullfiledict['/Site']['Name'] =='Resolute North':
                radarname='risr'
            else:
                radarname='pfisr'
            Pcal=fullfiledict['/Rx']['Bandwidth']*fullfiledict['/Rx']['CalTemp']*v_Boltz

            bco = fullfiledict['/S/Data']['Beamcodes']
            beamlist = bco[0]
            time= fullfiledict['/Time']['UnixTime']
#            if ifile==0 and iflistn==0:
#                time0=time[0,0]
#            time=time-time0
            #nt x nbeams x lags x range x 2
            acfs = fullfiledict['/S/Data/Acf']['Data']
            acfs = acfs[:,:,:,:,0]+1j*acfs[:,:,:,:,1]
            (nt,nbeams,nlags,nrng) =acfs.shape
            acfrng = fullfiledict['/S/Data/Acf']['Range'].flatten()
            acf_pint = fullfiledict['/S/Data']['PulsesIntegrated']

            pwidth = fullfiledict['/S/Data']['Pulsewidth']

            # Pull in call and noise material because these will needed for fitting

            cal_pint = fullfiledict['/S/Cal']['PulsesIntegrated']
            #nt x nbeams x range
            caldata = fullfiledict['/S/Cal/Power']['Data']
            caldata = sp.nanmedian(caldata,axis=-1)
            caldata=caldata/cal_pint

            noise_pint = fullfiledict['/S/Noise']['PulsesIntegrated']
            noise_pwer = fullfiledict['/S/Noise/Power']['Data']
            noise_pwer = sp.nanmedian(noise_pwer,axis=-1)
            noise_pwer = noise_pwer/noise_pint

            caldata = caldata-noise_pwer
            caldataD = sp.tile(caldata[:,:,sp.newaxis,sp.newaxis],(1,1,nlags,nrng))
            #nt x nbeams x lags x range x 2
            noise_data = fullfiledict['/S/Noise/Acf']['Data']
            noise_data = noise_data[:,:,:,:,0]+1j*noise_data[:,:,:,:,1]
            nnrg = noise_data.shape[-1]
            caldataN = sp.tile(caldata[:,:,sp.newaxis,sp.newaxis],(1,1,nlags,nnrg))
            # subtract noise and
            acfs = Pcal*acfs/caldataD
            acfs = acfs.transpose((0,1,3,2))
            noise_data = Pcal*noise_data/caldataN
            noise_data = noise_data.transpose((0,1,3,2))
            # Create output dictionaries and output data
            if ifile==0:
                acfs_sum=acfs.copy()
                acf_pint_sum = acf_pint.copy()
                noise_data_sum = noise_data.copy()
                noise_pint_sum = noise_pint.copy()

            else:
                acfs_sum=acfs_sum+acfs
                acf_pint_sum = acf_pint_sum+acf_pint
                noise_data_sum = noise_data_sum+ noise_data
                noise_pint_sum = noise_pint_sum + noise_pint
        if iflistn==0:

            acf_acum=acfs_sum.copy()
            acf_pint_acum = acf_pint_sum.copy()
            noise_data_acum = noise_data_sum.copy()
            noise_pint_acum = noise_pint_sum.copy()
            Time_acum =time.copy()
        else:
            acf_acum=sp.vstack((acf_acum,acfs_sum))
            acf_pint_acum = sp.vstack((acf_pint_acum,acf_pint_sum))
            noise_data_acum = sp.vstack((noise_data_acum,noise_data_sum))
            noise_pint_acum= sp.vstack((noise_pint_acum,noise_pint_sum))
            Time_acum = sp.vstack((Time_acum,time))

    DataLags = {'ACF':acf_acum,'Pow':acf_acum[:,:,:,0].real,'Pulses':acf_pint_acum,'Time':Time_acum}
    NoiseLags = {'ACF':noise_data_acum,'Pow':noise_data_acum[:,:,:,0].real,'Pulses':noise_pint_acum,'Time':Time_acum}

    rng_vec = acfrng*1e-3
    ts = fullfiledict['/Rx']['SampleTime']
    sumrule = makesumrule('long',fullfiledict['/S/Data']['Pulsewidth'],ts)
    minrg = -sumrule[0].min()
    maxrg = len(rng_vec)-sumrule[1].max()
    rng_lims = [rng_vec[minrg],rng_vec[maxrg]]# limits of the range gates
    IPP = .0087 #interpulse period in seconds

    simparams =   {'IPP':IPP, #interpulse period
                   'TimeLim':time[-1,1], # length of simulation
                   'RangeLims':rng_lims, # range swath limit
#                   'Pulse':pulse, # pulse shape
                   'Pulselength':pwidth,
                   'FitType' :'acf',
                   't_s': ts,
                   'Pulsetype':'long', # type of pulse can be long or barker,
                   'Tint':time[0,1]-time[0,0], #Integration time for each fitting
                   'Fitinter':time[1,0]-time[0,0], # time interval between fitted params
                   'NNs': 100,# number of noise samples per pulse
                   'NNp':100, # number of noise pulses
                   'dtype':sp.complex128, #type of numbers used for simulation
                   'ambupsamp':1, # up sampling factor for ambiguity function
                   'species':['O+','e-'], # type of ion species used in simulation
                   'numpoints':128} # number of points for each spectrum

    (sensdict,simparams) = makeparamdicts(beamlist,radarname,simparams)
    simparams['Rangegates'] =rng_vec
    simparams['Rangegatesfinal']=rng_vec[minrg:maxrg]

    ionolag, ionosigs = lagdict2ionocont(DataLags,NoiseLags,sensdict,simparams,Time_acum)

    return (ionolag,ionosigs,simparams,sensdict)

def makefitdirectory(sridir,srifile,fitdir,simdir):

    srifiles = [glob.glob(os.path.join(sridir,'*.dt{0}.h5'.format(i))) for i in range(3)]

    if [] in srifiles:
        srifiles.remove([])

    srifilesnew = [[None]*len(srifiles)]*len(srifiles[0])
    for ieln in range(len(srifiles[0])):
        srifilesnew[ieln] =[i[ieln] for i in srifiles ]

    # make iono conatainers out of the SRI data
    (ionolag,ionosigs,simparams,sensdict) = SRIACF2iono(srifilesnew)

    paramsiono,startiono = SRIparams2iono(srifile)
    # Add diretories that are needed
    mkdirlist = [fitdir,simdir]

    mkdirlist.append( os.path.join(fitdir,'ACF'))
    mkdirlist.append(os.path.join(fitdir,'Origparams'))
    mkdirlist.append(os.path.join(simdir,'Origparams'))
    for idir in mkdirlist:
        if not os.path.isdir(idir):
            os.mkdir(idir)

    # Save ACFs
    ionolag.saveh5(os.path.join(mkdirlist[-3],'00lags.h5'))
    ionosigs.saveh5(os.path.join(mkdirlist[-3],'00sigs.h5'))
    # Save fitted data
    paramsiono.saveh5(os.path.join(mkdirlist[-2],'0 srifits.h5'))
    paramsiono.saveh5(os.path.join(mkdirlist[-1],'0 srifits.h5'))
    # Save start data
    startiono.saveh5(os.path.join(mkdirlist[0],'startdata.h5'))
    startiono.saveh5(os.path.join(mkdirlist[1],'startdata.h5'))
    # Save ini files
    makeconfigfile(os.path.join(mkdirlist[0],'sridata.ini'),simparams['Beamlist'],sensdict['Name'],simparams)
    makeconfigfile(os.path.join(mkdirlist[1],'sridata.ini'),simparams['Beamlist'],sensdict['Name'],simparams)


import datetime
from discord.ext import commands, tasks

class Dates(commands.Cog):
    """ Work With Dates """
    def __init__(self, bot):
        self.bot = bot

    # @bot.event => commands.Cog.listener()
    @commands.Cog.listener()
    async def on_ready(self):   # Para saber se o bot está conectado
        self.curret_time.start()     # Iniciar task 'curret_time'

    @tasks.loop(hours=1)
    async def curret_time(self):
        """
        -> Faz o bot executar uma tarefa (exibir data e hora).
        PARÂMETROS:
            self ->
        """
        now = datetime.datetime.now()
        now = now.strftime("%d/%m/%Y às %H:%M:%S")
        channel = self.bot.get_channel(993252657500258437)
        await channel.send("Data atual: " + now)

def setup(bot):
    bot.add_cog(Dates(bot))


# This files contains your custom actions which can be used to run
# custom Python code.
#
# See this guide on how to implement these action:
# https://rasa.com/docs/rasa/custom-actions

# This is a simple example for a custom action which utters "Hello World!"

# from typing import Any, Text, Dict, List
# from rasa_sdk import tensorflow
from rasa_sdk import Action, Tracker
from rasa_sdk.events import SlotSet, EventType
from rasa_sdk.executor import CollectingDispatcher
from actions.vital_sign_rest_api import fetch_vital_signs, fetch_aggr_signs, prediction
# from actions.db import add_user, authenticate_user
from typing import Dict, Text, List, Optional, Any
from rasa_sdk.forms import FormValidationAction

#
# class ActionAddUser(Action):
#     def name(self) -> Text:
#         return "add_user_action"
#
#     def run(
#             self,
#             dispatcher,
#             tracker: Tracker,
#             domain: "DomainDict",
#     ) -> List[Dict[Text, Any]]:
#         # users = add_user("ali", 2345)
#         users = add_user("ali", 2345)
#         if users == "success":
#             dispatcher.utter_message(template="utter_user_success", user_name="user_name")
#         else:
#             dispatcher.utter_message(template="utter_user_fail", user_name="user_name")

class ValidateAuthenticationForm(Action):
    def name(self) -> Text:
        return "validate_authentication_form"

    async def required_slots(
            self,
            slots_mapped_in_domain: List[Text],
            dispatcher: "CollectingDispatcher",
            tracker: "Tracker",
            domain: "DomainDict",
    ) -> Optional[List[Text]]:
        required_slots = slots_mapped_in_domain + ["auth_name"]
        return required_slots

    async def extract_auth_name(
            self, dispatcher: CollectingDispatcher, tracker: Tracker, domain: Dict
    ) -> Dict[Text, Any]:
        text_of_last_user_message = tracker.latest_message.get("text")
        # sit_outside = "outdoor" in text_of_last_user_message

        return {"auth_name": text_of_last_user_message}

# class ValidateRestaurantForm(Action):
#     def name(self) -> Text:
#         return "validate_authentication_form"
#
#     def run(
#             self, dispatcher: CollectingDispatcher, tracker: Tracker, domain: Dict
#     ) -> List[EventType]:
#         required_slots = ["auth_code"]
#
#         for slot_name in required_slots:
#             if tracker.slots.get(slot_name) is None:
#                 # The slot is not filled yet. Request the user to fill this slot next.
#                 return [SlotSet("requested_slot", slot_name)]
#
#         # All slots are filled.
#         return [SlotSet("requested_slot", None)]

class ActionCheckPrediction(Action):
    def name(self) -> Text:
        return "check_prediction_action"
    def run(
            self, dispatcher: CollectingDispatcher, tracker: Tracker, domain: Dict
    ) -> List[EventType]:
        dispatcher.utter_message(template="utter_prediction", prediction = prediction())

class ActionSubmit(Action):
    def name(self) -> Text:
        return "action_authentication_submit"

    def run(
            self,
            dispatcher,
            tracker: Tracker,
            domain: "DomainDict",
    ) -> List[Dict[Text, Any]]:
        # ucount = authenticate_user(tracker.get_slot("auth_name"), tracker.get_slot("auth_code"))
        ucount = 1
        if ucount == 1:
            dispatcher.utter_message(template="utter_auth_success",
                                     auth_code=tracker.get_slot("auth_code"), uth_name=tracker.get_slot("auth_name"))
        else:
            dispatcher.utter_message(template="utter_auth_fail",
                                     auth_code=tracker.get_slot("auth_code"), auth_name=tracker.get_slot("auth_name"))
        # dispatcher.utter_message(template="utter_details_thanks",
        #                          code=tracker.get_slot("auth_code"))

class ActionCheckStatus(Action):
    def name(self) -> Text:
        return "check_heath_status_action"

    def run(
            self,
            dispatcher,
            tracker: Tracker,
            domain: "DomainDict",
    ) -> List[Dict[Text, Any]]:
        vital_signs = fetch_vital_signs()
        if len(vital_signs) > 0:
            tempr = vital_signs[0]["tempr"]
            resp = vital_signs[0]["resp"]
            hr = vital_signs[0]["hr"]
            spo2 = vital_signs[0]["spo2"]
            output = prediction(hr, spo2, resp, tempr)
            dispatcher.utter_message(template="utter_health_status",
                                     health_status=str(output))
            if output == str("Abnormal"):
                if tempr >= 30:
                    dispatcher.utter_message(template="utter_exceed_tempr",
                                             tempr=str(tempr))
                elif tempr <= 20:
                    dispatcher.utter_message(template="utter_less_tempr",
                                             tempr=str(tempr))

                if resp >= 30:
                    dispatcher.utter_message(template="utter_exceed_resp",
                                             resp=str(resp))
                elif resp <= 20:
                    dispatcher.utter_message(template="utter_less_resp",
                                             resp=str(resp))
                if hr >= 30:
                    dispatcher.utter_message(template="utter_exceed_hr",
                                             hr=str(hr))
                elif hr <= 20:
                    dispatcher.utter_message(template="utter_less_hr",
                                             hr=str(hr))
                if spo2 >= 90:
                    dispatcher.utter_message(template="utter_high_pressure",
                                             spo2=str(spo2))
                elif spo2 <= 60:
                    dispatcher.utter_message(template="utter_low_pressure",
                                             spo2=str(spo2))

        else:
            dispatcher.utter_message(template="utter_no_data", no_data="No data available")

class ActionCheckAbnormalStatus(Action):
    def name(self) -> Text:
        return "check_abnormal_vital_signs_action"

    def run(
            self,
            dispatcher,
            tracker: Tracker,
            domain: "DomainDict",
    ) -> List[Dict[Text, Any]]:
        vital_signs = fetch_vital_signs()
        if len(vital_signs):
            tempr = vital_signs[0]["tempr"]
            resp = vital_signs[0]["resp"]
            hr = vital_signs[0]["hr"]
            spo2 = vital_signs[0]["spo2"]
            tempStatus = "Normal"
            hrStatus = "Normal"
            spo2Status = "Normal"
            respStatus = "Normal"
            if tempr >= 30 or tempr <= 20:
                tempStatus = "Abnormal"
            dispatcher.utter_message(template="utter_exceed_tempr",
                                         tempr=str(tempr), tempStatus=tempStatus)

            if resp >= 30 or resp <= 20:
                respStatus = "Abnormal"
            dispatcher.utter_message(template="utter_exceed_resp",
                                         resp=str(resp), respStatus=respStatus)
            if hr >= 30 or hr <= 20:
                hrStatus = "Abnormal"

            dispatcher.utter_message(template="utter_exceed_hr",
                                         hr=str(hr), hrStatus=hrStatus)

            if spo2 >= 90 or spo2 <= 60:
                spo2Status = "Abnormal"

            dispatcher.utter_message(template="utter_high_pressure",
                                         spo2=str(spo2), spo2Status=spo2Status)

            return {"temp_reading": tempr, "sop2_reading": spo2, "heart_reading": hr, "resp_reading": resp}
        else:
            dispatcher.utter_message(template="utter_no_data", no_data="No data available")

class ActionDiagnosticResponseAction(Action):
    def name(self) -> Text:
        return "diagnostic_response_action"

    def run(
            self,
            dispatcher,
            tracker: Tracker,
            domain: "DomainDict",
    ) -> List[Dict[Text, Any]]:
        vital_signs = fetch_vital_signs()
        if len(vital_signs) > 0:
            tempr = vital_signs[0]["tempr"]
            resp = vital_signs[0]["resp"]
            hr = vital_signs[0]["hr"]
            spo2 = vital_signs[0]["spo2"]
            output = prediction(hr, spo2, resp, tempr)

            if output == str("Abnormal"):
                dispatcher.utter_message(template="utter_abnormal_response",
                                         abnormal_response=str(
                                             "The Patient condition is not normal. The patient needs an agent medical "
                                             "attention"))
            elif output == str("Normal"):
                dispatcher.utter_message(template="utter_normal_response",
                                         normal_response=str("The Patient condition is Normal."))
        else:
            dispatcher.utter_message(template="utter_no_data", no_data="No data available")

class ActionSuggestion(Action):
    def name(self) -> Text:
        return "suggested_action"

    def run(
            self,
            dispatcher,
            tracker: Tracker,
            domain: "DomainDict",
    ) -> List[Dict[Text, Any]]:

        vital_signs = fetch_vital_signs()
        if len(vital_signs):
            tempr = vital_signs[0]["tempr"]
            resp = vital_signs[0]["resp"]
            hr = vital_signs[0]["hr"]
            spo2 = vital_signs[0]["spo2"]
            if tempr >= 30:
                dispatcher.utter_message(template="utter_temp_suggest",
                                         tempr_suggest="Please follow the steps below to reduce the body heat")
            elif tempr <= 20:
                dispatcher.utter_message(template="utter_temp_suggest",
                                         tempr_suggest="Please follow the steps below to increase the body heat")
            if resp >= 30:
                dispatcher.utter_message(template="utter_resp_suggest",
                                         resp_suggest="Please follow the steps for breathing relaxation")
            elif resp <= 20:
                dispatcher.utter_message(template="utter_resp_suggest",
                                         resp_suggest="Please follow the steps for breathing relaxation")
            if hr >= 30:
                dispatcher.utter_message(template="utter_hr_suggest",
                                         hr_suggest="Please follow the steps to lower the heart rate")
            elif hr <= 20:
                dispatcher.utter_message(template="utter_hr_suggest",
                                         hr_suggest="Please follow the steps for improving the heart rate")
            if spo2 >= 90:
                dispatcher.utter_message(template="utter_pressure_suggest",
                                         spo2_suggest="Please follow the steps bellow to lower the pressure to the safe value")
            elif spo2 <= 60:
                dispatcher.utter_message(template="utter_pressure_suggest",
                                         spo2_suggest="Please follow the steps bellow to increase the pressure to save value")

class ValidateRestaurantForm(Action):
    def name(self) -> Text:
        return "validate_diagnosis_forms"

    def run(
            self, dispatcher: CollectingDispatcher, tracker: Tracker, domain: Dict
    ) -> List[EventType]:
        required_slots = ["vital_signs"]

        for slot_name in required_slots:
            if tracker.slots.get(slot_name) is None:
                # The slot is not filled yet. Request the user to fill this slot next.
                return [SlotSet("requested_slot", slot_name)]

        # All slots are filled.
        return [SlotSet("requested_slot", None)]

class ActionSubmit(Action):
    def name(self) -> Text:
        return "action_diagnosis_submit"

    def run(
            self,
            dispatcher,
            tracker: Tracker,
            domain: "DomainDict",
    ) -> List[Dict[Text, Any]]:
        vital_signs = fetch_vital_signs()
        vital_aggr_signs = fetch_aggr_signs()
        if len(vital_signs) > 0:
            tempr = str(vital_signs[0]["tempr"])
            resp = str(vital_signs[0]["resp"])
            hr = str(vital_signs[0]["hr"])
            spo2 = str(vital_signs[0]["spo2"])
        else:
            tempr = "No data"
            resp = "No data"
            hr = "No Data"
            spo2 = "No data"
        if tracker.get_slot('vital_signs') == "temperature":
            maxtempr = str(vital_aggr_signs[0]["maxtempr"])
            mintempr = str(vital_aggr_signs[0]["mintempr"])
            avgtempr = str(vital_aggr_signs[0]["avgtempr"])
            dispatcher.utter_message(template="utter_temperature", temperature=tempr, maxtempr=maxtempr,
                                     mintempr=mintempr, avgtempr=avgtempr)

        elif tracker.get_slot('vital_signs') == "heart":
            maxhr = str(vital_aggr_signs[0]["maxhr"])
            minhr = str(vital_aggr_signs[0]["minhr"])
            avghr = str(vital_aggr_signs[0]["avghr"])
            dispatcher.utter_message(template="utter_heart", heart=hr, maxhr=maxhr, minhr=minhr, avghr=avghr)

        elif tracker.get_slot('vital_signs') == "pressure":
            maxspo2 = str(vital_aggr_signs[0]["maxspo2"])
            minspo2 = str(vital_aggr_signs[0]["minspo2"])
            avgspo2 = str(vital_aggr_signs[0]["avgspo2"])
            dispatcher.utter_message(template="utter_pressure", pressure=spo2, maxspo2=maxspo2, minspo2=minspo2,
                                     avgspo2=avgspo2)

        elif tracker.get_slot('vital_signs') == "respiration":
            maxresp = str(vital_aggr_signs[0]["maxresp"])
            minresp = str(vital_aggr_signs[0]["minresp"])
            avgresp = str(vital_aggr_signs[0]["avgresp"])
            dispatcher.utter_message(template="utter_respiration", respiration=resp, maxresp=maxresp, minresp=minresp,
                                     avgresp=avgresp)

        elif tracker.get_slot('vital_signs') == "all":
            dispatcher.utter_message(template="utter_all",
                                     all="Temp: " + tempr + " C Oxygen Saturation: " + spo2 + " % Heart rate: " + hr + " bpm Respiration: " + resp+" bpm")

        else:
            dispatcher.utter_message(template="utter_none",
                                     none="No vital sign selected")

        return [SlotSet("requested_slot", None)]


import numpy as np
import pycuda
import pycuda.driver as cuda
from pycuda.compiler import SourceModule
import pycuda.autoinit

length = 1024
print("Reducing %d ones... \n" % length)

a = np.ones(length)
a = a.astype(np.complex128)
a = a + 1.0j
a_gpu = cuda.mem_alloc(a.nbytes)
cuda.memcpy_htod(a_gpu, a)

ans     = np.array(0, ndmin=1).astype(np.complex128)
ans_gpu = cuda.mem_alloc(ans.nbytes)
cuda.memcpy_htod(ans_gpu, ans)

mod = SourceModule("""
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <cuComplex.h>
__global__ void nv_reduc(cuDoubleComplex *result, cuDoubleComplex *indat) {
	extern __shared__ cuDoubleComplex shr[];

	// local and lobal thread ID
	unsigned int lid = threadIdx.x;
	unsigned int gid = blockIdx.x*blockDim.x + threadIdx.x;

	shr[lid] = indat[gid];
	__syncthreads();

	for (unsigned int s=blockDim.x/2; s>0; s /= 2) {
		if (lid < s) {
			//shr[lid] += shr[lid + s];
			shr[lid] = make_cuDoubleComplex(cuCreal(shr[lid]) + cuCreal(shr[lid+s]), cuCimag(shr[lid]) + cuCimag(shr[lid+s]));
		}
		__syncthreads();
	}
	if (lid == 0) {
		*result = shr[0];
	}

}
""")

_reduce_1d_array = mod.get_function("nv_reduc")
_reduce_1d_array(ans_gpu, a_gpu, block=(1024, 1, 1), shared=16*length)

cuda.memcpy_dtoh(ans, ans_gpu)
print(ans)

# Now assume you have been given an n*m array (with m the "long" dimension) and you need to sum over all the columns


def divisors(n: int):
    """ 約数列挙
    """
    assert n >= 0

    import math

    divs_first = []
    divs_second = []
    for x in range(1, math.floor(n ** 0.5) + 1):
        if n % x == 0:
            divs_first.append(x)
            if x * x != n:
                divs_second.append(n // x)
    divs_first.extend(reversed(divs_second))
    return divs_first

for p in divisors(int(input())):
    print(p)


from rest_framework import serializers
from ..models import Category, Question

class CategorySerializer(serializers.ModelSerializer):

    class Meta:
        model = Category
        fields = ["id", "name", "description"]

class QuestionSerializer(serializers.ModelSerializer):
    category_name = serializers.CharField(source='category.name')

    class Meta:
        model = Question
        fields = ['id', 'title', 'answer', 'category_name']


from constructs import Construct
import os
import aws_cdk.aws_s3 as s3
import aws_cdk.aws_stepfunctions as sfn
import aws_cdk.aws_lambda_event_sources as eventsources
from aws_cdk import (CfnOutput, RemovalPolicy, Stack, Duration)
import amazon_textract_idp_cdk_constructs as tcdk

class AnalyzeExpenseStack(Stack):

    def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None:
        super().__init__(
            scope,
            construct_id,
            description=
            "IDP CDK constructs sample for Textract AnalyzeExpense (SO9217)",
            **kwargs)

        s3_expense_prefix = "expense-uploads"
        s3_output_prefix = "textract-output"

        # BEWARE! This is a demo/POC setup, remote the auto_delete_objects=True and
        document_bucket = s3.Bucket(
            self,
            "SchademCdkIdpStackPaystubW2",
            auto_delete_objects=True,
            removal_policy=RemovalPolicy.DESTROY,
            block_public_access=s3.BlockPublicAccess.BLOCK_ALL)

        # get the event source that will be used later to trigger the executions
        s3_event_source = eventsources.S3EventSource(
            document_bucket,
            events=[s3.EventType.OBJECT_CREATED],
            filters=[s3.NotificationKeyFilter(prefix=s3_expense_prefix)])

        # EXPENSE
        decider_task_expense = tcdk.TextractPOCDecider(
            self,
            f"ExpenseDecider",
        )

        textract_sync_task_expense = tcdk.TextractGenericSyncSfnTask(
            self,
            "TextractSyncExpense",
            s3_output_bucket=document_bucket.bucket_name,
            s3_output_prefix=s3_output_prefix,
            textract_api="EXPENSE",
            integration_pattern=sfn.IntegrationPattern.WAIT_FOR_TASK_TOKEN,
            lambda_log_level="DEBUG",
            timeout=Duration.hours(24),
            input=sfn.TaskInput.from_object({
                "Token":
                sfn.JsonPath.task_token,
                "ExecutionId":
                sfn.JsonPath.string_at('$$.Execution.Id'),
                "Payload":
                sfn.JsonPath.entire_payload,
            }),
            result_path="$.textract_result")

        workflow_chain_expense = sfn.Chain \
            .start(decider_task_expense) \
            .next(textract_sync_task_expense)

        state_machine = sfn.StateMachine(self,
                                         f'Expense',
                                         definition=workflow_chain_expense)

        # The StartThrottle triggers based on event_source (in this case S3 OBJECT_CREATED)
        # and handles all the complexity of making sure the limits or bottlenecks are not exceeded
        tcdk.SFExecutionsStartThrottle(
            self,
            "ExecutionThrottle",
            state_machine_arn=state_machine.state_machine_arn,
            executions_concurrency_threshold=550,
            sqs_batch=10,
            lambda_log_level="ERROR",
            event_source=[s3_event_source])

        # OUTPUT
        CfnOutput(
            self,
            "ExpenseDocumentUploadLocation",
            value=f"s3://{document_bucket.bucket_name}/{s3_expense_prefix}/")
        current_region = Stack.of(self).region
        CfnOutput(
            self,
            'StepFunctionFlowLink',
            value=
            f"https://{current_region}.console.aws.amazon.com/states/home?region={current_region}#/statemachines/view/{state_machine.state_machine_arn}"
        )


def rating_film(n):
    if n == int:
        raise TypeError
    if n >= 21:
        return ("DEWASA")
    elif 13 <= n < 21:
        return ("REMAJA")
    elif 9 <= n < 13:
        return ("BIMBINGAN ORANG TUA")
    elif n < 9:
        return ("SEMUA UMUR")

print(rating_film(12))


import tkinter as tk
from Rubiccrypt import ThreeXThree
from crypt import CryptPrepareAfter, CryptPrepareBefore
from decrypt import DecryptPrepareAfter, DecryptPrepareBefore
from key import RandomKey
from gui import Gui
class Engine(Gui):
    def __init__(self, window):
        super().__init__(window)
        self.generate_key_btn.config(command = lambda *args: self.key_gen())
        self.crypt_bth.config(command = lambda *args: self.crypt())
        self.decrypt_bth.config(command = lambda *args: self.decrypt())
        self.key_field.delete(0, tk.END)
        self.opentext_field.delete(1.0, tk.END)
        self.ready_text_field_hex.delete(1.0, tk.END)
        self.ready_text_field_sym.delete(1.0, tk.END)
    def key_gen(self):
        self.key_field.delete(0, tk.END)
        temp = RandomKey(20)
        self.key_field.insert(0, temp.generateKey())
    def crypt(self):
        self.encodeMessage = self.opentext_field.get(1.0, tk.END)
        finalCryptMesSym, finalCryptMesHex = self.prepareToCrypt(self.encodeMessage, self.key_field.get())
        temp = [str(bin(i))[2:].zfill(8) for i in self.encodeMessage.encode(encoding="koi8-r")]
        temp2 = ''
        for i in range(len(temp)):
            temp2+= str(hex(int(temp[i], 2)))[2:].zfill(2)
        self.opentext_field.delete(1.0, tk.END)
        self.opentext_field.insert(1.0, temp2)
        self.ready_text_field_hex.delete(1.0, tk.END)
        self.ready_text_field_sym.delete(1.0, tk.END)
        self.ready_text_field_sym.insert(1.0, finalCryptMesSym)
        self.ready_text_field_hex.insert(1.0, finalCryptMesHex)
    def decrypt(self):
        self.decodeMessage = self.opentext_field.get(1.0, tk.END)
        finalDecryptMes = self.prepareToDecrypt(self.decodeMessage, self.key_field.get())
        self.ready_text_field_hex.delete(1.0, tk.END)
        self.ready_text_field_sym.delete(1.0, tk.END)
        self.ready_text_field_sym.insert(1.0, finalDecryptMes)
    def prepareToCrypt(self, mes, key, shift = False):
        a = CryptPrepareAfter()
        prepMes = a.check13(mes)
        symbMes, hexMes = self.compileEncrypt(prepMes, key, shift)
        return symbMes, hexMes
    def compileEncrypt(self, mes, key, shift = False):
        if shift:
            cryptMas = crypt_with_shift(mes, key)
        else:
            cryptMas = [ThreeXThree.crypt(key,i) for i in mes]
        preCryptText = ''
        for i in cryptMas: preCryptText+=i
        r = CryptPrepareBefore()
        return(r.getReverseMixedMessage(preCryptText))
    def prepareToDecrypt(self, hexMes, key, shift = False):
        a = DecryptPrepareAfter()
        prepMas = a.getBitStr(hexMes)
        symbMes = self.compileDecrypt(prepMas, key)
        return symbMes
    def compileDecrypt(self, mes, key, shift = False):
        decryptMas = [ThreeXThree.decrypt(key, i) for i in mes]
        preDecryptText = ''
        for i in decryptMas: preDecryptText+=i
        r = DecryptPrepareBefore()
        return(r.getReverseMixedMessage(preDecryptText))

if __name__ == "__main__":
    q = tk.Tk()
    window = Engine(q)
    window.mainloop()

# Исходное сообщение
# encodeMessage = "Пример сообщения для демонстрации работоспособности текста"
# decodeMessage = 'c99df5c7c5cbc0da9597cd65cfd9c7cecbc1c5ccd964c6d4806482cfc7d4c3d0c2cbd188d2cbc3d0c3cd71d6d1d1de8865cfd6cfcf7ed4d4546bd4e16ac4f4f67b'

# key = RandomKey(20)
# readyKey = key.generateKey()
# print(readyKey)
# Key = 'okydekgszegntydzkfud'
# # c - шифрование, d - дешифрование
# operation = 'd'

# if operation == "c":
#     finalCryptMesSym, finalCryptMesHex = prepareToCrypt(encodeMessage, Key)
#     print(finalCryptMesSym, ' ', finalCryptMesHex)

# else:
#     finalDecryptMes = prepareToDecrypt(decodeMessage, Key)
#     print(finalDecryptMes)


import setuptools

with open("README.md", "r") as fh:
    long_description = fh.read()
with open("requirements.txt", "r") as fh:
    requirements = [line.strip() for line in fh]

setuptools.setup(
    name="functions_package",
    version="0.0.1",
    author="H Hurchand",
    author_email="h.hurchand@gmail.com",
    description="A python module to work with functions",
    long_description=long_description,
    long_description_content_type="text/md",
    packages=setuptools.find_packages(),
    classifiers=[
        "Programming Language :: Python :: 3",
        "License :: OSI Approved :: MIT License",
        "Operating System :: OS Independent",
    ],
    python_requires='>=3.10',
    install_requires=requirements,
)


import os
import json
import argparse

# 存放一些对于标注关系数据的统计信息(summary), 通过 `deepke-master/utils/convert_vivrecard2deepke.py` 处理后得到的
relation_root = './data/vivrecard/summary'
relation_vizdata_file = os.path.join(relation_root, 'vizdata_vivrecard_relation.json')

# 各个任务生命卡的属性数据, 通过 `talkop/avpair2ntriples_talkop_vivre_card.py` 处理后得到的
avpair_root = '../talkop/data/processed_manual_talkop_vivre_card/'
avpair_vizdata_file = os.path.join(avpair_root, 'vizdata_vivrecard_avpair.json')

# 存放实体对齐后的数据
alignment_root = './data/vivrecard/alignment'
alignment_raw_mapping_file = os.path.join(alignment_root, 'raw_entity_mapping.txt')
alignment_json_mapping_file = os.path.join(alignment_root, 'json_entity_mapping.json')
alignment_relation_vizdata_file = os.path.join(alignment_root, 'alignment_vizdata_vivrecard_relation.json')
if not os.path.exists(alignment_root):
	os.makedirs(alignment_root)

# visualization data
# link_template = "{{'source': '{}', 'target': '{}', 'relation': '{}', 'value': 3}}"
# node_template = "{{'class': '{}', 'group': '{}', 'id': '{}', 'size': '{}'}}"

with open(avpair_vizdata_file) as f:
	avpair = json.load(f)

with open(relation_vizdata_file) as f:
	relation = json.load(f)

avpair = avpair.keys()
relation_nodes = [item["id"] for item in relation["nodes"]]

def get_arguments():
    parser = argparse.ArgumentParser(description="DeepLab-ResNet Network")

    parser.add_argument('--mode', type=str, default='discover',
    					help='Which mode to use. option: `discover`, `convert`, `alignment`.\n'\
    					'`discover` is to discover related entity.\n'\
    					'`convert` is to convert raw mapping table file to json format.\n'\
    					'`alignment` is to align the `vizdata_vivrecard_relation.json` by json format mapping table.')
    return parser.parse_args()

# 规范化: 统一大小写，去除标点符号
def process_name(item):
	return item.lower().replace('•', '').replace('·', '').replace('.', '').replace(' ', '')

def discover_related_entity():
	for idx, item in enumerate(relation_nodes):
		process_item = process_name(item)
		for target in relation_nodes[idx+1:]:
			process_target = process_name(target)

			# 1. 直接包含子串
			if item in target:
				if item != target:
					if target in avpair:
						print('[1] {}/{}'.format(target, item))
					else:
						print('[1] {}/{}'.format(item, target))

			# 2. 规范化后包含子串
			elif process_item in process_target:
				if process_item != process_target:
					if target in avpair:
						print('[2] {}/{}'.format(target, item))
					else:
						print('[2] {}/{}'.format(item, target))

			# 3. item 和 target 之间的交集 >= 5
			else:
				item_set = set(process_item)
				target_set = set(process_target)
				inter_set = set.intersection(item_set, target_set)
				if len(inter_set) >= 4 and not item.endswith('海贼团') and not target.endswith('海贼团'):
				# if len(inter_set) == 2 and not item.endswith('海贼团') and not target.endswith('海贼团'):
					if target in avpair and item not in avpair:
						print('[3] {}/{} {}'.format(target, item, inter_set))
					else:
						print('[3] {}/{} {}'.format(item, target, inter_set))

# 将mapping文件转换为json文件，人物结点的key一般选择第一个，也就是能查到相应avpair的mention name
def convert():
	with open(alignment_raw_mapping_file) as f:
		raw_mapping = f.readlines()

	json_mapping_dict = dict()
	for item in raw_mapping:
		item = item.strip()
		if not item.startswith('#---'):
			item = item.split('/')
			if len(item) == 0:
				print('[Error] item length is 0, item: {}'.format(item))
				exit(-1)

			for i in item:
				json_mapping_dict[i] = item[0]

	print('Write file path: {}'.format(alignment_json_mapping_file))
	with open(alignment_json_mapping_file, 'w', encoding='utf-8') as f:
	    json.dump(json_mapping_dict, f, ensure_ascii=False, indent=4, sort_keys=True)

# 将数据中的实体进行对齐，消除表示同一个实体的多个mention name
def align():
	with open(alignment_json_mapping_file) as f:
		json_mapping_dict = json.load(f)
	mapping_keys = json_mapping_dict.keys()

	relation_nodes = relation["nodes"]
	new_relation_nodes = list()
	new_name_list = list()
	for item in relation_nodes:
		mention_name = item["id"]
		if mention_name in mapping_keys:
			mention_name = json_mapping_dict[mention_name]
			item["id"] = mention_name
		if mention_name not in new_name_list:
			new_name_list.append(mention_name)
			new_relation_nodes.append(item)
	relation["nodes"] = new_relation_nodes

	relation_links = relation["links"]
	for item in relation_links:
		source_mention_name = item["source"]
		target_mention_name = item["target"]
		if source_mention_name in mapping_keys:
			item["source"] = json_mapping_dict[source_mention_name]
		if target_mention_name in mapping_keys:
			item["target"] = json_mapping_dict[target_mention_name]
	relation["links"] = relation_links

	print('Write file path: {}'.format(alignment_relation_vizdata_file))
	with open(alignment_relation_vizdata_file, 'w', encoding='utf-8') as f:
	    json.dump(relation, f, ensure_ascii=False, indent=4, sort_keys=True)

def main(args):
    if args.mode == "discover":
        discover_related_entity()
    elif args.mode == "convert":
        convert()
    elif args.mode == "align":
        align()

if __name__ == '__main__':
    args = get_arguments()
    print(args)

    main(args)


# import packages we need
import os
import keras
import cv2
import numpy as np
import time
from PIL import Image
import tensorflow as tf
from keras.models import Sequential
from keras.layers.core import Dense, Dropout, Activation, Flatten
from keras.layers import Conv2D, MaxPooling2D
import matplotlib.pyplot as plt
from keras.utils import np_utils

# #---- GPU memory management --------------------------------
os.environ["CUDA_VISIBLE_DEVICES"]="0"
gpus = tf.config.experimental.list_physical_devices('GPU')
for gpu in gpus:
  tf.config.experimental.set_memory_growth(gpu, True)
print("Num GPUs Available: ", len(tf.config.list_physical_devices('GPU')))
print(gpus)

def prepare_data(image_path):
  num_image = 0
  data_label = []
  images = []
  for root, dirs, files in os.walk(image_path):
    # print("root: ", root)
    # print("dirs: ", dirs)
    # print("files:" ,files)
    for file in files:
      num_image +=1
    #   print("file: ", file)
    #   print()
      image_path = os.path.join(root, file) # get image's path
      img = Image.open(image_path)
      img = np.array(img).reshape(1, 28, 28)
    #   img = cv2.imread(image_path, cv2.IMREAD_GRAYSCALE)
      # print(img)
    #   print(img.shape)
    #   img = cv2.resize(img, (28,28))
      images.append(img)
      label = os.path.basename(os.path.normpath(root)) # get the basename of root(label)
      data_label.append(label) # append label
    # print("current_data_label", data_label)
  images = np.array(images)
  print("image shape: ", images.shape)
  print("num of labels: ", len(data_label))
  return images, data_label

# load data
x_train, y_train = prepare_data("train_image")
x_test, y_test = prepare_data("test_image")

# hyperparameters
batch_size = 128
num_classes = 10
epochs = 100

# normalize images
x_train = x_train.reshape(2450, 28, 28, 1).astype('float32')
x_test = x_test.reshape(1700, 28, 28, 1).astype('float32')
x_train /= 255
x_test /= 255
y_train = keras.utils.np_utils.to_categorical(y_train, num_classes) # one hot encoding
y_test = keras.utils.np_utils.to_categorical(y_test, num_classes) # one hot encoding

# show data's shape
print(x_train.shape)
print(y_train.shape)
print(x_test.shape)
print(y_test.shape)

# define model
model = Sequential()
model.add(Conv2D(32, (3, 3), input_shape=(28, 28, 1))) # add Conv layer
model.add(Activation('relu'))
model.add(Dropout(0.3))
model.add(MaxPooling2D(pool_size=(2, 2))) # pooling layer improve accuracy significantly

model.add(Conv2D(32, (3, 3))) # add Conv layer
model.add(Activation('relu'))
model.add(Dropout(0.3))
model.add(Conv2D(64, (3, 3))) # add Conv layer
model.add(Activation('relu'))
model.add(Dropout(0.3))
model.add(MaxPooling2D(pool_size=(2, 2))) # pooling layer improve accuracy significantly

model.add(Flatten())

model.add(Dense(128)) # add fully connected layer
model.add(Activation('relu'))
model.add(Dropout(0.5))

model.add(Dense(10)) # add fully connected layer
model.add(Activation('softmax'))

# output model summary
# model.summary()

# compile
model.compile(loss='categorical_crossentropy',
       optimizer="adam",
       metrics=['accuracy'])

# uncomment if u want to use EarlyStopping
# es = EarlyStopping(monitor='val_loss', patience=10)

start = time.time()
# start training
hist = model.fit(x_train, y_train,
          batch_size = batch_size,
          epochs = epochs,
          verbose = 1,
          validation_split = 0.1,
          )
end = time.time()
print("training time: ", end - start)

# show training set accuracy
score = model.evaluate(x_train, y_train, verbose=0)
print('train loss:', score[0])
print('train acc:', score[1])

# show testing set accuracy
score = model.evaluate(x_test, y_test, verbose=0)
print('test loss:', score[0])
print('test acc:', score[1])

# plot loss figure
loss = hist.history['loss']
val_loss = hist.history['val_loss']
epochs = len(loss)
plt.plot(range(epochs), loss, marker='.', label='loss(training data)')
plt.plot(range(epochs), val_loss, marker='.', label='val_loss(evaluation data)')
plt.legend(loc='best')
plt.grid()
plt.xlabel('epoch')
plt.ylabel('loss')
plt.savefig("result.jpg")
plt.show()


from collections import defaultdict

t = int(input())
for _ in range(t):
	n = int(input())
	arr = [int(j) for j in input().split()]
	d = defaultdict(int)

	for x in arr:
		d[x] += 1

	num = sum(arr)
	denom = n

	s = []
	for x in d:
		s += [[x, d[x]]]

	s.sort()
	# print(s)

	ind1, ind2 = 0, len(s)-1

	ans = 0
	while ind1 <= ind2:
		# print(ind1, ind2)
		curnum = s[ind1][0] + s[ind2][0]
		curdenom = 2
		if num*curdenom < curnum*denom:
			ind2 -= 1
		elif num*curdenom > curnum*denom:
			ind1 += 1
		else:
			if ind1 != ind2:
				ans += s[ind1][1]*s[ind2][1]
			else:
				ans += s[ind1][1]*(s[ind1][1]-1)//2
			ind1 += 1
			ind2 -= 1

	print(ans)


from datetime import timedelta
from airflow import DAG
from airflow.operators.bash import BashOperator
from airflow.utils.dates import days_ago
from sqlalchemy import false

DIR = "/tmp/project/airflow/dags/finalassignment/staging/"
ENV_VAR = {
    "DIR": DIR,
    "TOLL_DATA_URL": "https://cf-courses-data.s3.us.cloud-object-storage.appdomain.cloud/IBM-DB0250EN-SkillsNetwork/labs/Final%20Assignment/tolldata.tgz",
    "TOLL_DATA": "tolldata.tgz",
    "VEHICLE_DATA": "vehicle-data.csv",
    "CSV_DATA": "csv_data.csv",
    "TOLLPLAZA_DATA": "tollplaza-data.tsv",
    "TSV_DATA": "tsv_data.csv",
    "PAYMENT_DATA": "payment-data.txt",
    "FIXED_WITH_DATA": "fixed_width_data.csv",
    "EXTRACTED_DATA": "extracted_data.csv",
    "TRANSFORMED_DATA": "transformed_data.csv"
}

# Task 1.1 - Define DAG arguments
default_args = {
    "owner": "Mario Loera",
    "start_date": days_ago(0),
    "email": ["marioloera@somemail.com"],
    "email_on_failure": True,
    "email_on_retry": True,
    "retries": 1,
    "retry_delay": timedelta(minutes=5),
}

# Task 1.2 - Define the DAG
dag = DAG(
    "ETL_toll_data_loop",
    schedule_interval=timedelta(days=1),
    default_args=default_args,
    description="Apache Airflow Final Assignment",
)

def get_task(task_id, with_dir=True):
    if with_dir:
        dir = DIR
    else:
        dir = None

    return BashOperator(
        task_id=task_id,
        bash_command=TASKS_CONFIG[task_id],
        env=ENV_VAR,
        cwd=dir,
        dag=dag,
    )

TASKS_CONFIG = {
    "mkdir": "mkdir -p $DIR",
    "download_data": "wget $TOLL_DATA_URL -O $TOLL_DATA",
    "unzip_data": "tar zxvf $TOLL_DATA -C $DIR",
    "extract_data_from_csv": "cut -d',' -f1-4 $VEHICLE_DATA > $CSV_DATA",
    "extract_data_from_fixed_width": "cut -c 59-67 $PAYMENT_DATA | tr ' ' ',' > $FIXED_WITH_DATA",
}

pipeline = None

for task_id in TASKS_CONFIG.keys():
    # the first task is mkdir, and need with_dir=false
    if pipeline is None:
        pipeline = get_task(task_id, with_dir=false)
        continue

    # pipeline.set_downstream(_task)  # doesn't work
    # pipeline >> _task  # doesn't work
    pipeline = pipeline >> get_task(task_id)  # this work, but only linear


import geopandas as gpd
import pandas as pd
from sqlalchemy import create_engine, text

from modules.config import Config
from modules.gis_processing import GisProcessor

def dict_values_to_list(d: dict) -> dict:
    """Transform dict values to list."""
    return {k: [v] for k, v in d.items()}

def other_tag_to_dict(tags: str) -> dict:
    """Split OSM tags to dict."""
    tags = tags[1:-1]
    return {
        k: v for k, v in [s.split('"=>"') for s in tags.split('","')] if v is not None
    }

class TramInfra(GisProcessor):
    """Process tram infra."""

    def __init__(self, cfg: Config):
        self._cfg = cfg
        self._process_result_lines = None
        self._process_result_polygons = None
        self._debug_result_lines = None

        file_name = cfg.local_file("tram_infra")

        self._lines = gpd.read_file(file_name)

    def process(self):
        lines = self._lines
        lines_with_tags = lines[~lines.other_tags.isna()].copy()

        lines_with_tags["tag_dict"] = lines_with_tags.apply(
            lambda r: other_tag_to_dict(r.other_tags), axis=1
        )
        lines_with_tags_tram_index = lines_with_tags.apply(
            lambda r: r.tag_dict.get("railway") == "tram", axis=1
        )
        tram_lines = lines_with_tags[lines_with_tags_tram_index]

        df_list = []
        for i, r in tram_lines.iterrows():
            df_list.append(pd.DataFrame(dict_values_to_list(r.tag_dict)))
        df_new = pd.concat(df_list)
        df_new.index = tram_lines.index
        trams = tram_lines.join(df_new, how="inner").drop(["tag_dict"], axis=1)
        trams["infra"] = 1
        trams = trams.astype({"infra": "int32"})
        self._process_result_lines = trams.loc[:, ["infra", "geometry"]]
        self._debug_result_lines = trams

        # Buffering configuration
        buffers = self._cfg.buffer("tram_infra")
        if len(buffers) != 1:
            raise ValueError("Unkown number of buffer values")

        # buffer lines
        target_infra_polys = self._process_result_lines.copy()
        target_infra_polys["geometry"] = target_infra_polys.buffer(buffers[0])

        # save to instance
        self._process_result_polygons = target_infra_polys

    def persist_to_database(self):
        engine = create_engine(self._cfg.pg_conn_uri(), future=True)

        # persist original results for debugging and development
        debug_schema = "debug"

        with engine.connect() as conn:
            conn.execute(text("CREATE SCHEMA IF NOT EXISTS {}".format(debug_schema)))
            conn.commit()

        self._debug_result_lines.to_postgis(
            "tram_infra",
            engine,
            debug_schema,
            if_exists="replace",
            index=True,
            index_label="fid",
        )

        # persist route lines to database
        self._process_result_lines.to_postgis(
            "tram_infra",
            engine,
            "public",
            if_exists="replace",
            index=True,
            index_label="fid",
        )

        # persist polygons to database
        self._process_result_polygons.to_postgis(
            "tram_infra_polys",
            engine,
            "public",
            if_exists="replace",
            index=True,
            index_label="fid",
        )

    def save_to_file(self):
        """Save processing results to file."""
        # tram line infra as debug material
        target_infra_file_name = self._cfg.target_file("tram_infra")

        tram_lines = self._process_result_lines.reset_index(drop=True)

        schema = gpd.io.file.infer_schema(tram_lines)
        schema["properties"]["infra"] = "int32"

        tram_lines.to_file(target_infra_file_name, schema=schema, driver="GPKG")

        # tormays GIS material
        target_buffer_file_name = self._cfg.target_buffer_file("tram_infra")

        # instruct Geopandas for correct data type in file write
        # fid is originally as index, obtain fid as column...
        tormays_polygons = self._process_result_polygons.reset_index(drop=True)

        schema = gpd.io.file.infer_schema(tormays_polygons)
        schema["properties"]["infra"] = "int32"

        tormays_polygons.to_file(target_buffer_file_name, schema=schema, driver="GPKG")