'''Automatic preparation, submission and consolidation
of AWS batch tasks; as a single Luigi Task.
'''

from abc import ABC
from abc import abstractmethod
from collections import defaultdict
from nesta.core.luigihacks import batchclient
from subprocess import check_output
from subprocess import CalledProcessError
import time
from datetime import datetime as dt
import luigi
from nesta.core.luigihacks.misctools import get_config
import logging
import os

# Define a global timeout, set to 95% of the timeout time
# in order to give the Luigi worker some grace
_config = get_config("luigi.cfg", "worker")

def command_line(command, verbose=False):
    '''Execute command line tasks and return the final output line.
    This is particularly useful for extracting the AWS access keys
    directly from the OS; as well as executing the environment
    preparation script (:code:`core/scripts/nesta_prepare_batch.sh`).
    '''
    # Execute the command and decode the output
    out = check_output([command], shell=True)
    out_lines = out.decode("utf-8").split("\n")
    if verbose:
        for line in out_lines:
            logging.info(f"{os.getpid()}: "
                         ">>>\t'{}'".format(line.replace("\r", ' ')))
    # The second last output is the actual final output
    # (ignoring the status code, which is the last output)
    return out_lines[-2]

class AutoBatchTask(luigi.Task, ABC):
    '''A base class for automatically preparing and submitting AWS batch tasks.

    Unlike regular Luigi :code:`Tasks`, which require the user
    to override the :code:`requires`, :code:`output` and :code:`run`
    methods, :code:`AutoBatchTask` instead effectively replaces
    :code:`run` with two new abstract methods: :code:`prepare`
    and :code:`combine`, which are repectively documented. With these abstract
    methods specified, :code:`AutoBatchTask` will automatically prepare,
    submit, and combine one batch task (specified in
    :code:`core.batchables`) per parameter set specified in the
    :code:`prepare` method. The :code:`combine` method will subsequently
    combine the outputs from the batch task.

    Args:
        batchable (str): Path to the directory containing the run.py batchable
        job_def (str): Name of the AWS job definition
        job_name (str): Name given to this AWS batch job
        job_queue (str): AWS batch queue
        region_name (str): AWS region from which to batch
        env_files (:obj:`list` of :obj:`str`, optional): List of names
                  pointing to local environmental files (for example local
                  imports or scripts) which should be zipped up with the
                  AWS batch job environment. Defaults to [].
        vcpus (int, optional): Number of CPUs to request for the AWS batch job.
              Defaults to 1.
        memory (int, optional): Memory to request for the AWS batch job.
               Defaults to 512 MiB.
        max_runs (int, optional): Number of batch jobs to run, which is useful
                 for testing a subset of the full pipeline, or making cost
                 predictions for AWS computing time. Defaults to `None`,
                 implying that all jobs should be run.
        poll_time (int, optional): Time in seconds between querying the AWS
                  batch job status. Defaults to 60.
        success_rate (float, optional): If the fraction of FAILED jobs exceeds
                     :code:`success_rate` then the entire Task, along with
                     any submitted AWS batch jobs, is killed. The fraction is
                     calculated with respect to any jobs with RUNNING,
                     SUCCEEDED or FAILED status. Defaults to 0.75.
    '''
    batchable = luigi.Parameter()
    job_def = luigi.Parameter()
    job_name = luigi.Parameter()
    job_queue = luigi.Parameter()
    region_name = luigi.Parameter()
    env_files = luigi.ListParameter(default=[])
    vcpus = luigi.IntParameter(default=1)
    memory = luigi.IntParameter(default=512)
    max_runs = luigi.IntParameter(default=None)  # For testing
    timeout = luigi.IntParameter(default=21600)
    poll_time = luigi.IntParameter(default=60)
    success_rate = luigi.FloatParameter(default=0.95)
    test = luigi.BoolParameter(default=True)
    max_live_jobs = luigi.IntParameter(default=25)
    worker_timeout = float('inf')
    date = luigi.DateParameter(default=dt.now())

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.failed_jobs = set()

    def run(self):
        '''DO NOT OVERRIDE THIS METHOD.

        An implementation of the :code:`Luigi.Task.run` method which is a
        wrapper around the :code:`prepare`, :code:`execute` and
        :code:`combine` methods. Instead of overriding this method, you
        should implement :code:`prepare` and :code:`combine` methods in
        your class.
        '''
        pid = os.getpid()
        self.TIMEOUT = time.time() + int(_config["timeout"])

        # Generate the parameters for batches
        job_params = self.prepare()
        if self.test:
            if len(job_params) > 2:
                job_params = job_params[0:2]
                logging.info(f"Test mode ({pid}): running {len(job_params)} jobs")

        # Prepare the environment for batching
        env_files = " ".join(self.env_files)
        try:
            if self.test:
                logging.info(f"Test mode ({pid}): Preparing batch")
            s3file_timestamp = command_line("nesta_prepare_batch "
                                            "{} {}".format(self.batchable,
                                                           env_files), self.test)
            if self.test:
                logging.info(f"Test mode ({pid}): Prepared batch")
        except CalledProcessError:
            raise batchclient.BatchJobException("Invalid input "
                                                "or environment files")
        # Execute batch jobs
        self.execute(job_params, s3file_timestamp)
        # Combine the outputs
        self.combine(job_params)

    @abstractmethod
    def prepare(self):
        '''You should implement a method which returns a :code:`list`
        of :code:`dict`, where each :code:`dict` corresponds to inputs
        to the batchable. Each row of the output must at least
        contain the following keys:

        - **done** (`bool`): indicating whether the job has already been
          finished.
        - **outinfo** (`str`): Text indicating e.g. the location of the output,
          for use in the batch job and for `combine` method

        Returns:
            :obj:`list` of :obj:`dict`
        '''
        pass

    @abstractmethod
    def combine(self, job_params):
        '''You should implement a method which collects the outputs specified by
        the **outinfo** key of :code:`job_params`, which is the output from the
        :code:`prepare` method. This method should finally write to the
        :code:`luigi.Target` output.

        Parameters:
            job_params (:obj:`list` of :obj:`dict`): The batchable job
                       parameters, as returned from the :code:`prepare` method.
        '''
        pass

    def execute(self, job_params, s3file_timestamp):
        ''' The secret sauce, which automatically submits and monitors
        the AWS batch jobs. Your AWS access key and id are automatically
        retrieved via the AWS CLI.

        Parameters:
            job_params (:obj:`list` of :obj:`dict`): The batchable job
                       parameters, as returned from the :code:`prepare` method.
                       Each job is submitted from every item in this
                       :code:`list`. Each `dict` key-value per is converted
                       into an environmental variable in the batch job, with
                       the variable
                       name formed from the key, prefixed by `BATCHPAR_`.
            s3file_timestamp (str): The timestamp of the batchable zip file
                             to be found on S3 by the AWS batch job.
        '''
        pid = os.getpid()
        # Get AWS info to pass to the batch jobs
        aws_id = command_line("aws --profile default configure "
                              "get aws_access_key_id", self.test)
        aws_secret = command_line("aws --profile default configure "
                                  "get aws_secret_access_key", self.test)

        # Build a set of environmental variables to send to the jobs
        env_variables = [{"name": "AWS_ACCESS_KEY_ID", "value": aws_id},
                         {"name": "AWS_SECRET_ACCESS_KEY",
                          "value": aws_secret},
                         {"name": "BATCHPAR_S3FILE_TIMESTAMP",
                          "value": s3file_timestamp}]
                         #{"name": "PYTHONIOENCODING", "value": "latin1"}]

        if self.test:
            logging.info(f"Test mode ({pid}): Got env variables")

        # Set up batch client, and check that we haven't
        # already hit the time limit
        batch_client = batchclient.BatchClient(poll_time=self.poll_time,
                                               region_name=self.region_name)
        self._assert_timeout(batch_client, job_ids=[])
        if self.test:
            logging.info(f"Test mode ({pid}): Ready to batch")

        all_job_kwargs = []
        for i, params in enumerate(job_params):
            if params["done"]:
                continue
            # Break in case of testing
            if (self.max_runs is not None) and (i >= self.max_runs):
                break

            _env_variables = env_variables.copy()
            for k, v in params.items():
                new_row = dict(name="BATCHPAR_{}".format(k), value=str(v))
                _env_variables.append(new_row)
            # Add the environmental variables to the container overrides
            overrides = dict(environment=_env_variables,
                             memory=self.memory, vcpus=self.vcpus)
            job_kwargs = dict(jobDefinition=self.job_def,
                              jobName=self.job_name,
                              jobQueue=self.job_queue,
                              timeout=dict(attemptDurationSeconds=self.timeout),
                              containerOverrides=overrides)
            all_job_kwargs.append(job_kwargs)

        # Wait for jobs to finish
        self._run_batch_jobs(batch_client, all_job_kwargs)

    def _run_batch_jobs(self, batch_client, all_job_kwargs):
        '''Monitor AWS batch jobs until finished or failed.

        Parameters:
            batch_client (:obj:`BatchClient`)
            job_ids (:obj:`list` of :obj:`str`): List of AWS batch
                    job IDs to monitor.
        '''

        # Keep submitting until all submitted
        all_job_ids = set()
        done_job_ids = set()
        submitted_job_idxs = set()
        logging.info(f"{os.getpid()}: "
                     "{} jobs to run".format(len(all_job_kwargs)))
        while len(all_job_kwargs) > len(all_job_ids):
            # Get the number of live jobs
            running_job_ids = all_job_ids - done_job_ids
            n_live = len(running_job_ids)
            n_done = len(done_job_ids)
            n_left = len(all_job_kwargs) - n_done - n_live
            logging.info(f"{os.getpid()}: "
                         "{} jobs are live, "
                         "{} are finished, "
                         "and {} are yet to be submitted".format(n_live, n_done, n_left))

            if n_live > 1:
                self._assert_timeout(batch_client, running_job_ids)
                self._assert_success(batch_client, all_job_ids, done_job_ids)
            # Submit some jobs until `self.max_live_jobs` reached
            for ijob, job_kwargs in enumerate(all_job_kwargs):
                if n_live >= self.max_live_jobs:
                    break
                if ijob in submitted_job_idxs:
                    continue
                # Submit a new job
                id_ = batch_client.submit_job(**job_kwargs)
                all_job_ids.add(id_)
                submitted_job_idxs.add(ijob)
                n_live += 1
            # Wait before continuing
            logging.info(f"{os.getpid()}: Not done submitting...")
            time.sleep(self.poll_time)

        # Wait until all finished
        running_job_ids = all_job_ids - done_job_ids
        while len(running_job_ids) > 0:
            running_job_ids = all_job_ids - done_job_ids
            self._assert_timeout(batch_client, running_job_ids)
            self._assert_success(batch_client, all_job_ids, done_job_ids)
            # Wait before continuing
            #logging.info("Not finished waiting...")
            time.sleep(self.poll_time)

    def _assert_success(self, batch_client, job_ids, done_jobs):
        '''Assert that success rate has not been breached.'''

        stats = defaultdict(int)  # Collection of failure vs total statistics
        # Check status for each job
        for id_ in job_ids:
            status = batch_client.get_job_status(id_)
            if id_ not in done_jobs:
                logging.debug(f"{os.getpid()}: "
                              "{} {}".format(id_, status))
            if status == "FAILED":
                self.failed_jobs.add(id_)
            if status not in ("SUCCEEDED", "FAILED", "RUNNING"):
                continue
            stats[status] += 1
            if status != "RUNNING":
                done_jobs.add(id_)

        # Ignore if jobs are simply stalling
        if len(stats) == 0:
            logging.info(f"{os.getpid()}: "
                         "No jobs are currently running")
            return

        # Calculate the failure rate
        total = sum(stats.values())
        failure_rate = stats["FAILED"] / total
        if failure_rate <= (1 - self.success_rate):
            return
        reason = "Exiting due to high failure rate: {}%".format(int(failure_rate*100))
        reason += "\nFailed jobs are: {}".format(self.failed_jobs)
        batch_client.hard_terminate(job_ids=job_ids, reason=reason)

    def _assert_timeout(self, batch_client, job_ids):
        '''Assert that timeout has not been breached.'''
        logging.info(f"{os.getpid()}: "
                     "{} seconds left".format(self.TIMEOUT - time.time()))
        if time.time() < self.TIMEOUT:
            return
        reason = f"{os.getpid()}: "
        reason += "Impending worker timeout, so killing live tasks"
        reason += "\nFailed jobs are: {}".format(self.failed_jobs)
        batch_client.hard_terminate(job_ids=job_ids, reason=reason)


# First networkx library is imported
# along with matplotlib
import networkx as nx
import matplotlib.pyplot as plt
import requests

# Defining a Class
class GraphVisualization:

    def __init__(self):
        # visual is a list which stores all
        # the set of edges that constitutes a
        # graph
        self.visual = []

    # addEdge function inputs the vertices of an
    # edge and appends it to the visual list
    def addEdge(self, a, b):
        temp = [a, b]
        self.visual.append(temp)

    # In visualize function G is an object of
    # class Graph given by networkx G.add_edges_from(visual)
    # creates a graph with a given list
    # nx.draw_networkx(G) - plots the graph
    # plt.show() - displays the graph
    def visualize(self):
        G = nx.DiGraph()
        G.add_edges_from(self.visual)
        nx.draw_networkx(G)
        plt.show()

# Driver code
G = GraphVisualization()
seen = set()
nodes_list = []
from sys import argv
checked_node_id = argv[1] if len(argv) == 2 else 6000
while checked_node_id not in seen:
    resp = requests.get(f"http://0.0.0.0:{checked_node_id}").json()
    nodes_list.append(resp["Node"])
    seen.add(resp["Node"])
    checked_node_id = resp["N"]
nodes_list.append(checked_node_id)

for i in range(len(nodes_list)-1):
    G.addEdge(nodes_list[i], nodes_list[i+1])
G.addEdge(nodes_list[i], nodes_list[i+1])
# print(nodes_list)
G.visualize()


# $language = "python"
# $interface = "1.0"

def Main():
    show = '''
(1)md (2)ms (3)ud (4)da (5)pop3 (6)imap (7)session\n
(8)admin (9)webproxy (10)scequery (11)mta (12)search (13)arch (14)mscache
	'''

    svr = crt.Dialog.Prompt(show, "Input a server name(or type the number)")

    if svr in ('1', 'md'):
        svr_port = '6120'
    if svr in ('2', 'ms'):
        svr_port = '6162'
    if svr in ('3', 'ud'):
        svr_port = '6122'
    if svr in ('4', 'da'):
        svr_port = '6142'
    if svr in ('5', 'pop3'):
        svr_port = '6192'
    if svr in ('6', 'imap'):
        svr_port = '6232'
    if svr in ('7', 'session'):
        svr_port = '6152'
    if svr in ('8', 'admin'):
        svr_port = '6132'
    if svr in ('9', 'webproxy'):
        svr_port = '6212'
    if svr in ('10', 'scequery'):
        svr_port = '6172'
    if svr in ('11', 'mta'):
        svr_port = '6182'
    if svr in ('12', 'search'):
        svr_port = '6242'
    if svr in ('13', 'arch'):
        svr_port = '6202'
    if svr in ('14', 'mscache'):
        svr_port = '6642'

    crt.Screen.Send('telnet 0 %s' % svr_port + chr(13))

Main()


import requests
import validators
from telegram import ParseMode

def handle(bot, update, args):
    if args:
        domain = args.pop(0)
        if validators.domain(domain):
            try:
                data = requests.get("https://{}".format(domain))
                time = data.elapsed.total_seconds()
                code = data.status_code
                msg = "Website ***https://{}*** voi status code la `{}` trong `{}s`".format(domain,
                                                                         code,
                                                                         time)
                update.message.reply_text(
                             text=msg,
                             parse_mode=ParseMode.MARKDOWN)
            except requests.exceptions.ConnectionError:
                update.message.reply_text(
                             text='***Ket noi that bai toi website*** '
                                  '`https://{}`'.format(domain),
                             parse_mode=ParseMode.MARKDOWN)

        else:
            update.message.reply_text(
                         text='***Ten domain khong hop le***\n'
                              'VD: /is minhkma.com',
                         parse_mode=ParseMode.MARKDOWN)
    else:
        update.message.reply_text(
                         text='***Nhap domain ban muon check***\n'
                              'VD: /is minhkma.com',
                         parse_mode=ParseMode.MARKDOWN)


import argparse
import glob
import os
import cv2
import copy
import numpy as np
from collections import deque
THRES_IOU = 0.0

def get_args():

	parser = argparse.ArgumentParser()
	parser.add_argument('--type', default=0, type=int)
	parser.add_argument('--video', default=3, type=int)
	parser.add_argument('--start', default=890, type=int)
	parser.add_argument('--end', default=1080, type=int)
	parser.add_argument('--object', default='pedestrian', type=str)
	parser.add_argument('--object_idx', default=0, type=int)
	parser.add_argument('--output_dir', default='/tmp2/frank840306/demo_video', type=str)

	return parser.parse_args()

def mid_point(bbox):
	x = (bbox[0] + bbox[2]) / 2
	y = (bbox[1] + bbox[3]) / 2
	return (x, y)

def iou(bbox1, bbox2):
	one_x = bbox1[0]
	one_y = bbox1[1]
	one_w = bbox1[2] - bbox1[0]
	one_h = bbox1[3] - bbox1[1]

	two_x = bbox2[0]
	two_y = bbox2[1]
	two_w = bbox2[2] - bbox2[0]
	two_h = bbox2[3] - bbox2[1]

	if((abs(one_x - two_x) < ((one_w + two_w) / 2.0)) and (abs(one_y - two_y) < ((one_h + two_h) / 2.0))):
		lu_x_inter = max((one_x - (one_w / 2.0)), (two_x - (two_w / 2.0)))
		lu_y_inter = min((one_y + (one_h / 2.0)), (two_y + (two_h / 2.0)))

		rd_x_inter = min((one_x + (one_w / 2.0)), (two_x + (two_w / 2.0)))
		rd_y_inter = max((one_y - (one_h / 2.0)), (two_y - (two_h / 2.0)))

		inter_w = abs(rd_x_inter - lu_x_inter)
		inter_h = abs(lu_y_inter - rd_y_inter)

		inter_square = inter_w * inter_h
		union_square = (one_w * one_h) + (two_w * two_h) - inter_square

		IOU = inter_square / union_square * 1.0
		#print("calcIOU:", IOU)
	else:
		IOU = 0
		#print("No intersection!")

	return IOU

def read_bbox(bbox_dir, cfg):
	bbox_type = ['pedestrian', 'bicycle']
	object_dict = {}
	for bt in bbox_type:
		if bt not in object_dict:
			object_dict[bt] = {}
		bbox_file = os.path.join(bbox_dir, 'comp4_det_demo_type_{}_{}.txt'.format(cfg['type'], bt))
		with open(bbox_file) as f:
			content = f.readlines()
		for line in content:
			fname, prob, xmin, ymin, xmax, ymax = line[:-1].split()
			frame = int(fname.split('_')[-1])
			if frame > cfg['fend'] or frame < cfg['fstart']:
				continue
			#if frame < 1080 and frame > 870:
			#	print(fname)
			if int(fname[13]) != cfg['video']:
				continue

			if fname not in object_dict[bt]:
				object_dict[bt][fname] = []
			#print(xmin, ymin, xmax, ymax)
			object_dict[bt][fname].append([float(xmin), float(ymin), float(xmax), float(ymax), float(prob)])
			#print(object_dict[bt][fname][-1])
	return object_dict

def trace(cfg):
	bbox_dir = os.path.join('../dataset', 'car_type_{}'.format(cfg['type']), 'results', 'demo_type_{}'.format(cfg['type']))

	points = []
	bbox = read_bbox(bbox_dir, cfg)

	#print(bbox['bicycle']['type_0_video_3_frame_870'])
	#print(bbox['bicycle']['type_0_video_3_frame_871'])
	#print(bbox['bicycle']['type_0_video_3_frame_872'])
	#print(bbox['bicycle']['type_0_video_3_frame_873'])
	#print(bbox['bicycle']['type_0_video_3_frame_874'])
	prev_bbox = bbox[cfg['object']]['type_{}_video_{}_frame_{}'.format(cfg['type'], cfg['video'], cfg['fstart'])][cfg['object_idx']] # 26
	print('start: ', prev_bbox)
	points.append(mid_point(prev_bbox))
	for fidx in range(cfg['fstart'] + 1, cfg['fend']):
		frame = 'type_{}_video_{}_frame_{}'.format(cfg['type'], cfg['video'], fidx)
		if frame in bbox[cfg['object']]:

			bboxs = bbox[cfg['object']][frame]
			# print(bboxs)
			best_score = 0
			best_bbox = None
			for bx in bboxs:
				score = iou(prev_bbox, bx)
				if score > best_score:
					best_bbox = copy.deepcopy(bx)
					best_score = score
			if best_bbox is None or best_score < THRES_IOU:
				# no suitable bbox, use the prev one
				best_bbox = prev_bbox

			prev_bbox = best_bbox
		print(mid_point(prev_bbox))
		points.append(mid_point(prev_bbox))
	return points

def output_video(cfg, points):
	img_dir = os.path.join('../dataset', 'car_type_{}'.format(cfg['type']), 'data', 'Images')
	# glob.glob(os.path.join(img_dir, 'type_{}_video_{}_frame_{}'.format(cfg['type'], cfg['video'])))
	pts = deque(maxlen=200)

	img = cv2.imread(os.path.join(img_dir, 'type_{}_video_{}_frame_0.png'.format(cfg['type'], cfg['video'])))
	h, w, c = img.shape
	print(img.shape)
	out = cv2.VideoWriter(os.path.join(cfg['output_dir'], 'demo_type_{}_video_{}_movement.mp4'.format(cfg['type'], cfg['video'])), 0x7634706d, 30, (w, h))
	for idx in range(len(points)):
		fidx = cfg['fstart'] + idx
		img_file = os.path.join(img_dir, 'type_{}_video_{}_frame_{}.png'.format(cfg['type'], cfg['video'], fidx))
		img = cv2.imread(img_file)

		pts.appendleft((int(points[idx][0]), int(points[idx][1])))
		for i in range(1, len(pts)):
			if pts[i - 1] is None or pts[i] is None:
				continue
			thickness = int(np.sqrt(32 / float(i + 1)) * 2.5)
			#print(thickness)
			cv2.line(img, pts[i - 1], pts[i], (0, 0, 255), thickness)
		out.write(img)
		print('write frame {} / {}'.format(idx, len(points)))
	out.release()

def main():
	args = get_args()
	cfg = {
		'type': args.type,
		'video': args.video,
		'fstart': args.start,
		'fend': args.end,
                'object': args.object,
                'object_idx': args.object_idx,
		'output_dir': args.output_dir
	}
	points = trace(cfg)

	# print('size: {}'.format(len(points)))
	# for i, p in enumerate(points):
	# 	print('frame: {}, ({}, {})'.format(i + 1, p[0], p[1]))
	output_video(cfg, points)
if __name__ == '__main__':
	main()


# -*- coding: utf-8 -*-
'''
Created on June 30, 2009

@summary: A Plex Media Server plugin that integrates trailers of French web site Allocine.
@version: 0.6
@author: Oncleben31
'''

# Import the parts of the Plex Media Server Plugin API we need
from PMS import *
from PMS.Objects import *
from PMS.Shortcuts import *
import lxml

# Plugin parameters
PLUGIN_TITLE						= "Allociné"					# The plugin Title
PLUGIN_PREFIX   					= "/video/Allocine"				# The plugin's contextual path within Plex
PLUGIN_HTTP_CACHE_INTERVAL			= 0

# Plugin Icons
PLUGIN_ICON_DEFAULT					= "icon-default.png"
PLUGIN_ICON_BA_ANEPASMANQUER		= "icon-default.png"
PLUGIN_ICON_BA_CETTESEMAINE			= "icon-default.png"
PLUGIN_ICON_BA_ALAFFICHE			= "icon-default.png"
PLUGIN_ICON_BA_PROCHAINEMENT		= "icon-default.png"
PLUGIN_ICON_PREFS					= "icon-default.png"

# Strings - Here since there is a bug with the JSON loading
ANEPASMANQUER_MENU_TITLE			= "À ne pas manquer".decode('utf-8')
ANEPASMANQUER_MENU_SUMMARY			= "Les Bandes-Annonces des films attendus".decode('utf-8')
CETTESEMAINE_MENU_TITLE			= "Sorties de la semaine".decode('utf-8')
CETTESEMAINE_MENU_SUMMARY			= "Les Bandes-Annonces des films sortis mercredi dernier.".decode('utf-8')
PROCHAINEMENT_MENU_TITLE			= "Prochainement".decode('utf-8')
PROCHAINEMENT_MENU_SUMMARY			= "Les Bandes-Annonces des films devant sortirs dans les semaines à venir.".decode('utf-8')
ALAFFICHE_MENU_TITLE				= "À l'affiche".decode('utf-8')
ALAFFICHE_MENU_SUMMARY				= "Les Bandes-Annonces des films en salle actuellement.".decode('utf-8')

# Plugin Artwork
PLUGIN_ARTWORK						= "art-default.jpg"

#Some URLs for the script
PLUGIN_URL_BA_ANEPASMANQUER			= "http://rss.allocine.fr/ac/bandesannonces/anepasmanquer"
PLUGIN_URL_BA_CETTESEMAINE			= "http://rss.allocine.fr/ac/bandesannonces/cettesemaine"
PLUGIN_URL_BA_ALAFFICHE				= "http://rss.allocine.fr/ac/bandesannonces/alaffiche"
PLUGIN_URL_BA_PROCHAINEMENT			= "http://rss.allocine.fr/ac/bandesannonces/prochainement"

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

def Start():
	# Register our plugins request handler
	Plugin.AddPrefixHandler(PLUGIN_PREFIX, MainMenu, PLUGIN_TITLE.decode('utf-8'), PLUGIN_ICON_DEFAULT, PLUGIN_ARTWORK)

	# Add in the views our plugin will support

	Plugin.AddViewGroup("Menu", viewMode="InfoList", mediaType="items")

	# Set up our plugin's container

	#MediaContainer.title1 = PLUGIN_TITLE
	MediaContainer.title1 = PLUGIN_TITLE.decode('utf-8')
	MediaContainer.viewGroup = "Menu"
	MediaContainer.art = R(PLUGIN_ARTWORK)

	# Configure HTTP Cache lifetime

#	HTTP.SetCacheTime(PLUGIN_HTTP_CACHE_INTERVAL)

####################################################################################################
# The plugin's main menu.

def MainMenu():
	dir = MediaContainer(art = R(PLUGIN_ARTWORK), viewGroup = "Menu")
	dir.Append(Function(DirectoryItem(ListeANePasManquer, title=ANEPASMANQUER_MENU_TITLE, thumb=R(PLUGIN_ICON_BA_ANEPASMANQUER), summary=ANEPASMANQUER_MENU_SUMMARY)))
	dir.Append(Function(DirectoryItem(ListeCetteSemaine, title=CETTESEMAINE_MENU_TITLE, thumb=R(PLUGIN_ICON_BA_CETTESEMAINE), summary=CETTESEMAINE_MENU_SUMMARY)))
	dir.Append(Function(DirectoryItem(ListeALAffiche, title=ALAFFICHE_MENU_TITLE, thumb=R(PLUGIN_ICON_BA_ALAFFICHE), summary=ALAFFICHE_MENU_SUMMARY)))
	dir.Append(Function(DirectoryItem(ListeProchainement, title=PROCHAINEMENT_MENU_TITLE, thumb=R(PLUGIN_ICON_BA_PROCHAINEMENT), summary=PROCHAINEMENT_MENU_SUMMARY)))

	return dir

####################################################################################################
# The A Ne pas Manquer menu
def TraiteFluxRSS(urlFluxRSS, titreFluxRSS):
	dir = MediaContainer(art = R(PLUGIN_ARTWORK), viewGroup = "Menu", title2 = titreFluxRSS)

	fluxXML = XML.ElementFromURL(urlFluxRSS, encoding="iso-8859-1")

	for c in fluxXML.xpath("//item"):
		titleEtSubtitle = c.find('title').text.encode("iso-8859-1").rsplit(' - ',1)
		title = titleEtSubtitle[0]
		subtitle = titleEtSubtitle[1]
		thumb = c.find('enclosure').get('url')

		urlFlv = "http://hd.fr.mediaplayer.allocine.fr/nmedia/" + thumb.rsplit("acmedia/medias/nmedia/")[1].rsplit(".jpg")[0] + "_hd_001.flv"
		Log("urlFlv %s" % (urlFlv.encode("utf8")))

		urlDescription = "http://www.allocine.fr/film/fichefilm_gen_cfilm=" + c.find('link').text.rsplit("cfilm=")[1]
		Log("urlDescription %s" % (urlDescription.encode("utf8")))

		pageFilm = XML.ElementFromURL(urlDescription, isHTML=True, encoding="utf-8")
		divDescription = pageFilm.xpath('//p[contains(., "Synopsis :")]')
		description = divDescription[0].xpath("string()").rsplit("Synopsis :")[1]

		dir.Append(VideoItem(urlFlv, title=title.decode("utf-8"), subtitle=subtitle.decode("utf-8"), summary=description.decode("utf-8"), thumb=thumb))

	return dir

####################################################################################################
# The A Ne pas Manquer menu
def ListeANePasManquer(sender):
	dir = TraiteFluxRSS(PLUGIN_URL_BA_ANEPASMANQUER, ANEPASMANQUER_MENU_TITLE)
	return dir

####################################################################################################
# The Cette Semaine menu
def ListeCetteSemaine(sender):
	dir = TraiteFluxRSS(PLUGIN_URL_BA_CETTESEMAINE, CETTESEMAINE_MENU_TITLE)
	return dir

####################################################################################################
# The A L'Affichie menu
def ListeALAffiche(sender):
	dir = TraiteFluxRSS(PLUGIN_URL_BA_ALAFFICHE, ALAFFICHE_MENU_TITLE)
	return dir

####################################################################################################
# The Prochainement menu
def ListeProchainement(sender):
	dir = TraiteFluxRSS(PLUGIN_URL_BA_PROCHAINEMENT, PROCHAINEMENT_MENU_TITLE)
	return dir

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


import json

from time import sleep
from threading import Thread
from logger import Logger
log = Logger.getInstance().getLogger()

class DeviceEvents(Thread):

    def __init__(self,
                 lock,
                 event_queue,
                 device_hash):
        Thread.__init__(self)
        self.setDaemon(True)
        self.lock = lock
        self.event_queue = event_queue
        self.device_hash = device_hash

    def process_entry(self, msg) -> int:
        topic = msg.topic

        if topic not in self.device_hash:
            # log.debug(("{} is not "
            #           "in device hash").format(topic))
            return 0

        payload = json.loads(msg.payload.decode("utf-8"))
        self.device_hash[topic].refresh_device_data(payload)
        device = self.device_hash[topic]
        log.debug("\n{0}\n".format(device))

        rc = 0
        try:
            rc = device.process()
        except Exception as e:
            log.error(e)
            rc = -1

        return rc

    def process_events(self):
        if not self.event_queue.empty():
            self.lock.acquire()
            msg = self.event_queue.get()
            self.lock.release()
            rc = self.process_entry(msg)
            if rc != 0:
                log.error("Failed to process entry {0}".format(
                    rc
                ))

    def run(self):
        while True:
            if self.event_queue:
                self.process_events()
            sleep(1)


import logging
from pathlib import Path
from typing import Literal

from pydantic_settings import BaseSettings

class Settings(BaseSettings):
    # ---------------------------------------------------
    # Startup parameters
    # ---------------------------------------------------
    restore_persisted_state: bool = True
    log_level: int = logging.DEBUG

    # ---------------------------------------------------
    # CORS
    # ---------------------------------------------------
    cors_origins: list = ["*"]

    # ---------------------------------------------------
    # Redis
    # ---------------------------------------------------
    redis_host: str = "localhost"
    redis_port: int = 6379

    # ---------------------------------------------------
    # Travel
    # ---------------------------------------------------
    travel_tick_seconds: float = 0.3

    # ---------------------------------------------------
    # Sonar
    # ---------------------------------------------------
    serenity_name: str = "Serenity"
    serenity_hp: int = 3
    sonar_starting_distance: int = 8
    sonar_map_width: int = 15
    sonar_map_height: int = 15
    sonar_map_file_name: Literal["default"] = "default"
    sonar_spawn_margin: int = 2
    sonar_torpedo_damage: int = 2
    sonar_torpedo_reach: int = 4
    sonar_torpedo_radius: int = 2
    sonar_mine_damage: int = 2
    sonar_mine_reach: int = 4
    sonar_mine_radius: int = 2
    sonar_player_default_hp: int = 4
    sonar_use_control_panel: bool= True

    # ---------------------------------------------------
    # Paths
    # ---------------------------------------------------
    package_dir: Path = Path(__file__).parents[1]
    planetary_config_path: Path = package_dir / "defaults/planet_graph.json"
    asteroid_map_dir: Path = package_dir / "defaults/maps/"
    switches_path: Path = package_dir / "defaults/switches.json"

    class Config:
        env_prefix = "serenity_"
        env_file = ".env"
        env_file_encoding = "utf-8"

settings = Settings()


# you can write to stdout for debugging purposes, e.g.
# print("this is a debug message")

def solution(A):
    # write your code in Python 3.6
    N = len(A)+1
    missing = N
    for i in range(1, N):
        missing ^= A[i-1]
        missing ^= i

    return missing

Lesson 03 - Time Complexity/PermMissingElem_2.py


import numpy as np
import matplotlib.pyplot as plt
from PIL import Image

# Define the image name
inputimage = 'static/img/1.tif'
# Load the imagef
img = Image.open(inputimage)

img = np.asarray(img)
img2 = img
for i in range(3):
    img2 = np.concatenate((img2, np.rot90(img, i+1)), axis=1)
# Prepare figure window
plt.figure()
# Show image on the window
plt.imshow(img2, cmap='gray')
# Show the window
plt.show()


import time
import requests
from scrapy import Selector

headers = {
    "Accept": 'text/html, application/xhtml+xml, application/xml; q=0.9, */*; q=0.8',
    # "Accept-Encoding": 'gzip, deflate, br',
    "Accept-Language": 'zh-CN,zh;q=0.9',
    "Cache-Control": 'max-age=0',
    "Cookie": 'cf_clearance=ea2b3e04bded706ff7978fbd92b61bf163c91469-1579604232-0-250; __cfduid=d5da5233bff7d49a3203df0474113ca6e1579604232; ALs=dc5f533d31714acc3cd3672cc582d2c1; _ga=GA1.2.1517880621.1579604339; _gid=GA1.2.1272238848.1579604339',
    "Host": 'www.addustour.com',
    "Upgrade-Insecure-Requests": '1',
    "User-Agent": 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36'
    }

def get_news(news_url, prefix):
    s = requests.Session()
    s.keep_alive = False  # 关闭多余连接
    repeat = 10
    while repeat:
        try:
            resp = s.get(news_url, headers=headers, verify=False, timeout=20)
            break
        except:
            print('trying:', repeat)
            repeat -= 1
            time.sleep(3)
    if repeat == 0:
        return
    resp.encoding = 'UTF-8'
    sel = Selector(resp)
    title = sel.xpath('//*[@id="article_title"]/h2/text()').extract_first()
    contents = sel.xpath('//*[@id="article_text"]/p//text()').extract()
    content = "\n".join(contents) if contents else ""
    target_file = 'addustour/' + prefix + '.txt'
    print(news_url)
    print(title)
    print("==================")
    with open(target_file, 'a', encoding='utf-8') as t:
        if title:
            t.write(title)
            t.write('\n')
        if content:
            t.write(content)
            t.write('\n')
    now_day = time.strftime("%Y-%m-%d", time.localtime())
    target_file = 'addustour/' + 'count_' + now_day + '.txt'
    with open(target_file, 'a', encoding='utf-8') as t:
        if content:
            t.write(news_url)
            t.write('\n')

def get_urls(url):
    s = requests.Session()
    s.keep_alive = False  # 关闭多余连接
    repeat = 10
    while repeat:
        try:
            resp = s.get(url, headers=headers, verify=False, timeout=20)
            break
        except:
            print('trying:', repeat)
            repeat -= 1
            time.sleep(3)
    if repeat == 0:
        return
    resp.encoding='UTF-8'
    sel = Selector(resp)
    info_urls = sel.xpath('//*[@id="al-right"]/div[2]/ul/li/a/@href').extract()
    if not info_urls:
        raise ValueError("cookie 失效！")

    news_urls = []
    for info_url in info_urls:
        news_url = "https://www.addustour.com" + info_url.replace("../..","")
        news_urls.append(news_url)

    return news_urls

if __name__ == '__main__':
    requests.adapters.DEFAULT_RETRIES = 10  # 增加重连次数
    requests.packages.urllib3.disable_warnings()
    categories = [('1-%D9%85%D8%AD%D9%84%D9%8A%D8%A7%D8%AA', 17895),
                  ('2-%D9%85%D8%AD%D8%A7%D9%81%D8%B8%D8%A7%D8%AA', 3056),
                  ('4-%D8%A7%D9%82%D8%AA%D8%B5%D8%A7%D8%AF', 6062),
                  ('5-%D8%B9%D8%B1%D8%A8%D9%8A-%D9%88%D8%AF%D9%88%D9%84%D9%8A', 9024),
                  ('7-%D8%B1%D9%8A%D8%A7%D8%B6%D8%A9', 7476),
                  ('3-%D8%AB%D9%82%D8%A7%D9%81%D8%A9', 2719),
                  ('6-%D8%AF%D8%B1%D9%88%D8%A8', 4520),
                  ('32-%D8%B4%D8%A8%D8%A7%D8%A8', 9),
                  ('33-%D8%AC%D8%A7%D9%85%D8%B9%D8%A7%D8%AA', 58)]
    for cid, category in enumerate(categories):
        base_url = 'https://www.addustour.com/categories/' + category[0]
        if cid == 0:
            start = 4502
        else:
            start = 1
        for i in range(start, category[1]+1):
            url = base_url + "/page" + str(i)
            prefix = category[0].split('-')[0] + '_' + str(i)
            news_urls = get_urls(url)
            for news_url in news_urls:
                get_news(news_url, prefix)
                time.sleep(1)
            time.sleep(1)


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Thu Jun 18 20:49:41 2020

@author: chenshihti
"""

import requests #引入api函數
import json
#想要爬資料的 標網址
r= requests.get('https://www.dcard.tw/_api/forums/job/posts?popular=true')

response1=r.text
response2=json.loads(r.text)

for i in response2:
    print (i['excerpt'])


import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import LabelEncoder
import pickle
import pandas as pd
from sklearn.metrics import accuracy_score

def feature_scaling(X, a, b):
    X = np.array(X)
    Normalized_X = np.zeros((X.shape[0], X.shape[1]))
    for i in range(X.shape[1]):
        Normalized_X[:, i] = ((X[:, i] - min(X[:, i])) / (max(X[:, i]) - min(X[:, i]))) * (b - a) + a
    return Normalized_X

def feature_encoder(X):
    lbl = LabelEncoder()
    lbl.fit(list(X.values))
    X = lbl.transform(list(X.values))
    return X

data = pd.read_csv("VideoLikesDatasetClassification.csv")

#data.dropna(how='any', inplace=True)
data["tags"].fillna("[none]", inplace=True)
data['views'].fillna(int((data['views'].mean())), inplace=True)
data['comment_count'].fillna(int((data['comment_count'].mean())), inplace=True)
data['category_id'].fillna((data['category_id'].max()), inplace=True)

data["video_id"] = feature_encoder(data["video_id"])
data["title"] = feature_encoder(data["title"])
data["channel_title"] = feature_encoder(data["channel_title"])
data["comments_disabled"] = feature_encoder(data["comments_disabled"])
data["ratings_disabled"] = feature_encoder(data["ratings_disabled"])
data["video_error_or_removed"] = feature_encoder(data["video_error_or_removed"])
data["tags"] = feature_encoder(data["tags"])
data["VideoPopularity"] = feature_encoder(data["VideoPopularity"])

# Correlation matrix to help us in features selection
corr_matrix = data.corr()
best_features = corr_matrix.index[abs(corr_matrix['VideoPopularity']) > 0.04]
best_features = best_features.delete(-1)
X = data[best_features]
X = feature_scaling(X, 0, 100)
Y = data[['VideoPopularity']].iloc[:, :]
Y = feature_scaling(Y, 0, 100)
Y = Y.flatten()
X_train, X_test, y_train, y_test = train_test_split(X, Y, test_size=0.20, random_state=1)

filename = 'LogisticRegression.sav'
# load the model from disk
LogisticRegression = pickle.load(open(filename, 'rb'))
y_pred = LogisticRegression.predict(X_test)
logisticRegressionAccuracy = accuracy_score(y_pred, y_test)
print('Logistic Regression Accuracy', logisticRegressionAccuracy)
print("-----------------------------------------------------------------------------")

filename = 'SVMPolynomial.sav'
# load the model from disk
SVMPolynomial = pickle.load(open(filename, 'rb'))
y_pred = SVMPolynomial.predict(X_test)
SVMPolykernelAccuracy = accuracy_score(y_pred, y_test)
print('SVM with Polynomial kernel Accuracy', SVMPolykernelAccuracy)
print("-----------------------------------------------------------------------------")

filename = 'decisionTree.sav'
# load the model from disk
decisionTree = pickle.load(open(filename, 'rb'))
y_pred = decisionTree.predict(X_test)
decisionTreeAccuracy = accuracy_score(y_pred, y_test)
print('Decision Tree Accuracy', decisionTreeAccuracy)

print("-----------------------------------------------------------------------------")
filename = 'SVMRBFkernel.sav'
# load the model from disk
loaded_model = pickle.load(open(filename, 'rb'))
y_pred = loaded_model.predict(X_test)
SVMRBFkernelAccuracy = accuracy_score(y_pred, y_test)
print('SVM with Gaussian(RBF) kernel Accuracy', SVMRBFkernelAccuracy)


import random
import pygame

pygame.init()

display_width = 800
display_height = 600

display = pygame.display.set_mode((display_width, display_height))
pygame.display.set_caption('Poker')

icon = pygame.image.load('icon.png')
pygame.display.set_icon(icon)

bank = 0
Max_points = 0
Player1_points = 0
Player2_points = 0

clock = pygame.time.Clock()
current_time = 0

need_input = False
input_text = '|'
input_tick = 30

player_name = ''

class Card:
    def __init__(self, val, suit, image, x, y, points, set):
        self.val = val
        self.suit = suit
        self.image = image
        self.x = x
        self.y = y
        self.points = points
        self.set = set

    def __repr__(self):
        return repr(self.val + ' ' + self.suit)

class Button:
    def __init__(self, width, height):
        self.width = width
        self.height = height
        self.inactive_color = (142, 142, 142)
        self.active_color = (195, 195, 195)
        self.active = False

    def draw(self, x, y, message, action, font_color=(0, 0, 0), font_size=30, h=0, w=0):
        mouse = pygame.mouse.get_pos()
        click = pygame.mouse.get_pressed(3)

        if x < mouse[0] < x + self.width and y < mouse[1] < y + self.height:
            pygame.draw.rect(display, self.active_color, (x, y, self.width, self.height))

            if click[0] == 1:
                if action is not None:
                    self.active = True
                    if action == quit:
                        pygame.quit()
                        quit()
                    else:
                        action()
                        self.active = False

        else:
            pygame.draw.rect(display, self.inactive_color, (x, y, self.width, self.height))

        output_text(message=message, x=x + w, y=y + h, font_color=font_color, font_size = font_size)

Card_values = ['2', '3', '4', '5', '6', '7', '8', '9', '10', 'Jack', 'Queen', 'King', 'Ace']
Card_suits = ['Clubs', 'Diamonds', 'Hearts', 'Spades']
Cards_img = pygame.image.load('Cards.png')
Combination = {'High card': 1, 'Pair': 2, 'Two pair': 3, 'Three of a Kind': 4, 'Straight': 5, 'Flush': 6, 'Full House': 7, 'Four of a Kind': 8, 'Straight-flush': 9, 'Royal Flush': 10}
results = {'p1': 0, 'p1 points': 0, 'p2': 0, 'p2 points': 0}

def show_menu():
    menu_background = pygame.image.load('Menu_background.png')

    settings_btn = Button(190, 80)
    quit_btn = Button(190, 80)

    show = True
    while show:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                quit()

        display.blit(menu_background, (0, 0))
        settings_btn.draw(display_width/2 - 190/2, display_height/2 - 65, 'Играть', settings, (0, 0, 0), 50, 10, 20)
        quit_btn.draw(display_width/2 - 190/2, display_height/2 + 40, 'Выход', quit, (0, 0, 0), 50, 10, 20)

        pygame.display.update()
        clock.tick(60)

def start_game():
    if Max_points > 0:
        while game_cycle():
            pass

def game_cycle():

    global Player1_cards
    global Player2_cards
    global Table_cards
    global Cards
    global Player1_points
    Cards = []

    run = True
    background = pygame.image.load('Table.png')

    for i in range(len(Card_values)):
        for j in range(len(Card_suits)):
            rect = (80 * i, 120 * j, 80, 120)
            img = Cards_img.subsurface(rect)
            Cards.append(Card(Card_values[i], Card_suits[j], img, 0, 0, i + 2, ''))

    Player1_cards = create_set('p1')
    Player2_cards = create_set('p2')
    Table_cards = create_set('t')

    output(Player1_cards, Player2_cards, Table_cards)

    while run:

        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                quit()

        display.blit(background, (0, 0))
        draw_players_cards()
        draw_table_cards()

        output_text(str(Player1_points), 10, 560, (0, 0, 0))
        output_text(str(Player2_points), 10, 10, (0, 0, 0))
        output_text('Банк: ' + str(bank), 10, 275, (0, 0, 0))
        output_text(player_name, 55, 480, (255, 255, 255), font_size=35)

        auction()

        pygame.display.update()

        if len(Table_cards) == 5:
            pygame.time.wait(10000)
            if Player1_points == 0 or Player2_points == 0:
                run = False
            else:
                start_game()

    return end_game()

def settings():

    bckgrnd = pygame.image.load('settings_bg.png')
    settings = True

    global plus_100_btn
    global plus_200_btn
    global plus_500_btn
    global plus_1000_btn
    global  plus_2000_btn

    global minus_100_btn
    global minus_200_btn
    global minus_500_btn
    global minus_1000_btn
    global minus_2000_btn

    global equally_0_btn

    plus_100_btn = Button(90, 40)
    plus_200_btn = Button(90, 40)
    plus_500_btn = Button(90, 40)
    plus_1000_btn = Button(90, 40)
    plus_2000_btn = Button(90, 40)

    minus_100_btn = Button(90, 40)
    minus_200_btn = Button(90, 40)
    minus_500_btn = Button(90, 40)
    minus_1000_btn = Button(90, 40)
    minus_2000_btn = Button(90, 40)

    equally_0_btn = Button(60, 40)
    start_btn = Button(130, 50)

    while settings:

        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                quit()

        display.blit(bckgrnd, (0, 0))

        output_text('Введите ваше имя и нажмите Enter', 175, 300, (50, 50, 50), font_size=30)
        output_text('Ваше имя: ' + player_name, 175, 430, (50, 50, 50), font_size=30)
        output_text('Количество очков у игрока: ' + str(Max_points), 150, 30, (0, 0, 0), font_size=40)

        plus_100_btn.draw(90, 100, '+ 100', setting, (0, 0, 0), 20, 10, 20)
        plus_200_btn.draw(200, 100, '+ 200', setting, (0, 0, 0), 20, 10, 20)
        plus_500_btn.draw(310, 100, '+ 500', setting, (0, 0, 0), 20, 10, 20)
        plus_1000_btn.draw(420, 100, '+ 1000', setting, (0, 0, 0), 20, 10, 20)
        plus_2000_btn.draw(530, 100, '+ 2000', setting, (0, 0, 0), 20, 10, 20)

        minus_100_btn.draw(90, 170, '- 100', setting, (0, 0, 0), 20, 10, 20)
        minus_200_btn.draw(200, 170, '- 200', setting, (0, 0, 0), 20, 10, 20)
        minus_500_btn.draw(310, 170, '- 500', setting, (0, 0, 0), 20, 10, 20)
        minus_1000_btn.draw(420, 170, '- 1000', setting, (0, 0, 0), 20, 10, 20)
        minus_2000_btn.draw(530, 170, '- 2000', setting, (0, 0, 0), 20, 10, 20)

        equally_0_btn.draw(660, 135, '= 0', setting, (0, 0, 0), 20, 10, 20)

        start_btn.draw(660, 540, 'Начать', start_game, (0, 0, 0), h=10, w=20)

        get_input()

        pygame.display.update()

def auction():

    pygame.time.wait(1000)

    global run_auction
    global bet
    global plus_10_btn
    global minus_10_btn
    global all_in_btn
    global time

    run_auction = True

    bet = 0

    create_bet = Button(90, 35)
    plus_10_btn = Button(40, 40)
    minus_10_btn = Button(40, 40)
    all_in_btn = Button(80, 35)
    check_btn = Button(80, 35)

    while run_auction:

        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                quit()

        pygame.draw.rect(display, (255, 255, 255), (670, 430, 70, 40))

        output_text(str(bet), 675, 435, (0, 0, 0))

        if Player1_points > 0:
            create_bet.draw(660, 480, 'сделать', end_auction, (0, 0, 0), 15, w=20)
            output_text('ставку', 683, 495, (0, 0, 0), font_size=15)
            minus_10_btn.draw(620, 430, '-10', calculate, font_size=20, h=10, w=5)
            plus_10_btn.draw(750, 430, '+10', calculate, font_size=20, h=10, w=5)
            all_in_btn.draw(620, 550, 'Ва-банк', calculate, (0, 0, 0), 15, h=10, w=12)
        else:
            create_bet.draw(660, 480, 'сделать', None, (0, 0, 0), 15, w=20)
            output_text('ставку', 683, 495, (0, 0, 0), font_size=15)
            minus_10_btn.draw(620, 430, '-10', None, font_size=20, h=10, w=5)
            plus_10_btn.draw(750, 430, '+10', None, font_size=20, h=10, w=5)
            all_in_btn.draw(620, 550, 'Ва-банк', None, (0, 0, 0), 15, h=10, w=12)

        check_btn.draw(710, 550, 'Чек', end_auction, (0, 0, 0), 15, h=10, w=25)

        pygame.display.update()

def calculate():

    global bet

    if plus_10_btn.active and bet < Player1_points:
        bet += 10

    if minus_10_btn.active and bet > 0:
        bet -= 10

    if all_in_btn.active:
        bet = Player1_points
        end_auction()

    pygame.time.wait(300)

def end_auction():

    global run_auction
    global bank
    global Player1_points

    bank += bet
    Player1_points -= bet

    if bet > 0:
        output_text('-' + str(bet), 80, 560, (0, 0, 0))

    run_auction = False
    pygame.time.wait(5000)
    new_card()

def setting():

    global Max_points
    global Player1_points
    global Player2_points

    if plus_100_btn.active == True:
        Max_points += 100

    elif plus_200_btn.active == True:
        Max_points += 200

    elif plus_500_btn.active == True:
        Max_points += 500

    elif plus_1000_btn.active == True:
        Max_points += 1000

    elif plus_2000_btn.active == True:
        Max_points += 2000

    elif minus_100_btn.active == True and Max_points - 100 >= 0:
        Max_points -= 100

    elif minus_200_btn.active == True and Max_points - 200 >= 0:
        Max_points -= 200

    elif minus_500_btn.active == True and Max_points - 500 >= 0:
        Max_points -= 500

    elif minus_1000_btn.active == True and Max_points - 1000 >= 0:
        Max_points -= 1000

    elif minus_2000_btn.active == True and Max_points - 2000 >= 0:
        Max_points -= 2000

    elif equally_0_btn.active == True:
        Max_points = 0

    Player1_points = Max_points
    Player2_points = Max_points

    pygame.time.wait(300)

def get_input():
    global input_text, need_input, player_name, input_tick

    input_rect = pygame.Rect(225, 350, 350, 60)

    pygame.draw.rect(display, (255, 255, 255), input_rect)

    mouse = pygame.mouse.get_pos()
    click = pygame.mouse.get_pressed(3)

    if input_rect.collidepoint(mouse[0], mouse[1]) and click[0]:
        need_input = True

    if need_input:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                quit()

            if need_input and event.type == pygame.KEYDOWN:
                input_text = input_text.replace('|', '')
                input_tick = 30

                if event.key == pygame.K_RETURN:
                    need_input = False
                    player_name = input_text
                    input_text = ''
                    print(player_name)
                elif event.key == pygame.K_BACKSPACE:
                    input_text = input_text[:-1]
                else:
                    if len(input_text) < 10:
                        input_text += event.unicode

                input_text += '|'

    if len(input_text):
        output_text(input_text, input_rect.x + 10, input_rect.y + 10, (0, 0, 0), font_size=40)

    input_tick -= 1

    if input_tick == 0:
        input_text = input_text[:-1]
    if input_tick == -30:
        input_text += '|'
        input_tick = 30

def rand_card():
    choice = random.randrange(0, len(Cards))
    card = Cards[choice]
    del Cards[choice]
    return card

def create_set(a):
    mass = []
    for i in range(2):
        card = rand_card()
        card.set = a
        mass.append(card)
    return mass

def new_card():
    card = rand_card()
    card.set = 't'
    Table_cards.append(card)
    print(repr(Table_cards[-1]))
    display.blit(Table_cards[-1].image,(Table_cards[-2].x - 100, Table_cards[-2].y))

def output(Player1_cards, Player2_cards, Table_cards):
    print('Player1: ', end="")
    for i in range(0, len(Player1_cards)):
        print('|' + repr(Player1_cards[i]) + '| ', end="")

    print('\n', 'Table: ', end="", sep="")
    for i in range(0, len(Table_cards)):
        print('|' + repr(Table_cards[i]) + '| ', end="")

    print('\n', 'Player2: ', end="", sep="")
    for i in range(0, len(Player2_cards)):
        print('|' + repr(Player2_cards[i]) + '| ', end="")

    print('\n')

def draw_players_cards():
    for i in range(2):
        display.blit(Player1_cards[i].image, ((display_width/2)-90+100*i, 470))
        Player1_cards[i].x = (display_width/2)-90+100*i
        Player1_cards[i].y = 470
        display.blit(Player2_cards[i].image, ((display_width/2)-90+100*i, 10))
        Player2_cards[i].x = (display_width/2)-90+100*i
        Player2_cards[i].y = 10

def draw_table_cards():
    for i in range(len(Table_cards)):
        display.blit(Table_cards[i].image, ((display_width / 2) + 160 - 100 * i, (display_height / 2) - 60))
        Table_cards[i].x = (display_width / 2) + 160 - 100 * i
        Table_cards[i].y = (display_height / 2) - 60

def new_mass(mass1, mass2):
    Mass = []
    for i in range(len(mass1)):
        Mass.append(mass1[i])

    for i in range(len(mass2)):
        Mass.append(mass2[i])

    sorted_mass = sort_mass(Mass)
    return sorted_mass

def sort_mass(Tab_and_p):
    for i in range(len(Tab_and_p) - 1):
        for j in range(len(Tab_and_p) - i - 1):
            if Tab_and_p[j].points > Tab_and_p[j + 1].points:
                Tab_and_p[j], Tab_and_p[j + 1] = Tab_and_p[j + 1], Tab_and_p[j]

    print('\n')
    for i in range(len(Tab_and_p)):
        print(repr(Tab_and_p[i]) + ' ')

    return Tab_and_p

def check(Player_cards, Table_cards):

    global results
    Tab_and_p = new_mass(Player_cards, Table_cards)

#Алгоритм поиска Старшей карты
    for i in range(-1, -1*len(Tab_and_p), -1):
        if (Tab_and_p[i].set != 't'):
            if (Player_cards == Player1_cards):
                results['p1'] = Combination['High card']
                results['p1 points'] = Tab_and_p[i].points
            elif (Player_cards == Player2_cards):
                results['p2'] = Combination['High card']
                results['p2 points'] = Tab_and_p[i].points
            print('Старшая карта')
            break

#Алгоритм поиска Пары карт
    for i in range(1, len(Tab_and_p)):
        if (Tab_and_p[i].val == Tab_and_p[i-1].val and Tab_and_p[i].set != Tab_and_p[i-1].set):
            if (Player_cards == Player1_cards):
                results['p1'] = Combination['Pair']
                results['p1 points'] = (Tab_and_p[i].points + Tab_and_p[i-1].points)
            elif (Player_cards == Player2_cards):
                results['p2'] = Combination['Pair']
                results['p2 points'] = (Tab_and_p[i].points + Tab_and_p[i-1].points)
            print('Пара')
            break

#Алгоритм поиска Двух Пар карт
    for i in range(1, len(Tab_and_p)):
        if (Tab_and_p[i].val == Tab_and_p[i-1].val and Tab_and_p[i].set != Tab_and_p[i-1].set):
            for j in range(i+2, len(Tab_and_p)):
                if (Tab_and_p[j].val == Tab_and_p[j - 1].val and Tab_and_p[j].set != Tab_and_p[j - 1].set):
                    if (Player_cards == Player1_cards):
                        results['p1'] = Combination['Two pair']
                        results['p1 points'] = Tab_and_p[j].points + Tab_and_p[j-1].points + Tab_and_p[i].points + Tab_and_p[i-1].points
                    elif (Player_cards == Player2_cards):
                        results['p2'] = Combination['Two pair']
                        results['p2 points'] += Tab_and_p[j].points + Tab_and_p[j-1].points + Tab_and_p[i].points + Tab_and_p[i-1].points
                print('Две Пары')
            break

#Алгоритм поиска Тройки(Сета)
    for i in range(2, len(Tab_and_p)):
        if ((Tab_and_p[i].val == Tab_and_p[i - 1].val and Tab_and_p[i].val == Tab_and_p[i - 2].val) and (Tab_and_p[i].set != 't' or Tab_and_p[i-1].set != 't' or Tab_and_p[i-2].set != 't')):
            if (Player_cards == Player1_cards):
                results['p1'] = Combination['Three of a Kind']
                results['p1 points'] = Tab_and_p[i].points + Tab_and_p[i-1].points + Tab_and_p[i-2].points
            elif (Player_cards == Player2_cards):
                results['p2'] = Combination['Three of a Kind']
                results['p2 points'] = Tab_and_p[i].points + Tab_and_p[i-1].points + Tab_and_p[i-2].points
            print('Тройка')

#Алгоритм поиска Стрита
    for i in range(4, len(Tab_and_p)):
        if ((Tab_and_p[i].points == Tab_and_p[i-1].points + 1) and (Tab_and_p[i].points == Tab_and_p[i-2].points + 2) and (Tab_and_p[i].points == Tab_and_p[i-3].points + 3) and (Tab_and_p[i].points == Tab_and_p[i-4].points + 4) and (Tab_and_p[i].set != 't' or Tab_and_p[i-1].set != 't' or Tab_and_p[i-2].set != 't' or Tab_and_p[i-3].set != 't' or Tab_and_p[i-4].set != 't')):
            if (Player_cards == Player1_cards):
                results['p1'] = Combination['Straight']
                results['p1 points'] = Tab_and_p[i].points + Tab_and_p[i-1].points + Tab_and_p[i-2].points + Tab_and_p[i-3].points + Tab_and_p[i-4].points
            elif (Player_cards == Player2_cards):
                results['p2'] = Combination['Straight']
                results['p2 points'] = Tab_and_p[i].points + Tab_and_p[i-1].points + Tab_and_p[i-2].points + Tab_and_p[i-3].points + Tab_and_p[i-4].points
            print('Стрит')

#Алгоритм поиска Флэша
    for i in range(4, len(Tab_and_p)):
        if ((Tab_and_p[i].suit == Tab_and_p[i-1].suit) and (Tab_and_p[i].suit == Tab_and_p[i-2].suit) and (Tab_and_p[i].suit == Tab_and_p[i-3].suit) and (Tab_and_p[i].suit == Tab_and_p[i-4].suit) and (Tab_and_p[i].set != 't' or Tab_and_p[i-1].set != 't' or Tab_and_p[i-2].set != 't' or Tab_and_p[i-3].set != 't' or Tab_and_p[i-4].set != 't')):
            if (Player_cards == Player1_cards):
                results['p1'] = Combination['Flush']
                results['p1 points'] = Tab_and_p[i].points + Tab_and_p[i-1].points + Tab_and_p[i-2].points + Tab_and_p[i-3].points + Tab_and_p[i-4].points
            elif (Player_cards == Player2_cards):
                results['p2'] = Combination['Flush']
                results['p2 points'] = Tab_and_p[i].points + Tab_and_p[i-1].points + Tab_and_p[i-2].points + Tab_and_p[i-3].points + Tab_and_p[i-4].points
            print('Флэш')

#Алгоритм поиска Фулл Хауса, начиная с Пары
    for i in range(1, len(Tab_and_p)):
        if (Tab_and_p[i].val == Tab_and_p[i-1].val and Tab_and_p[i].set != Tab_and_p[i-1].set):
            if (len(Tab_and_p) - 1 - i > 2):
                for j in range(i+3, len(Tab_and_p)):
                    if ((Tab_and_p[j].val == Tab_and_p[j - 1].val and Tab_and_p[j].val == Tab_and_p[j - 2].val) and (Tab_and_p[j].set != 't' or Tab_and_p[j-1].set != 't' or Tab_and_p[j-2].set != 't')):
                        if (Player_cards == Player1_cards):
                            results['p1'] = Combination['Full House']
                            results['p1 points'] = Tab_and_p[i].points + Tab_and_p[i - 1].points + Tab_and_p[j].points + Tab_and_p[j - 1].points + Tab_and_p[j - 2].points
                        elif (Player_cards == Player2_cards):
                            results['p2'] = Combination['Full House']
                            results['p2 points'] = Tab_and_p[i].points + Tab_and_p[i - 1].points + Tab_and_p[j].points + Tab_and_p[j - 1].points + Tab_and_p[j - 2].points
                        print('Фулл Хаус')

#Алгоритм поиска Фулл Хауса, начиная с Тройки(Сета)
    for i in range(2, len(Tab_and_p)):
        if ((Tab_and_p[i].val == Tab_and_p[i - 1].val and Tab_and_p[i].val == Tab_and_p[i - 2].val) and (Tab_and_p[i].set != 't' or Tab_and_p[i-1].set != 't' or Tab_and_p[i-2].set != 't')):

            if (len(Tab_and_p) - 1 - i > 1):
                for j in range(i+2, len(Tab_and_p)):
                    if (Tab_and_p[j].val == Tab_and_p[j - 1].val and Tab_and_p[j].set != Tab_and_p[j - 1].set):
                        if (Player_cards == Player1_cards):
                            results['p1'] = Combination['Full House']
                            results['p1 points'] = Tab_and_p[j].points + Tab_and_p[j - 1].points + Tab_and_p[i].points + Tab_and_p[i - 1].points + Tab_and_p[i - 2].points
                        elif (Player_cards == Player2_cards):
                            results['p2'] = Combination['Full House']
                            results['p2 points'] = Tab_and_p[j].points + Tab_and_p[j - 1].points + Tab_and_p[i].points + Tab_and_p[i - 1].points + Tab_and_p[i - 2].points
                        print('Фулл Хаус')

#Алгоритм поиска Каре
    for i in range(3, len(Tab_and_p)):
        if ((Tab_and_p[i].val == Tab_and_p[i-1].val and Tab_and_p[i].val == Tab_and_p[i-2].val and Tab_and_p[i].val == Tab_and_p[i-3].val) and (Tab_and_p[i] != 't' or Tab_and_p[i-1] != 't' or Tab_and_p[i-2] != 't' or Tab_and_p[i-3] != 't')):
            if (Player_cards == Player1_cards):
                results['p1'] = Combination['Four of a Kind']
                results['p1 points'] = Tab_and_p[i].points + Tab_and_p[i - 1].points + Tab_and_p[i-2].points + Tab_and_p[i - 3].points
            elif (Player_cards == Player2_cards):
                results['p2'] = Combination['Four of a Kind']
                results['p2 points'] = Tab_and_p[i].points + Tab_and_p[i - 1].points + Tab_and_p[i-2].points + Tab_and_p[i - 3].points
            print('Каре')

#Алгоритм поиска Стрит-Флэша
    for i in range(4, len(Tab_and_p)):
        if ((Tab_and_p[i].points == Tab_and_p[i-1].points - 1 and Tab_and_p[i].points == Tab_and_p[i-2].points - 2 and Tab_and_p[i].points == Tab_and_p[i-3].points - 3 and Tab_and_p[i].points == Tab_and_p[i-4].points - 4) and (Tab_and_p[i].suit == Tab_and_p[i-1].suit and Tab_and_p[i].suit == Tab_and_p[i-2].suit and Tab_and_p[i].suit == Tab_and_p[i-3].suit and Tab_and_p[i].suit == Tab_and_p[i-4].suit)):
            if (Player_cards == Player1_cards):
                results['p1'] = Combination['Straight-flush']
                results['p1 points'] = Tab_and_p[i].points + Tab_and_p[i-1].points + Tab_and_p[i-2].points + Tab_and_p[i-3].points + Tab_and_p[i-4].points
            elif (Player_cards == Player2_cards):
                results['p2'] = Combination['Straight-flush']
                results['p2 points'] = Tab_and_p[i].points + Tab_and_p[i-1].points + Tab_and_p[i-2].points + Tab_and_p[i-3].points + Tab_and_p[i-4].points
            print('Стрит-Флэш')

#Алгоритм поиска Флэш-Рояля
    for i in range(4, len(Tab_and_p)):
        if (Tab_and_p[i].val == 'Ace' and (Tab_and_p[i].points == Tab_and_p[i-1].points - 1 and Tab_and_p[i].points == Tab_and_p[i-2].points - 2 and Tab_and_p[i].points == Tab_and_p[i-3].points - 3 and Tab_and_p[i].points == Tab_and_p[i-4].points - 4) and (Tab_and_p[i].suit == Tab_and_p[i-1].suit and Tab_and_p[i].suit == Tab_and_p[i-2].suit and Tab_and_p[i].suit == Tab_and_p[i-3].suit and Tab_and_p[i].suit == Tab_and_p[i-4].suit)):
            if (Player_cards == Player1_cards):
                results['p1'] = Combination['Straight-flush']
                results['p1 points'] = Tab_and_p[i].points + Tab_and_p[i-1].points + Tab_and_p[i-2].points + Tab_and_p[i-3].points + Tab_and_p[i-4].points
            elif (Player_cards == Player2_cards):
                results['p2'] = Combination['Straight-flush']
                results['p2 points'] = Tab_and_p[i].points + Tab_and_p[i-1].points + Tab_and_p[i-2].points + Tab_and_p[i-3].points + Tab_and_p[i-4].points
            print('Флэш-Рояль')

def end_game():

    bckgrnd = pygame.image.load('end_game_background.png')

    global results
    check(Player1_cards, Table_cards)
    check(Player2_cards, Table_cards)

    restart_btn = Button(280, 70)
    back_to_menu_btn = Button(290, 70)

    end = True
    while end:

        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                quit()

        display.blit(bckgrnd, (0, 0))
        restart_btn.draw(display_width / 2 - 150, display_height / 2 - 65, 'Играть заново', settings, (0, 0, 0), 40, 10, 15)
        back_to_menu_btn.draw(display_width / 2 - 155, display_height / 2 + 50, 'Выйти из игры', show_menu, (0, 0, 0), 40, 10, 15)

        output_text('КОНЕЦ ИГРЫ', display_width / 2 - 200, display_height / 2 - 210, (0, 0, 0), font_size = 60)

        if results['p1'] == results['p2']:
            if results['p1 points'] == results['p2 points']:
                output_text('Ничья', display_width / 2 - 100, display_height / 2 - 130, (0, 0, 0))
            elif results['p1 points'] > results['p2 points']:
                output_text('Первый игрок выиграл', display_width / 2 - 150, display_height / 2 - 130, (0, 0, 0))
            elif results['p1 points'] < results['p2 points']:
                output_text('Второй игрок выиграл', display_width / 2 - 150, display_height / 2 - 130, (0, 0, 0))
        elif results['p1'] > results['p2']:
            output_text('Первый игрок выиграл', display_width/2 - 150, display_height/2 - 130, (0, 0, 0))
        elif results['p1'] < results['p2']:
            output_text('Второй игрок выиграл', display_width/2 - 150, display_height/2 - 130, (0, 0, 0))

        pygame.display.update()

def output_text(message, x, y, font_color, font_type = 'times-new-roman.ttf', font_size = 30):
    font_type = pygame.font.Font(font_type, font_size)
    text = font_type.render(message, True, font_color)
    display.blit(text, (x, y))

show_menu()

pygame.quit()
quit()


# """
# 题目：You are given two strings s1 and s2 of equal length consisting of letters "x" and "y" only.
# Your task is to make these two strings equal to each other.
# You can swap any two characters that belong to different strings,
# which means: swap s1[i] and s2[j].
#
# Return the minimum number of swaps required to make s1 and s2 equal, or return -1 if it is impossible to do so.
#
#
#
# Example 1:
#
# Input: s1 = "xx", s2 = "yy"
# Output: 1
# Explanation:
# Swap s1[0] and s2[1], s1 = "yx", s2 = "yx".
# Example 2:
#
# Input: s1 = "xy", s2 = "yx"
# Output: 2
# Explanation:
# Swap s1[0] and s2[0], s1 = "yy", s2 = "xx".
# Swap s1[0] and s2[1], s1 = "xy", s2 = "xy".
# Note that you can't swap s1[0] and s1[1] to make s1 equal to "yx", cause we can only swap chars in different strings.
# Example 3:
#
# Input: s1 = "xx", s2 = "xy"
# Output: -1
# Example 4:
#
# Input: s1 = "xxyyxyxyxx", s2 = "xyyxyxxxyx"
# Output: 4
#
#
# Constraints:
#
# 1 <= s1.length, s2.length <= 1000
# s1, s2 only contain 'x' or 'y'.
#
# url:
# """

class Solution:
    def minimumSwap(self, s1: str, s2: str) -> int:
        self.s1 = s1
        self.s2 = s2

        for i in range(len(s1)):
            for j in range(len(s1)):
                print(i, j)  # 遍历所有交换情况
        return 0

    def help_me(self, x, y, step):
        """
        交换 xy 看看行不行
        :param x:
        :param y:
        :return:
        """

        for value, i in enumerate(self.s1):
            self.help_me(x, y, step)

        return 0

if __name__ == '__main__':
    s1 = "xx"
    s2 = "xy"

    solution = Solution()
    result = solution.minimumSwap(s1, s2)
    print(result)

# """
# 分析: 最少的交换次数将两个字符串变成相等
#
# """


#!python3
#klipper.py - a module for modifying a klipbook data file

import shelve, pyperclip

#klipperInsert(key, fileName | default(KlipBook)) - inserts clipboard content using specified keyword and filename
def klipperInsert(wordKey,book_Name='KlipBook'):
    df = shelve.open(book_Name)
    df[wordKey]=pyperclip.paste()
    df.close()
    return wordKey + ' was added to ' + book_Name

#klipperErase(key, fileName | default(KlipBook)) - deletes the key content from the specified klipbook file
def klipperErase(wordKey, book_Name='KlipBook'):
    df = shelve.open(book_Name)
    del df[wordKey]
    df.close()
    return wordKey + ' was deleted from ' + book_Name

#klipperGet(key, fileName | default(KlipBook)) - pastes the content of the key from the specified klipbook file
def klipperGet(wordKey, book_Name='KlipBook'):
    df = shelve.open(book_Name)
    if(wordKey in df):
        pyperclip.copy(df[wordKey])
        df.close()
        return wordKey + " from " + book_Name + " was pasted to the clipboard "
    else:
        df.close()
        return wordKey + " from " + book_Name + " was missing "

#klipperKeys(fileName | default(KlipBook)) - returns the keys from the specified klipbook file
def klipperKeys(book_Name='KlipBook'):
    df = shelve.open(book_Name)
    keys = str(list(df.keys()))
    df.close()
    return keys


import adi # pip install pyadi-iio
import matplotlib.pyplot as plt
import numpy as np

# Create radio
sdr = adi.Pluto()

# Configure properties
sdr.rx_rf_bandwidth = 4000000
sdr.rx_lo = 2000000000

# Read properties
print("RX LO %s" % (sdr.rx_lo))

# Collect data
sig = sdr.rx()
plt.plot(np.real(sig))
plt.plot(np.imag(sig))
plt.xlabel("Samples")
plt.ylabel("Amplitude [dbFS]")
plt.show()


#!/usr/bin/env python
# coding=utf-8
'''
@Description:
@Author: Xuannan
@Date: 2019-12-17 22:20:20
@LastEditTime : 2019-12-28 22:13:17
@LastEditors  : Xuannan
'''
from app.utils.swagger_filed import IntegerQueryFiled, StringQueryFiled, IntegerPathFiled, StringPathFiled

file = StringQueryFiled(name='file',
						description="上传文件",
						default='',
						required=True).data

data_fields = {
						'name':{"type": "string",},
						'path':{"type": "string",},
						'size':{"type": "string",},
						}

upload = {
	"description": "上传",
	"parameters": [
		file
	],
	"security": [
		{
			"Authorization": ''
		}
	],
	"responses": {
		"201": {
			"description": "上传成功",
			"properties":{
				'data':{
					'properties':data_fields
				},
			}
		}
	}
}


from numpy import *
from glob import *
from os import *
import cv2

class Util:

	#returns the pythagorean distance between two coordinates:
	def calculateDistance(self, xy1, xy2):
		(x1, y1) = xy1
		(x2, y2) = xy2
		dist = sqrt((x2-x1)**2 + (y2-y1)**2)
		return dist

	#returns an angle in radians from 0 to 2pi (no negative values)
	def calculateAngle(self, p1, p2):
		x1, y1 = p1
		x2, y2 = p2
		angle = arctan2(y2-y1, x2-x1)
		if angle < 0:
			angle = 2*pi + angle
		return angle

	#function to get the videos
	#note that I am assuming that the paths to get the videos are exactly those found on the folder that is downloaded form the dataset website.
	def getVideoPaths(self, path):

		#mapping each of the 10 category names to a number to be used as the label (0 to 9)
		category_labels = {0:'Diving', 1:'Golf-Swing', 2:'Kicking', 3:'Lifting', 4:'Riding-Horse', 5:'Running', 6:'SkateBoarding', \
		 7:'Swing-Bench', 8:'Swing-Side', 9:'Walking'}

		#list of category name for each folder
		category_folders = {'Diving-Side':0, 'Golf-Swing-Back':1, 'Golf-Swing-Front':1, 'Golf-Swing-Side':1, 'Kicking-Front':2, \
		'Kicking-Side':2, 'Lifting':3, 'Riding-Horse':4, 'Run-Side':5, 'SkateBoarding-Front':6, 'Swing-Bench':7, 'Swing-SideAngle':8, \
		'Walk-Front':9}

		videoPaths = []
		videoLabels = []
		categoryFolders = listdir(path)

		for cat in categoryFolders:
			if cat != ".DS_Store" :
				category = path + "/" + cat
				videoFolders = listdir(category)
				for video in videoFolders:
					folder = category + "/" + video
					f = glob(folder + '/*.avi')

					if f != []:
						videoPaths += f
						videoLabels.append(category_folders[str(cat)])
		return videoPaths, videoLabels


from common.datetime_ import datetime_

__author__ = 'SLCIT, Inc.'
__email__ = 'simoncharest@gmail.com'
__copyright__ = f'Copyright © {datetime_.get_years(2020)} {__author__} <{__email__}>. All rights reserved.'
__project__ = 'Genealopy'
__credits__ = {
    'Simon Charest': {
        'organization': [f'{__author__}', 'SLCIT, Inc.'],
        'email': [f'{__email__}', 'simoncharest@gmail.com'],
        'Facebook': 'https://www.facebook.com/simon.charest/',
        'GitHub': 'https://github.com/Simon-Charest',
        'LinkedIn': 'https://www.linkedin.com/in/simoncharest/',
        'Twitter': 'https://twitter.com/scharest'
    },
    'Francis-Olivier Gradel, Eng.': {
        'organization': 'Retronic Design',
        'product': 'DB9 to USB Game Controller Adapter',
        'email': 'info@retronicdesign.com',
        'website': 'retronicdesign.com',
        'eBay': 'https://www.ebay.com/usr/retronicdesign',
        'Facebook': 'https://www.facebook.com/retronicdesign',
        'LinkedIn': 'https://ca.linkedin.com/in/francis-gradel-ing-b620591a',
        'Twitter': 'https://twitter.com/fogradel',
        'AtariAge': 'https://atariage.com/forums/profile/37766-nitz1976/',
        'Famille Gradel': 'https://www.retronicdesign.com/genealogie/'
    },
    'Gilles Charest': {},
    'Gilles Deguire': {'email': 'deguire@mesancetres.ca', 'organization': 'Mes ancêtres', 'website': 'http://www.mesancetres.ca/'},
    'Louise Charest': {'email': 'charestl53@videotron.ca'},
    'Marc Charest': {'email': 'marc@lourobin.com'},
    'Michel Charest': {'email': 'mic6349@gmail.com'},
    'Pierre Charest': {'email': 'charestp@videotron.ca', 'organization': '9116-8872 Québec inc.', 'website': 'https://www.myheritage.fr/site-205814691/charest'},
    'Richard Côté': {'email': 'richardcoste@sogetel.net', 'organization': "Le Centre de généalogie francophone d'Amérique", 'website': 'http://www.genealogie.org/login/'},
    'Suzanne Coderre': {'email': 'suzanne1809@gmail.com'},
    'The Charest Family': {}
}
__license__ = 'GNU'
__maintainer__ = 'Simon Charest'
__status__ = 'Developement'
__version__ = '2.0.0'

"""
Filenames examples:
    ma01_dubreuil_lague.json   : first-degree (01) ascendant (a) of the mother's side (m) of the family
    fa01_tremblay_charest.json : first-degree (01) ascendant (a) of the father's side (f) of the family
    00_lague_charest.json      : Root (00) of both sides of the family
    m00_dubreuil_lague.json    : Root (00) of the mother's side (m) of the family
    f00_tremblay_charest.json  : Root (00) of the father's side (f) of the family
    md01_dubreuil_lague.json   : first-degree (01) descendant (d) of the mother's side (m) of the family
    fd01_charest_drouin.json   : first-degree (01) descendant (d) of the father's side (f) of the family
"""

# Data files
DATA_DIRECTORY = 'data/'
INPUT_DIRECTORY = f'{DATA_DIRECTORY}input/'
OUTPUT_DIRECTORY = f'{DATA_DIRECTORY}output/'
ALL_FILENAMES = [f'{INPUT_DIRECTORY}**/*.json']
INPUT_FILENAMES = map(lambda filename: INPUT_DIRECTORY + str(filename), [
        # Laguë
        # 'Laguë/far_ascendance/*.json',  # Marie-Anne Lucas dit Francoeur's ascendance
        # 'Laguë/*.json',  # Suzanne Laguë's ascendance
        # 'Laguë/descendance/*.json',

        # Charest
        "Charest/far_ascendence/fa99_delorraine.json",  # Charest noble ascendence
        'Charest/far_ascendence/*.json',  # Delphis Charest's ascendence
        'Charest/tanguay_charest_siblings/*.json',  # Delphis Charest's siblings
        'Charest/dion_charette_ascendence/*.json',  # Aurèle Charette (Charest-Charette)'s ascendence
        'Charest/little_cousins/*.json',  # Clément Charest siblings' descendence
        'Charest/little_cousin_descendence/*.json',  # Clément Charest siblings' descendence
        'Tremblay/*.json',  # Rita Lacombe Tremblay's ascendence
        'Charest/*.json',
        'Charest/descendence/*.json',

        # Laguë-Charest
        '0?_lague_charest.json'
    ]
)
OUTPUT_FILENAME = f'{OUTPUT_DIRECTORY}data.txt'

# Encryption
SECURITY_DIRECTORY = f'{DATA_DIRECTORY}security/'
KEY_FILENAME = f'{SECURITY_DIRECTORY}key.txt'
SALT_FILENAME = f'{SECURITY_DIRECTORY}salt.txt'

# Visuals
GRAPH_DIRECTORY = f'{DATA_DIRECTORY}graph/'
GRAPH_FILENAME = f'{GRAPH_DIRECTORY}{__project__.lower()}.gv'
GRAPH_FORMAT = 'png'
RANK_DIRECTION = 'TB'  # TB, LR, BT or RL
SHAPE = 'box'
STYLE = 'filled'
NAME_UNKNOWN = '(inconnu)'

# Filters
GENDER = ['M', 'F']
RELATIONSHIP = ['grandfather', 'father', 'grandmother', 'mother', 'union']

# Colors
DARKEN_INCOMPLETE = True
FEMALE_COLOR = 'pink'
FEMALE_INCOMPLETE_COLOR = 'deeppink'
MALE_COLOR = 'lightblue'
MALE_INCOMPLETE_COLOR = 'deepskyblue'
UNDEFINED_COLOR = 'grey'
SEARCH_COLOR = 'orange'
PARENT_LINK_STYLE = 'solid'
UNDEFINED_LINK_STYLE = 'dashed'

# Debugging
DEBUG = False


import json
import os
import time

from . import stats
from .stats import Details, SortIndex, StatGroup
from .util.media_type import MediaType
from .util.progress_type import ProgressType

def json_decoder(obj):
    if "server_id" in obj:
        return MediaData(obj)
    if "number" in obj:
        return ChapterData(obj)
    return obj

class State:
    version = 1.4
    cache_version = 1

    def __init__(self, settings, session=None):
        self.settings = settings
        self.session = session
        self.media = {}
        self.all_media = {}
        self.hashes = {}
        self.cookie_hash = None
        self.server_cache = {}

        self.load()

    @staticmethod
    def get_hash(json_dict):
        if not json_dict or not any(map(lambda x: json_dict[x], json_dict)):
            return 0, ""
        json_str = json.dumps(json_dict, indent=4, sort_keys=True)
        return hash(json_str), json_str

    def read_file_as_dict(self, file_name, object_hook=json_decoder):
        try:
            with open(file_name, "r") as jsonFile:
                json_dict = json.load(jsonFile, object_hook=object_hook)
                self.hashes[file_name] = State.get_hash(json_dict)[0]
                return json_dict
        except (json.decoder.JSONDecodeError, FileNotFoundError):
            return {}

    def save_to_file(self, file_name, json_dict):
        h, json_str = State.get_hash(json_dict)
        if self.hashes.get(file_name, 0) == h:
            return False
        self.hashes[file_name] = h
        os.makedirs(os.path.dirname(file_name), exist_ok=True)
        with open(file_name, "w") as jsonFile:
            jsonFile.write(json_str)
        import logging
        logging.info("Persisting state to %s", file_name)

        return True

    def save(self):
        self.save_session_cookies()
        self.save_to_file(self.settings.get_metadata_file(), self.all_media)
        self.save_to_file(self.settings.get_server_cache_file(), self.server_cache)
        for media_data in self.media.values():
            self.save_to_file(self.settings.get_chapter_metadata_file(media_data), media_data.chapters)

    def set_session(self, session, no_load=False):
        self.session = session
        if not no_load and not self.settings.no_load_session:
            self.load_session_cookies()
        self._set_session_hash()

    def load(self):
        self.load_media()
        self.server_cache = self.read_file_as_dict(self.settings.get_server_cache_file())
        if not self.server_cache or self.server_cache.get("version") != self.cache_version:
            self.update_server_cache()

    def load_chapter_data(self, media_data):
        media_data.chapters = self.read_file_as_dict(self.settings.get_chapter_metadata_file(media_data))

    def load_media(self):
        self.all_media = self.read_file_as_dict(self.settings.get_metadata_file())
        if not self.all_media:
            self.all_media = dict(media={}, disabled_media={}, version=State.version)
        self.media = self.all_media["media"]
        self.disabled_media = self.all_media["disabled_media"]

        for key, media_data in list(self.media.items()):
            if key != media_data.global_id:
                del self.media[key]
                self.media[media_data.global_id] = media_data
            assert not media_data.chapters
            self.load_chapter_data(media_data)

    def _set_session_hash(self):
        """
        Sets saved cookie_hash
        @return True iff the hash is different than the already saved one

        """
        cookie_hash = hash(str(self.session.cookies))
        if cookie_hash != self.cookie_hash:
            self.cookie_hash = cookie_hash
            return True
        return False

    def load_session_cookies(self, file=None, domains=None):
        """ Load session from disk """
        try:
            with open(file or self.settings.get_cookie_file(), "r") as f:
                for i, line in enumerate(f):
                    line = line.rstrip()
                    if not line or line[0].startswith("#"):
                        continue
                    try:
                        domain, domain_specified, path, secure, expires, name, value, _ = (line + "\t" * 2).split("\t", 7)
                        if domains is not None and not any(map(lambda x: domain.endswith(x), domains)):
                            continue
                        self.session.cookies.set(name, value, path=path, domain=domain, secure=secure == "TRUE", expires=expires if expires else None)
                    except ValueError:
                        import logging
                        logging.info(f"Error on line {i + 1}: {line}")
        except FileNotFoundError:
            pass

    def save_session_cookies(self, force=False):
        """ Save session to disk """
        if self.settings.no_save_session or not self._set_session_hash():
            return False

        os.makedirs(self.settings.cache_dir, exist_ok=True)
        with open(self.settings.get_cookie_file(), "w") as f:
            f.write("# Netscape HTTP Cookie File\n")
            for cookie in self.session.cookies:
                l = [cookie.domain, str(cookie.domain_specified and cookie.domain.startswith(".")).upper(), cookie.path, str(cookie.secure).upper(), str(cookie.expires) if cookie.expires else "", cookie.name, cookie.value]
                f.write("\t".join(l) + "\n")
        return True

    def is_out_of_date(self):
        return State.version > self.all_media.get("version", 0)

    def is_out_of_date_minor(self):
        """ Is a minor state upgrade needed
        Minor upgrades are those that can before performed safely, without an
        internet connect, without user input and the new state is forwards
        compatible (the upgraded file can be used with an older program (same
        major version) without any state loss
        """
        return self.is_out_of_date() and State.version - self.all_media.get("version", 0) < 1

    def update_verion(self):
        self.all_media["version"] = State.version

    def configure_media(self, server_list):
        for key in list(self.media.keys()):
            if self.media[key]["server_id"] not in server_list:
                self.disabled_media[key] = self.media[key]
                del self.media[key]

        for key in list(self.disabled_media.keys()):
            if self.disabled_media[key]["server_id"] in server_list:
                self.media[key] = self.disabled_media[key]
                self.load_chapter_data(self.media[key])
                del self.disabled_media[key]
        self.update_server_cache(server_list)

    def update_server_cache(self, server_list={}):

        self.server_cache = {"servers": {server.id: {"media_type": server.media_type.value, "has_login": server.has_login()} for server in server_list.values()}}
        auth_servers = {server.id for server in server_list.values() if server.has_login()} | {server.alias for server in server_list.values() if server.has_login() and server.alias}
        self.server_cache["auth_servers"] = sorted(list(auth_servers))
        self.server_cache["version"] = self.cache_version

    def get_all_names(self, media_type=None, disallow_servers=False):
        names = set()
        if not disallow_servers:
            for server_id in self.server_cache["servers"]:
                if not media_type or self.server_cache["servers"][server_id]["media_type"] & media_type:
                    names.add(server_id)
        for media_id, media in self.media.items():
            if not media_type or media["media_type"] & media_type:
                names.add(media_id)
                if media.global_id_alt:
                    names.add(media.global_id_alt)
                names.add(media["dir_name"])
                if not "_ARGCOMPLETE" in os.environ:
                    names.add(media["name"])
                    names.add(str(media["id"]))
        return names

    def get_all_single_names(self, media_type=None):
        return self.get_all_names(media_type=media_type, disallow_servers=True)

    def get_server_ids(self):
        return self.server_cache["servers"].keys()

    def get_server_ids_with_logins(self):
        return self.server_cache["auth_servers"]

    def is_tracked(self, media_data):
        return bool(media_data["trackers"])

    def get_media(self, name=None, media_type=None, tag=None, shuffle=False, tracked=None):
        if isinstance(name, dict):
            yield name
            return
        media = self.media.values()
        if shuffle:
            media = list(media)
            import random
            random.shuffle(media)
        for media_data in media:
            if name is not None and name not in (media_data["server_id"], media_data["name"], media_data.global_id, media_data.global_id_alt, str(media_data["id"]), media_data["id"], media_data["dir_name"]):
                continue
            if media_type and media_data["media_type"] & media_type == 0:
                continue
            if tag and tag not in media_data["tags"] or tag == "" and not media_data["tags"]:
                continue
            if tracked is not None and self.is_tracked(media_data) != tracked:
                continue
            yield media_data

    def get_single_media(self, name=None, media_type=None):
        return next(self.get_media(media_type=media_type, name=name))

    def list_media(self, name=None, media_type=None, out_of_date_only=False, tag=None, csv=False, tracked=None):
        now = time.time()
        for media_data in self.get_media(name=name, media_type=media_type, tag=tag, tracked=tracked):
            last_chapter = media_data.get_last_chapter()
            last_read = media_data.get_last_read_chapter()
            if not out_of_date_only or last_chapter.get("number", 0) != last_read.get("number", 0):
                num_key = "number" if media_data["progress_type"] != ProgressType.CHAPTER_VOLUME else "volume_number"
                next_chapter_date_str = media_data.get_next_chapter_available_str(now)
                args = [media_data.friendly_id, media_data["name"], media_data["season_title"], str(last_read.get(num_key, 0)), str(last_chapter.get(num_key, 0)), next_chapter_date_str, ",".join(media_data["tags"])]
                if csv:
                    yield args
                else:
                    yield "{}\t{} {}\t{}/{} {} {}".format(*args)

    def list_chapters(self, name, show_ids=False):
        media_data = self.get_single_media(name=name)
        for chapter in media_data.get_sorted_chapters():
            yield "{:4}{}:{}{}".format(chapter["number"], "*" if chapter["special"] else " ", chapter["title"], ":" + chapter["id"] if show_ids else "")

    def save_stats(self, identifier, stats):
        stats_file = self.settings.get_stats_file()
        saved_data = self.read_file_as_dict(stats_file, object_hook=lambda obj: TrackerEntry(obj))
        saved_data.update({identifier or "": stats})
        self.save_to_file(stats_file, saved_data)

    def list_stats(self, username=None, media_type=None, stat_group=StatGroup.NAME, sort_index=SortIndex.NAME, reverse=False, min_count=0, min_score=1, time_unit=0, no_header=False, details_type=Details.NAME, details_limit=None):
        saved_data = self.read_file_as_dict(self.settings.get_stats_file(), object_hook=lambda obj: TrackerEntry(obj))
        data = saved_data.get(username if username else "", {})
        if media_type:
            data = list(filter(lambda x: x["media_type"] == media_type, data))
        grouped_data = stats.group_entries(data, min_score=min_score)[stat_group.value]
        sorted_data = stats.compute_stats(grouped_data, sort_index.value, reverse=reverse, min_count=min_count, time_unit=time_unit, details_type=details_type, details_limit=details_limit)
        if not no_header:
            yield stats.get_stat_headers(stat_group, details_type=details_type)
        yield from stats.get_stat_entries(sorted_data, details_type)

class MediaData(dict):
    def __init__(self, backing_map):
        super().__init__(backing_map)
        self.chapters = {}

    def __getitem__(self, key):
        if key == "chapters":
            return self.chapters
        else:
            return super().__getitem__(key)

    def __str__(self):
        return "{}\t{} {} ({})".format(self.global_id, self["name"], self.get("label", self["season_title"]), MediaType(self["media_type"]).name)

    def reset(self, media_data):
        assert media_data is not self
        assert not media_data.chapters
        copy = MediaData(media_data)
        self.copy_fields_to(copy)
        self.clear()
        self.chapters.clear()
        self.update(copy)

    def get_sorted_chapters(self, volume=False, filter_list=[]):
        return sorted(self["chapters"].values(), key=lambda x: (x.get_number(volume=volume), x.get_number()))

    @property
    def global_id(self):
        return "{}:{}{}{}".format(self["server_id"], self["id"], (self["season_id"] if self["season_id"] else ""), self.get("lang", "").split("-")[0][:3])

    @property
    def global_id_alt(self):
        return "{}:{}{}{}".format(self["server_id"], self["alt_id"], (self["season_id"] if self["season_id"] else ""), self.get("lang", "")[:3]) if self.get("alt_id", False) else None

    @property
    def friendly_id(self):
        return self.global_id if len(self.global_id) < 32 or not self.global_id_alt else self.global_id_alt

    def get_next_chapter_available_str(self, time):
        timestamp = self.get("nextTimeStamp") or self.get("nextTimeStampTracker", 0)
        if not timestamp:
            return ""
        delta = max(timestamp - time, 0)
        if delta < 3600:
            return f"{delta/60:.1f} minutes"
        elif delta < 3600 * 24 * 1.5:
            return f"{delta/3600:.1f} hours"
        else:
            return f"{delta/3600/24:.1f} days"

    def copy_fields_to(self, dest):
        for key in ("nextTimeStampTracker", "offset", "progress", "progress_type", "tags", "trackers"):
            if key in self:
                dest[key] = self.get(key)

    def get_last_chapter(self):
        return max(self["chapters"].values(), key=lambda x: x["number"], default={})

    def get_first_chapter_number_greater_than_zero(self):
        return min(self["chapters"].values(), key=lambda x: x["number"] if x["number"] > 0 else float("inf"))["number"]

    def get_chapter_number_to_id(self, chapter_num):
        return max(filter(lambda x: x["number"] == chapter_num, self["chapters"].values()), key=lambda x: x["number"], default={}).get("id")

    def get_last_read_chapter(self, volume=False):
        return max(filter(lambda x: x["read"], self["chapters"].values()), key=lambda x: x.get_number(volume), default=ChapterData({}))

    def get_last_read_chapter_number(self, volume=False):
        return self.get_last_read_chapter(volume=volume).get_number(volume)

    def get_unreads(self, any_unread=False, volume=False):
        lastRead = self.get_last_read_chapter_number(volume=volume)
        for chapter in self.get_sorted_chapters(volume=volume):
            if not chapter["read"] and (any_unread or (chapter.get_number(volume) > lastRead and not chapter["special"])):
                yield chapter

    def get_labels(self):
        return [self.global_id, self["name"], self["server_id"], self["server_alias"], MediaType(self["media_type"]).name]

class ChapterData(dict):
    update_state = False

    def __init__(self, backing_map):
        super().__init__(backing_map)

    def update(self, key_pars):
        super().update(key_pars)
        self.update_state = True

    def get_number(self, volume=False):
        return self.get("volume_number" if volume else "number") or 0

    def check_if_updated_and_clear(self):
        updated = self.update_state
        self.update_state = False
        return updated

class TrackerEntry(dict):
    def __init__(self, backing_map):
        super().__init__(backing_map)

    def __getitem__(self, key):
        if key == "name":
            names = super().get("names")
            return names.get("english") or names.get("romaji") or next(iter(names.values())) if names else super().__getitem__(key)
        elif key == "names":
            names = super().get("names")
            return list(set(filter(lambda x: x, names.values())))
        else:
            return super().__getitem__(key)


from datetime import datetime
from venv import logger
from model.backend_logs_model import BackendLogModel
from util import file_util
from util import mysql_util
from config import projrct_config as conf
import time
from util import logging_util

# 创建日志对象
logger = logging_util.init_logger('backend_logs')

# 1、获取后台访问日志文件夹下有哪些日志文件
all_file_list = file_util.get_dir_files_list(conf.backend_logs_data_root_path)

# 2、查询元数据库表中已经采集的日志文件，用来对比要采集的新的访问日志文件

# 创建元数据库连接
metadata_util = mysql_util.get_mysql_util()

# 获取已经被采集的日志文件
processed_file_list = mysql_util.get_processed_files(
    util=metadata_util,
    db_name=conf.metadata_db,
    tb_name=conf.logs_monitor_meta_table_name,
    tb_cols=conf.logs_monitor_meta_table_create_cols
)

# 对比要采集的日志文件
new_file_list = file_util.get_new_by_compare_lists(processed_file_list,all_file_list)

# 3、进行日志数据采集
csv_file = open(conf.logs_output_csv_root_path + conf.logs_output_csv_file_name, 'a')
# 向csv文件中写入表头
csv_file.write(BackendLogModel.generate_csv_header())

# 创建数据库连接
target_util = mysql_util.get_mysql_util()
target_util.check_table_exists_and_create(
    db_name=conf.target_db,
    tb_name=conf.target_logs_table_name,
    tb_cols=conf.target_logs_table_create_cols
)

if len(new_file_list)>0:
    # 遍历要采集的日志文件
    start_time = time.time()
    for file_name in new_file_list:
        # 开启事务
        target_util.start_transaction()

        try:
            count_lines = 0
            for row in open(file_name,'r',encoding='utf-8'):
                # 逐行写入到数据库中
                backend_logs_model = BackendLogModel(row)
                target_util.insert_single_sql_without_commit(backend_logs_model.generate_insert_sql())

                # 逐行写入到CSV文件中
                csv_file.write(backend_logs_model.generate_csv_str())
                # 每处理一行，记录加一
                count_lines += 1

            # 将已处理的文件插入元数据表中，进行标记，防止重复采集
            mysql_util.process_file_insert_matedata_sql(file_name,count_lines,datetime.now().strftime("%Y-%m-%d %H:%M:%S"))
        except Exception as e:
            target_util.rollback_transaction()   # 执行异常，回滚事务
            print('事务已经回滚！')
            raise e
        else:
            target_util.commit_transaction()    # 正常执行，提交事务
            print(f'日志{file_name}已经采集完毕!')
    # 记录日志信息
    end_time = time.time()
    logger.info(f'本次总共采集了{len(new_file_list)}个文件，本次采集共消耗了{end_time-start_time}s')

else:
    print('日志已经全部采集完毕!')

# 关闭连接
csv_file.close()
target_util.close()
metadata_util.close()