import typing as t

import discord
import discord.ui as ui

from views.adventure.template import InteractionCheckMixin, Backpack

class DecisionSelect(ui.Select["Decision"]):
    def __init__(self, choices: t.Iterable[str]):
        choices = [
            discord.SelectOption(label=c, value=c)
            for c in choices
        ]
        super().__init__(options=choices, placeholder="What do you want to do?")

    async def callback(self, i: discord.Interaction):
        assert self.view is not None
        self.view.decision = self.values[0]
        await i.response.defer()
        self.view.stop()

class Decision(ui.View, InteractionCheckMixin):
    def __init__(
            self,
            user: discord.Member,
            choices: t.Iterable[str],
            loc_file: discord.File | None = None
    ):
        super().__init__()

        self.user = user

        self.decision = None
        self.show_map = None
        self.loc_img = loc_file

        toggle, exit_button = self.children
        self.remove_item(toggle)
        self.remove_item(exit_button)

        order = [Backpack(row=1), exit_button, DecisionSelect(choices)]
        if loc_file is not None:
            order.insert(1, toggle)
        for i in order:
            self.add_item(i)

    @ui.button(label="Toggle Map", row=1, style=discord.ButtonStyle.blurple)
    async def toggle_map(self, i: discord.Interaction, button: ui.Button):
        msg = i.message
        await i.response.defer()
        if msg.attachments:
            msg = await msg.remove_attachments(*msg.attachments)
        else:
            self.loc_img.fp.seek(0)
            msg = await msg.edit(attachments=[self.loc_img])
        self.show_map = bool(msg.attachments)

    @ui.button(label="Exit", row=1, style=discord.ButtonStyle.red)
    async def exit(self, i: discord.Interaction, button: ui.Button):
        self.decision = "exit"
        await i.response.defer()
        self.stop()


# -*- coding: utf-8 -*-

import decimal
Decimal = decimal.Decimal
import os
import traceback
from time import strftime

from debughelpers import Error
from options import debug
from ordereddict import OrderedDict
from safe_print import safe_print
from util_io import StringIOu as StringIO
from util_str import safe_unicode
import CGATS
import ICCProfile as ICCP
import colormath
import localization as lang

cals = {}

def quote_nonoption_args(args):
	""" Puts quotes around all arguments which are not options
	(ie. which do not start with a hyphen '-')

	"""
	args = list(args)
	for i, arg in enumerate(args):
		if arg[0] != "-":
			args[i] = '"' + arg + '"'
	return args

def add_dispcal_options_to_cal(cal, options_dispcal):
	# Add dispcal options to cal
	options_dispcal = quote_nonoption_args(options_dispcal)
	try:
		cgats = CGATS.CGATS(cal)
		cgats[0].add_section("ARGYLL_DISPCAL_ARGS",
							 " ".join(options_dispcal).encode("UTF-7",
															  "replace"))
		return cgats
	except Exception as exception:
		safe_print(safe_unicode(traceback.format_exc()))

def add_options_to_ti3(ti3, options_dispcal=None, options_colprof=None):
	# Add dispcal and colprof options to ti3
	try:
		cgats = CGATS.CGATS(ti3)
		if options_colprof:
			options_colprof = quote_nonoption_args(options_colprof)
			cgats[0].add_section("ARGYLL_COLPROF_ARGS",
							   " ".join(options_colprof).encode("UTF-7",
																"replace"))
		if options_dispcal and 1 in cgats:
			options_dispcal = quote_nonoption_args(options_dispcal)
			cgats[1].add_section("ARGYLL_DISPCAL_ARGS",
							   " ".join(options_dispcal).encode("UTF-7",
																"replace"))
		return cgats
	except Exception as exception:
		safe_print(safe_unicode(traceback.format_exc()))

def cal_to_fake_profile(cal):
	"""
	Create and return a 'fake' ICCProfile with just a vcgt tag.

	cal must refer to a valid Argyll CAL file and can be a CGATS instance
	or a filename.

	"""
	vcgt, cal = cal_to_vcgt(cal, True)
	if not vcgt:
		return
	profile = ICCP.ICCProfile()
	profile.fileName = cal.filename
	profile._data = "\0" * 128
	profile._tags.desc = ICCP.TextDescriptionType("", "desc")
	profile._tags.desc.ASCII = safe_unicode(
				os.path.basename(cal.filename)).encode("ascii", "asciize")
	profile._tags.desc.Unicode = safe_unicode(os.path.basename(cal.filename))
	profile._tags.vcgt = vcgt
	profile.size = len(profile.data)
	profile.is_loaded = True
	return profile

def cal_to_vcgt(cal, return_cgats=False):
	"""
	Create a vcgt tag from calibration data.

	cal must refer to a valid Argyll CAL file and can be a CGATS instance
	or a filename.

	"""
	if not isinstance(cal, CGATS.CGATS):
		try:
			cal = CGATS.CGATS(cal)
		except (IOError, CGATS.CGATSInvalidError,
			CGATS.CGATSInvalidOperationError, CGATS.CGATSKeyError,
			CGATS.CGATSTypeError, CGATS.CGATSValueError) as exception:
			safe_print("Warning - couldn't process CGATS file '%s': %s" %
					   tuple(safe_unicode(s) for s in (cal, exception)))
			return None
	required_fields = ("RGB_I", "RGB_R", "RGB_G", "RGB_B")
	data_format = cal.queryv1("DATA_FORMAT")
	if data_format:
		for field in required_fields:
			if not field in list(data_format.values()):
				if debug: safe_print("[D] Missing required field:", field)
				return None
		for field in list(data_format.values()):
			if not field in required_fields:
				if debug: safe_print("[D] Unknown field:", field)
				return None
	entries = cal.queryv(required_fields)
	if len(entries) < 1:
		if debug: safe_print("[D] No entries found in calibration",
							 cal.filename)
		return None
	vcgt = ICCP.VideoCardGammaTableType("", "vcgt")
	vcgt.update({
		"channels": 3,
		"entryCount": len(entries),
		"entrySize": 2,
		"data": [[], [], []]
	})
	for n in entries:
		for i in range(3):
			vcgt.data[i].append(entries[n][i + 1] * 65535.0)
	if return_cgats:
		return vcgt, cal
	return vcgt

def can_update_cal(path):
	""" Check if cal can be updated by checking for required fields. """
	try:
		calstat = os.stat(path)
	except Exception as exception:
		safe_print("Warning - os.stat('%s') failed: %s" %
				   tuple(safe_unicode(s) for s in (path, exception)))
		return False
	if not path in cals or cals[path].mtime != calstat.st_mtime:
		try:
			cal = CGATS.CGATS(path)
		except (IOError, CGATS.CGATSInvalidError,
			CGATS.CGATSInvalidOperationError, CGATS.CGATSKeyError,
			CGATS.CGATSTypeError, CGATS.CGATSValueError) as exception:
			if path in cals:
				del cals[path]
			safe_print("Warning - couldn't process CGATS file '%s': %s" %
					   tuple(safe_unicode(s) for s in (path, exception)))
		else:
			if cal.queryv1("DEVICE_CLASS") == "DISPLAY" and not None in \
			   (cal.queryv1("TARGET_WHITE_XYZ"),
				cal.queryv1("TARGET_GAMMA"),
				cal.queryv1("BLACK_POINT_CORRECTION"),
				cal.queryv1("QUALITY")):
				cals[path] = cal
	return path in cals and cals[path].mtime == calstat.st_mtime

def extract_cal_from_profile(profile, out_cal_path=None,
							 raise_on_missing_cal=True,
							 prefer_cal=False):
	""" Extract calibration from 'targ' tag in profile or vcgt as fallback """

	white = False

	# Check if calibration is included in TI3
	targ = profile.tags.get("targ", profile.tags.get("CIED"))
	if isinstance(targ, ICCP.Text):
		cal = extract_cal_from_ti3(targ)
		if cal:
			check = cal
			get_cgats = CGATS.CGATS
			arg = cal
	else:
		cal = None
	if not cal:
		# Convert calibration information from embedded WCS profile
		# (if present) to VideCardFormulaType if the latter is not present
		if (isinstance(profile.tags.get("MS00"), ICCP.WcsProfilesTagType) and
			not "vcgt" in profile.tags):
			profile.tags["vcgt"] = profile.tags["MS00"].get_vcgt()

		# Get the calibration from profile vcgt
		check = isinstance(profile.tags.get("vcgt"),
						   ICCP.VideoCardGammaType)
		get_cgats = vcgt_to_cal
		arg = profile

	if not check:
		if raise_on_missing_cal:
			raise Error(lang.getstr("profile.no_vcgt"))
		else:
			return False
	else:
		try:
			cgats = get_cgats(arg)
		except (IOError, CGATS.CGATSError) as exception:
			raise Error(lang.getstr("cal_extraction_failed"))
	if (cal and not prefer_cal and isinstance(profile.tags.get("vcgt"),
											  ICCP.VideoCardGammaType)):
		# When vcgt is nonlinear, prefer it
		# Check for video levels encoding
		if cgats.queryv1("TV_OUTPUT_ENCODING") == "YES":
			black, white = (16, 235)
		else:
			output_enc = cgats.queryv1("OUTPUT_ENCODING")
			if output_enc:
				try:
					black, white = (float(v) for v in
									output_enc.split())
				except (TypeError, ValueError):
					white = False
		cgats = vcgt_to_cal(profile)
		if white and (black, white) != (0, 255):
			safe_print("Need to un-scale vcgt from video levels (%s..%s)" %
					   (black, white))
			# Need to un-scale video levels
			data = cgats.queryv1("DATA")
			if data:
				safe_print("Un-scaling vcgt from video levels (%s..%s)" %
						   (black, white))
				encoding_mismatch = False
				# For video encoding the extra bits of
				# precision are created by bit shifting rather
				# than scaling, so we need to scale the fp
				# value to account for this
				oldmin = (black / 256.0) * (65536 / 65535.)
				oldmax = (white / 256.0) * (65536 / 65535.)
				for entry in data.values():
					for column in "RGB":
						v_old = entry["RGB_" + column]
						lvl = round(v_old * (65535 / 65536.) * 256, 2)
						if lvl < round(black, 2) or lvl > round(white, 2):
							# Can't be right. Metadata says it's video encoded,
							# but clearly exceeds the encoding range.
							safe_print("Warning: Metadata claims video levels "
									   "(%s..%s) but vcgt value %s exceeds "
									   "encoding range. Using values as-is." %
									   (round(black, 2), round(white, 2), lvl))
							encoding_mismatch = True
							break
						v_new = colormath.convert_range(v_old, oldmin, oldmax, 0, 1)
						entry["RGB_" + column] = min(max(v_new, 0), 1)
					if encoding_mismatch:
						break
				if encoding_mismatch:
					cgats = vcgt_to_cal(profile)
				# Add video levels hint to CGATS
				elif (black, white) == (16, 235):
					cgats[0].add_keyword("TV_OUTPUT_ENCODING", "YES")
				else:
					cgats[0].add_keyword("OUTPUT_ENCODING",
										 " ".join(str(v) for v in (black, white)))
			else:
				safe_print("Warning - no un-scaling applied - no "
						   "calibration data!")
	if out_cal_path:
		cgats.write(out_cal_path)
	return cgats

def extract_cal_from_ti3(ti3):
	"""
	Extract and return the CAL section of a TI3.

	ti3 can be a file object or a string holding the data.

	"""
	if isinstance(ti3, CGATS.CGATS):
		ti3 = str(ti3)
	if isinstance(ti3, str):
		ti3 = StringIO(ti3)
	cal = False
	cal_lines = []
	for line in ti3:
		line = line.strip()
		if line == "CAL":
			line = "CAL    "  # Make sure CGATS file identifiers are
							  # always a minimum of 7 characters
			cal = True
		if cal:
			cal_lines.append(line)
			if line == 'END_DATA':
				break
	if isinstance(ti3, file):
		ti3.close()
	return "\n".join(cal_lines)

def extract_fix_copy_cal(source_filename, target_filename=None):
	"""
	Return the CAL section from a profile's embedded measurement data.

	Try to 'fix it' (add information needed to make the resulting .cal file
	'updateable') and optionally copy it to target_filename.

	"""
	from worker import get_options_from_profile
	try:
		profile = ICCP.ICCProfile(source_filename)
	except (IOError, ICCP.ICCProfileInvalidError) as exception:
		return exception
	if "CIED" in profile.tags or "targ" in profile.tags:
		cal_lines = []
		ti3 = StringIO(profile.tags.get("CIED", "") or
					   profile.tags.get("targ", ""))
		ti3_lines = [line.strip() for line in ti3]
		ti3.close()
		cal_found = False
		for line in ti3_lines:
			line = line.strip()
			if line == "CAL":
				line = "CAL    "  # Make sure CGATS file identifiers are
								  #always a minimum of 7 characters
				cal_found = True
			if cal_found:
				cal_lines.append(line)
				if line == 'DEVICE_CLASS "DISPLAY"':
					options_dispcal = get_options_from_profile(profile)[0]
					if options_dispcal:
						whitepoint = False
						b = profile.tags.lumi.Y
						for o in options_dispcal:
							if o[0] == "y":
								cal_lines.append('KEYWORD "DEVICE_TYPE"')
								if o[1] == "c":
									cal_lines.append('DEVICE_TYPE "CRT"')
								else:
									cal_lines.append('DEVICE_TYPE "LCD"')
								continue
							if o[0] in ("t", "T"):
								continue
							if o[0] == "w":
								continue
							if o[0] in ("g", "G"):
								if o[1:] == "240":
									trc = "SMPTE240M"
								elif o[1:] == "709":
									trc = "REC709"
								elif o[1:] == "l":
									trc = "L_STAR"
								elif o[1:] == "s":
									trc = "sRGB"
								else:
									trc = o[1:]
									if o[0] == "G":
										try:
											trc = 0 - Decimal(trc)
										except decimal.InvalidOperation as \
											   exception:
											continue
								cal_lines.append('KEYWORD "TARGET_GAMMA"')
								cal_lines.append('TARGET_GAMMA "%s"' % trc)
								continue
							if o[0] == "f":
								cal_lines.append('KEYWORD '
									'"DEGREE_OF_BLACK_OUTPUT_OFFSET"')
								cal_lines.append(
									'DEGREE_OF_BLACK_OUTPUT_OFFSET "%s"' %
									o[1:])
								continue
							if o[0] == "k":
								cal_lines.append('KEYWORD '
									'"BLACK_POINT_CORRECTION"')
								cal_lines.append(
									'BLACK_POINT_CORRECTION "%s"' % o[1:])
								continue
							if o[0] == "B":
								cal_lines.append('KEYWORD '
									'"TARGET_BLACK_BRIGHTNESS"')
								cal_lines.append(
									'TARGET_BLACK_BRIGHTNESS "%s"' % o[1:])
								continue
							if o[0] == "q":
								if o[1] == "l":
									q = "low"
								elif o[1] == "m":
									q = "medium"
								else:
									q = "high"
								cal_lines.append('KEYWORD "QUALITY"')
								cal_lines.append('QUALITY "%s"' % q)
								continue
						if not whitepoint:
							cal_lines.append('KEYWORD "NATIVE_TARGET_WHITE"')
							cal_lines.append('NATIVE_TARGET_WHITE ""')
		if cal_lines:
			if target_filename:
				try:
					f = open(target_filename, "w")
					f.write("\n".join(cal_lines))
					f.close()
				except Exception as exception:
					return exception
			return cal_lines
	else:
		return None

def extract_device_gray_primaries(ti3, gray=True, logfn=None,
								  include_neutrals=False,
								  neutrals_ab_threshold=0.1):
	"""
	Extract gray or primaries into new TI3

	Return extracted ti3, extracted RGB to XYZ mapping and remaining RGB to XYZ

	"""
	filename = ti3.filename
	ti3 = ti3.queryi1("DATA")
	ti3.filename = filename
	ti3_extracted = CGATS.CGATS("""CTI3
DEVICE_CLASS "DISPLAY"
COLOR_REP "RGB_XYZ"
BEGIN_DATA_FORMAT
END_DATA_FORMAT
BEGIN_DATA
END_DATA""")[0]
	ti3_extracted.DATA_FORMAT.update(ti3.DATA_FORMAT)
	subset = [(100.0, 100.0, 100.0),
			  (0.0, 0.0, 0.0)]
	if not gray:
		subset.extend([(100.0, 0.0, 0.0),
					   (0.0, 100.0, 0.0),
					   (0.0, 0.0, 100.0),
					   (50.0, 50.0, 50.0)])
		if logfn:
			logfn("Extracting neutrals and primaries from %s" %
				  ti3.filename)
	else:
		if logfn:
			logfn("Extracting neutrals from %s" %
				  ti3.filename)
	RGB_XYZ_extracted = OrderedDict()
	RGB_XYZ_remaining = OrderedDict()
	dupes = {}
	if include_neutrals:
		white = ti3.get_white_cie("XYZ")
		str_thresh = str(neutrals_ab_threshold)
		round_digits = len(str_thresh[str_thresh.find(".") + 1:])
	for i, item in ti3.DATA.items():
		if not i:
			# Check if fields are missing
			for prefix in ("RGB", "XYZ"):
				for suffix in prefix:
					key = "%s_%s" % (prefix, suffix)
					if not key in item:
						raise Error(lang.getstr("error.testchart.missing_fields",
												(ti3.filename, key)))
		RGB = (item["RGB_R"], item["RGB_G"], item["RGB_B"])
		XYZ = (item["XYZ_X"], item["XYZ_Y"], item["XYZ_Z"])
		for RGB_XYZ in (RGB_XYZ_extracted, RGB_XYZ_remaining):
			if RGB in RGB_XYZ:
				if RGB != (100.0, 100.0, 100.0):
					# Add to existing values for averaging later
					# if it's not white (all other readings are scaled to the
					# white Y by dispread, so we don't alter it. Note that it's
					# always the first encountered white that will have Y = 100,
					# even if subsequent white readings may be higher)
					XYZ = tuple(RGB_XYZ[RGB][i] + XYZ[i]
								for i in range(3))
					if not RGB in dupes:
						dupes[RGB] = 1.0
					dupes[RGB] += 1.0
				elif RGB in subset:
					# We have white already, remove it from the subset so any
					# additional white readings we encounter are ignored
					subset.remove(RGB)
		if ((gray and
			 (item["RGB_R"] == item["RGB_G"] == item["RGB_B"] or
			  (include_neutrals and
			   all(round(abs(v), round_digits) <= neutrals_ab_threshold
				   for v in colormath.XYZ2Lab(item["XYZ_X"],
											  item["XYZ_Y"],
											  item["XYZ_Z"],
											  whitepoint=white)[1:]))) and
			 not RGB in [(100.0, 100.0, 100.0),
						 (0.0, 0.0, 0.0)]) or
			RGB in subset):
			ti3_extracted.DATA.add_data(item)
			RGB_XYZ_extracted[RGB] = XYZ
		elif not RGB in [(100.0, 100.0, 100.0),
						 (0.0, 0.0, 0.0)]:
			RGB_XYZ_remaining[RGB] = XYZ
	for RGB, count in dupes.items():
		for RGB_XYZ in (RGB_XYZ_extracted, RGB_XYZ_remaining):
			if RGB in RGB_XYZ:
				# Average values
				XYZ = tuple(RGB_XYZ[RGB][i] / count for i in range(3))
				RGB_XYZ[RGB] = XYZ
	return ti3_extracted, RGB_XYZ_extracted, RGB_XYZ_remaining

def ti3_to_ti1(ti3_data):
	"""
	Create and return TI1 data converted from TI3.

	ti3_data can be a file object, a list of strings or a string holding the data.

	"""
	ti3 = CGATS.CGATS(ti3_data)
	if not ti3:
		return ""
	ti3[0].type = "CTI1"
	ti3[0].DESCRIPTOR = "Argyll Calibration Target chart information 1"
	ti3[0].ORIGINATOR = "Argyll targen"
	if hasattr(ti3[0], "COLOR_REP"):
		color_rep = ti3[0].COLOR_REP.split('_')[0]
	else:
		color_rep = "RGB"
	ti3[0].add_keyword("COLOR_REP", color_rep)
	ti3[0].remove_keyword("DEVICE_CLASS")
	if hasattr(ti3[0], "LUMINANCE_XYZ_CDM2"):
		ti3[0].remove_keyword("LUMINANCE_XYZ_CDM2")
	if hasattr(ti3[0], "ARGYLL_COLPROF_ARGS"):
		del ti3[0].ARGYLL_COLPROF_ARGS
	return str(ti3[0])

def vcgt_to_cal(profile):
	""" Return a CAL (CGATS instance) from vcgt """
	cgats = CGATS.CGATS(file_identifier="CAL")
	context = cgats.add_data({"DESCRIPTOR": "Argyll Device Calibration State"})
	context.add_data({"ORIGINATOR": "vcgt"})
	context.add_data({"CREATED": strftime("%a %b %d %H:%M:%S %Y",
										  profile.dateTime.timetuple())})
	context.add_keyword("DEVICE_CLASS", "DISPLAY")
	context.add_keyword("COLOR_REP", "RGB")
	context.add_keyword("RGB_I")
	key = "DATA_FORMAT"
	context[key] = CGATS.CGATS()
	context[key].key = key
	context[key].parent = context
	context[key].root = cgats
	context[key].type = key
	context[key].add_data(("RGB_I", "RGB_R", "RGB_G", "RGB_B"))
	key = "DATA"
	context[key] = CGATS.CGATS()
	context[key].key = key
	context[key].parent = context
	context[key].root = cgats
	context[key].type = key
	values = profile.tags.vcgt.getNormalizedValues()
	for i, triplet in enumerate(values):
		context[key].add_data(("%.7f" % (i / float(len(values) - 1)), ) + triplet)
	return cgats

def verify_cgats(cgats, required, ignore_unknown=True):
	"""
	Verify and return a CGATS instance or None on failure.

	Verify if a CGATS instance has a section with all required fields.
	Return the section as CGATS instance on success, None on failure.

	If ignore_unknown evaluates to True, ignore fields which are not required.
	Otherwise, the CGATS data must contain only the required fields, no more,
	no less.
	"""
	cgats_1 = cgats.queryi1(required)
	if cgats_1 and cgats_1.parent and cgats_1.parent.parent:
		cgats_1 = cgats_1.parent.parent
		if cgats_1.queryv1("NUMBER_OF_SETS"):
			if cgats_1.queryv1("DATA_FORMAT"):
				for field in required:
					if not field in list(cgats_1.queryv1("DATA_FORMAT").values()):
						raise CGATS.CGATSKeyError("Missing required field: %s" % field)
				if not ignore_unknown:
					for field in list(cgats_1.queryv1("DATA_FORMAT").values()):
						if not field in required:
							raise CGATS.CGATSError("Unknown field: %s" % field)
			else:
				raise CGATS.CGATSInvalidError("Missing DATA_FORMAT")
		else:
			raise CGATS.CGATSInvalidError("Missing NUMBER_OF_SETS")
		modified = cgats_1.modified
		cgats_1.filename = cgats.filename
		cgats_1.modified = modified
		return cgats_1
	else:
		raise CGATS.CGATSKeyError("Missing required fields: %s" %
								  ", ".join(required))

def verify_ti1_rgb_xyz(cgats):
	"""
	Verify and return a CGATS instance or None on failure.

	Verify if a CGATS instance has a TI1 section with all required fields
	for RGB devices. Return the TI1 section as CGATS instance on success,
	None on failure.

	"""
	return verify_cgats(cgats, ("RGB_R", "RGB_B", "RGB_G",
								"XYZ_X", "XYZ_Y", "XYZ_Z"))


import dash
import dash_core_components as dcc
import dash_html_components as html
import plotly.graph_objects as go
from dash.dependencies import Input, Output, State
import pandas as pd
import numpy as np
import plotly.figure_factory as ff
import plotly.express as px
from urllib.request import urlopen
import json
import dash_bootstrap_components as dbc
import plotly.io as pio

external_stylesheets = [
    'https://codepen.io/chriddyp/pen/bWLwgP.css',
   {
        'href': 'https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css',
        'rel': 'stylesheet',
#         'integrity': 'sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO',
    'crossorigin': 'anonymous'
   }
]
data=pd.read_csv('Data_Gurgen_Blbulyan.csv')
data=data.drop('Unnamed: 0',axis=1)
data.set_index('lead_id',inplace=True)

metadata=pd.read_excel('readme.xlsx')
bool_columns=metadata[metadata['type']=='bool']['Variable'].tolist()
count_columns=metadata[metadata['type']=='continuous']['Variable'].tolist()
cat_columns=metadata[metadata['type']=='categorical']['Variable'].tolist()
date_columns=metadata[metadata['type']=='datetime']['Variable'].tolist()
id_columns=metadata[metadata['type']=='id']['Variable'].tolist()
geo_columns=metadata[metadata['type']=='geospacial']['Variable'].tolist()

data[bool_columns]=data[bool_columns].astype('bool')
data[count_columns]=data[count_columns].astype('float')
data[cat_columns]=data[cat_columns].astype('category')
data[date_columns]=data[date_columns].astype('datetime64[ns]')

ddd=pd.read_csv('uszips.csv',dtype={"county_fips": str})
dd=ddd[['zip','county_name','county_fips']]
data=data.merge(dd,'left',on='zip')

data.dropna(inplace=True)
datascl=data.copy()
datascl[count_columns]=(datascl[count_columns]-datascl[count_columns].min())/(datascl[count_columns].max()-datascl[count_columns].min())

with urlopen('https://raw.githubusercontent.com/plotly/datasets/master/geojson-counties-fips.json') as response:
    counties = json.load(response)

pio.templates.default = "ggplot2"
app = dash.Dash(external_stylesheets =external_stylesheets)

app.layout = html.Div([
            html.H1("Dataviz Dashboard with Dash", style={'text-align': 'center'}),

            html.Div([
                   html.Div([

                               html.Div([dcc.Graph(figure = {},id='map1')]),
                               html.Div([
                                   html.Div([dcc.Dropdown(
                                    id = 'map1_bool',
#                                     value=bool_columns[0],
                                    options =  [{'label': i, 'value': i} for i in bool_columns],

                                    placeholder="Select a boolian variable")],className = 'four columns'),

                                   html.Div([dcc.Dropdown(
                                    id = 'map1_color',
                                    options =  [{'label': i, 'value': i} for i in cat_columns],
#                                     value=cat_columns[0],
                                    placeholder="Select a color variable")],className = 'four columns'),

                                   html.Div([dcc.Dropdown(
                                    id = 'map1_size',
                                    options =  [{'label': i, 'value': i} for i in count_columns],
#                                     value=count_columns[0],
                                    placeholder="Select a size variable")],className = 'four columns'),

                               ],className = 'row')

                   ],className = 'eight columns'),

                   html.Div([
                               html.Div([dcc.Graph(figure = {},id='box1')]),
                               html.Div([
                                   html.Div([dcc.Dropdown(
                                    id = 'box_bool',
                                    options =  [{'label': i, 'value': i} for i in bool_columns],

                                    placeholder="Select a boolian variable")],className = 'six columns'),

                                   html.Div([dcc.Dropdown(
                                    id = 'box_count',
                                    options = [{'label': i, 'value': i} for i in count_columns],

                                    placeholder="Select a continuous variable")],className = 'six columns')

                               ],className = 'row')

                  ],className = 'four columns')

            ], className = 'row'),

    html.Div([
                   html.Div([

                               html.Div([dcc.Graph(figure = {},id='scater1')]),
                               html.Div([dcc.Dropdown(id='scat_count',
    options=[{'label': i, 'value': i} for i in count_columns],
    placeholder="Select a 3 continuous variable last for size"   ,

    multi=True
)  ])

                   ],className = 'four columns'),

                   html.Div([
                               html.Div([dcc.Graph(figure = {},id='coloplath1')]),
                               html.Div([
                                   html.Div([dcc.Dropdown(
                                    id = 'coloplath_state',
                                    options =  [{'label': i, 'value': i} for i in count_columns],

                                    placeholder="Select a continuous variable")])

                               ])

                  ],className = 'eight columns')

            ], className = 'row'),

html.Div([

                               html.Div([dcc.Graph(figure = {},id='violin')]),
                               html.Div([
                                   html.Div([dcc.Dropdown(
                                    id = 'violin_bool',
                                    options =  [{'label': i, 'value': i} for i in bool_columns],

                                    placeholder="Select a boolian variable")],className = 'four columns'),

                                   html.Div([dcc.Dropdown(
                                    id = 'violin_count',
                                    options = [{'label': i, 'value': i} for i in count_columns],

                                    placeholder="Select a continuous variable")],className = 'four columns'),
                               html.Div([dcc.Dropdown(
                                    id = 'violin_cat',
                                    options = [{'label': i, 'value': i} for i in cat_columns+bool_columns],

                                    placeholder="Select a categorical variable")],className = 'four columns')

                               ],className = 'row')

                   ]),

html.Div([

                   html.Div([

                               html.Div([dcc.Graph(figure = {},id='distplot')]),
                               html.Div([
                                   html.Div([dcc.Dropdown(
                                    id = 'dist_ver',
                                    options =  [{'label': i, 'value': i} for i in count_columns],
                                    multi=True,
                                    placeholder="Select a continuous variable")],className = 'six columns'),

                                   html.Div([dcc.Slider(
        id='my_slider',
        min=0,
        max=1,
        step=0.1,
        value=0.25,
    )],className = 'six columns'),

                               ],className = 'row')

                   ],className = 'six columns'),

    html.Div([

                               html.Div([dcc.Graph(figure = {},id='countplot')]),
                               html.Div([dcc.Dropdown(id='count_cat',
    options=[{'label': i, 'value': i} for i in bool_columns+cat_columns],
    placeholder="Select a 2 categorical variable",
    multi=True
)  ])

                   ],className = 'six columns'),

            ], className = 'row'),

    html.Div([

                               html.Div([dcc.Graph(figure = {},id='map2')]),
                               html.Div([
                                   html.Div([dcc.Dropdown(
                                    id = 'map2_val',
                                    options =  [{'label': i, 'value': i} for i in count_columns],

                                    placeholder="Select a continuous variable")],className = 'six columns'),

                                   html.Div([dcc.RangeSlider(
        id='my_rangslider',
        min=0,
        max=1,
        step=0.1,
        value=[0.5,0.7],
    )],className = 'six columns')

                   ],className='row'),

            ]),

], className = 'container')

@app.callback(
    [Output(component_id='map1', component_property='figure'),
     Output(component_id='box1', component_property='figure'),
     Output(component_id='scater1', component_property='figure'),
     Output(component_id='coloplath1', component_property='figure'),
     Output(component_id='violin', component_property='figure'),
     Output(component_id='distplot', component_property='figure'),
     Output(component_id='countplot', component_property='figure'),
     Output(component_id='map2', component_property='figure')
    ],
    [Input(component_id='map1_bool', component_property='value'),
     Input(component_id='map1_color', component_property='value'),
     Input(component_id='map1_size', component_property='value'),
     Input(component_id='box_bool', component_property='value'),
     Input(component_id='box_count', component_property='value'),
     Input(component_id='scat_count', component_property='value'),
     Input(component_id='coloplath_state', component_property='value'),
     Input(component_id='violin_count', component_property='value'),
     Input(component_id='violin_bool', component_property='value'),
     Input(component_id='violin_cat', component_property='value'),
     Input(component_id='my_slider', component_property='value'),
     Input(component_id='dist_ver', component_property='value'),
     Input(component_id='count_cat', component_property='value'),
     Input(component_id='map2_val', component_property='value'),
     Input(component_id='my_rangslider', component_property='value')
    ]
)
def update_graph(map1_bool,map1_color,map1_size,box_bool,box_count,scat_count,
                 coloplath_state,violin_count,violin_bool,violin_cat,
                 my_slider,dist_ver,count_cat,map2_val,my_rangslider):

    try:
        fig = px.scatter_mapbox(data[data[map1_bool]==True].copy(), lat="latitude", lon="longitude",         hover_name="country_code",color=map1_color,size=map1_size,title='Check the boolean variables location', zoom=3,size_max=15)
        fig.update_layout(mapbox_style="open-street-map")

    except:
        fig = px.scatter_mapbox(data[data['black_ip']==True], lat="latitude", lon="longitude",         hover_name="country_code",color='gender',size='amount_request',title='Check the boolean variables location', zoom=3,size_max=15)
        fig.update_layout(mapbox_style="open-street-map")
    try:
        fig1 = px.box(data,x=box_bool,  y=box_count,title='Box plot with boolian variable')
    except:
        fig1 = px.box(data, x="target", y='amount_request',title='Box plot with boolian variable')

    try:
        fig2 = px.scatter(data, x=scat_count[0], y=scat_count[1],size=scat_count[2],title='Scatter plot with size')

    except:
        fig2 = px.scatter(data, x="emptime", y="monthlyincome",size='emptime',title='Scatter plot with size')

    try:
        fig3 = px.choropleth(data.groupby('state')[coloplath_state].mean().reset_index(),locations='state', locationmode="USA-states", color=coloplath_state, scope="usa",title='Choropleth for USA state level')

    except:
        fig3 = px.choropleth(data.groupby('state')['median_income'].mean().reset_index(),locations='state', locationmode="USA-states", color='median_income', scope="usa",title='Choropleth for USA state level')

    try:
        fig4 = go.Figure()

        fig4.add_trace(go.Violin(x=data[violin_cat][ data[violin_bool] == True],
                        y=data[violin_count][ data[violin_bool] == True ],
                        legendgroup='Yes', scalegroup='Yes', name='Yes',
                        side='negative',
                        line_color='blue')
             )
        fig4.add_trace(go.Violin(x=data[violin_cat][ data[violin_bool] == False ],
                        y=data[violin_count][ data[violin_bool] == False ],
                        legendgroup='No', scalegroup='No', name='No',
                        side='positive',
                        line_color='orange')
             )
        fig4.update_traces(meanline_visible=True)
        fig4.update_layout(violingap=0, violinmode='overlay')

    except:
        fig4 = go.Figure()

        fig4.add_trace(go.Violin(x=data['day'][ data['target'] == True],
                        y=data['monthlyincome'][ data['target'] == True ],
                        legendgroup='Yes', scalegroup='Yes', name='Yes',
                        side='negative',
                        line_color='blue')
             )
        fig4.add_trace(go.Violin(x=data['day'][ data['target'] == False ],
                        y=data['monthlyincome'][ data['target'] == False ],
                        legendgroup='No', scalegroup='No', name='No',
                        side='positive',
                        line_color='orange')
             )
        fig4.update_traces(meanline_visible=True)
        fig4.update_layout(violingap=0, violinmode='overlay',title='Violin plot')

    try:
        fig5 = ff.create_distplot([datascl[c] for c in dist_ver] , dist_ver, bin_size=my_slider,show_rug=False)
    except:
        fig5 = ff.create_distplot([datascl['monthlyincome']], ['monthlyincome'], bin_size=.25,show_rug=False)
    fig5.update_layout(title='Distribution plot')

    try:
        fig6 = px.histogram(data, x=count_cat[0], color=count_cat[1])
    except:
        fig6 = px.histogram(data, x="target", color="bypass")

    fig6.update_layout(title='Count plot')

    try:
        fig7 = px.choropleth(datascl, geojson=counties, locations='county_fips', color=map2_val,
                           color_continuous_scale="Viridis",
                           range_color=my_rangslider,
                           scope="usa",

                          )

    except:
        fig7 = px.choropleth(datascl, geojson=counties, locations='county_fips', color='score',
                           color_continuous_scale="Viridis",
                           range_color=(0, 20),
                           scope="usa",

                          )
    fig7.update_layout(title='ZIP level Choropleth')
    return fig,fig1,fig2,fig3,fig4,fig5,fig6,fig7

if __name__ == '__main__':
    app.run_server(debug=True)

#https://github.com/Coding-with-Adam/Dash-by-Plotly/blob/master/Other/Dash_Introduction/intro.py
#https://dataviz.shef.ac.uk/blog/12/06/2020/dash-tutorial-2
#https://github.com/plotly/dash-sample-apps/tree/main/apps


import itertools

def init_guess_set():
    stuff = [[1, 2, 3, 4, 5, 6], [1, 2, 3, 4, 5, 6], [1, 2, 3, 4, 5, 6], [1, 2, 3, 4, 5, 6]]
    S = itertools.product(*stuff)
    S2 = []
    for thing in S:
        S2.append(thing)

    return S2

def best_guess(S):

    most_removed = 0
    best = None
    for guess in S:
        num_eliminated = least_eliminated(S, guess)
        if num_eliminated >= most_removed:
            most_removed == num_eliminated
            best = guess

    return best

def least_eliminated(S, guess):

    possible_responses = [(0, 0), (0, 1), (0, 2), (0, 3), (0, 4), (1, 0), (1, 1), (1, 2), (1, 3), (2, 0), (2, 1), (2, 2), (3, 0), (3, 1), (4, 0)]
    least_removed = 1296
    for response in possible_responses:
        remove_count = count_not_matching(S, guess, response)
        if remove_count < least_removed:
            least_removed = remove_count

    return least_removed

def count_not_matching(S, guess, response):

    whites, blacks = response
    remove_count = 0
    for combo in S:
        if not check_blacks(guess, combo, blacks) or not check_whites(guess, combo, whites, blacks):
            remove_count += 1

    return remove_count

def remove_not_matching(S, guess, response):

    whites, blacks = response
    remove_count = 0
    S2 = list(S)
    for combo in S:
        if not check_blacks(guess, combo, blacks) or not check_whites(guess, combo, whites, blacks):
            S2.remove(combo)

    return S2

def check_whites(previous_guess, new_guess, num_whites, num_blacks):

    pguess = list(previous_guess)
    nguess = list(new_guess)
    num_hits = 0

    for peg in pguess:
        if peg in nguess:
            num_hits += 1
            nguess.remove(peg)

    if num_hits == num_whites + num_blacks:
        return True

    else:
        return False

def check_blacks(previous_guess, new_guess, num_blacks):

    pguess = list(previous_guess)
    nguess = list(new_guess)
    num_hits = 0

    for i, peg in enumerate(pguess):
        if nguess[i] == peg:
            num_hits += 1

    if num_hits == num_blacks:

        return True

    else:
        return False


import click
import os
import hashlib
import time
import sys

from qcloud_cos import CosConfig
from qcloud_cos import CosS3Client
import logging

logging.basicConfig(level=logging.INFO, stream=sys.stdout)
# 腾讯云COS密钥
secret_id = ""
secret_key = ""
token = None               # 如果使用永久密钥不需要填入token，如果使用临时密钥需要填入，临时密钥生成和使用指引参见https://cloud.tencent.com/document/product/436/14048
# 区域
region = ''
# 存储桶名
bucket_name = ""
# 自定义腾讯存储路径名
upload_name = ""
search_path = path = os.getcwd() + os.sep

# 腾讯云COS 初始化
config = CosConfig(Region=region, SecretId=secret_id, SecretKey=secret_key, Token=token)
client = CosS3Client(config)

def get_file_md5(file):
    with open(file, 'rb') as fp:
        data = fp.read()
        return hashlib.md5(data).hexdigest()

def upload_file(key, path):
    md5 = get_file_md5(path)
    if containMd5(md5) and not ignoreMd5:
        print('忽略文件: '+path)
        return
    try:
        response = client.upload_file(
            Bucket=bucket_name,
            LocalFilePath=path,
            Key=key,
            PartSize=1,
            MAXThread=4,
            EnableMD5=False
        )
        if response['ETag']:
            print("上传成功: " + upload_name+path)
            addLog(md5,path)
            return 1
    except BaseException:
        print("上传失败: "+path)
        return 0

def addLog(md5, path):
    localTime = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
    list_files.append(md5 + "," + path + "," + localTime)
    list_md5.append(md5)

def createLog():
    createFile("logs.log", list_files)
    print('已上传' + str(len(list_files)) + '个文件')

def insertMd5():
    createFile("md5.txt", list_md5)

def createFile(name, list):
    dirname, filename = os.path.split(os.path.abspath(sys.argv[0]))
    file = open(dirname + os.sep + name, 'a', encoding='utf-8')
    for fileName in list:
        file.write(fileName + '\n')
    file.close()

def containMd5(md5):
    if list_md5.__contains__(md5):
        return True
    return False

def loadMd5():
    dirname, filename = os.path.split(os.path.abspath(sys.argv[0]))
    path = dirname + os.sep + "logs.log"
    if not os.path.exists(path):
        os.mknod(path)
    file = open(path, 'r')
    if file is None:
        return
    lines = file.readlines()
    for line in lines:
        md5 = line.replace("\n", "").split(",")[0]
        if not containMd5(md5):
            list_md5.append(md5)

list_md5 = []
list_files = []

def scanfile(dir):
    for path, d, filelist in os.walk(dir):
        for filename in filelist:
            full_path = os.path.join(path, filename)
            if containType(full_path):
                md5 = get_file_md5(full_path)
                if not containMd5(md5):
                    allfiles.append(full_path)

def containType(path):
    if file_types is None:
        return True
    for ftype in file_types:
        if path.endswith("." + ftype):
            return True
    return False

allfiles = []
ignoreMd5 = False
file_types = None

@click.command()
@click.option('-f', "--file", type=str, default=None, help="单个文件压缩")
@click.option('-d', "--dir", type=str, default=None, help="被压缩的文件夹")
@click.option('-i', "--ignore", type=bool, default=False, help="忽略MD5验证")
@click.option('-p', "--path", type=str, default="", help="七牛云自定义路径")
@click.option('-t', "--type", type=str, default=None, help="指定文件后缀")
def run(file, dir, ignore, path, type):
    global ignoreMd5
    ignoreMd5 = ignore

    global upload_name
    upload_name = path

    if type is not None:
        global file_types
        file_types = type.split(",")
    if file is not None:
        allfiles.append(file)
        pass
    elif dir is not None:
        scanfile(dir)
        pass
    else:
        print("未指定文件夹，自动定位当前运行目录")
        scanfile(search_path)
        pass
    print("开始上传文件：腾讯云COS路径", ("/" if upload_name == "" else upload_name))
    runUpload()
    createLog()

def runUpload():
    for file in allfiles:
        upload_path = (upload_name + file).replace(os.sep + os.sep, os.sep)
        upload_path = upload_path[1:] if upload_path[0]=='/' else upload_path
        if upload_file(upload_path, file): continue

if __name__ == '__main__':
    try:
        loadMd5()
        run()
    except SystemExit:
        pass
    except BaseException as e:
        raise e


from sys import stdin

for _ in range(int(stdin.readline())):
    n = int(stdin.readline())
    a = list(map(int, stdin.readline().split()))
    cur_max = a[0]
    max_diff = 0
    t = 0
    b = []
    c = []
    s = 0
    for i in range(n):
        if a[i] > cur_max:
            cur_max = a[i]
        elif cur_max - a[i] > max_diff:
            max_diff = cur_max - a[i]
    while s < max_diff:
        s += 2**t
        t += 1
    print(t)


import sklearn
import time
import random
import numpy as np
import matplotlib.pyplot as plt
import sqlite3
import cv2

from numpy.linalg import inv

from scipy.spatial.distance import euclidean,cityblock,squareform
from scipy.cluster.hierarchy import dendrogram, linkage, ward

from fastdtw import fastdtw

from sklearn.cluster import DBSCAN, AgglomerativeClustering, AffinityPropagation, SpectralClustering
import scipy.spatial.distance as ssd

def discretize(square_side_size,trajectory):
    Discretized_trajectory = []
    for point in trajectory:
        i = int(point[1]/square_side_size)
        j = int(point[0]/square_side_size)
        square = [i,j]
        if  len(Discretized_trajectory) == 0 or Discretized_trajectory[-1] != square:
            Discretized_trajectory.append(square)
    return Discretized_trajectory

def distance_matrix(trajectories):
    l =len(trajectories)
    D = np.zeros((l,l))
    for i in range(l):
        for j in range(i,l):
            #D[i,j] = my_affinity_wrapper(trajectories[i],trajectories[j])
            #D[i,j],p = fastdtw(trajectories[i],trajectories[j], dist=euclidean)
            D[i,j],p = fastdtw(trajectories[i],trajectories[j], dist=cityblock)
            D[j,i] = D[i,j]
    return D

data_file = "laurier.sqlite"
data_base = sqlite3.connect(data_file)
cursor = data_base.cursor()
#data_base.commit()

db_request1 = "SELECT max(trajectory_id), min(trajectory_id) FROM positions"
max_min = cursor.execute(db_request1).fetchall()
nb_trajectory = max_min[0][0]- max_min[0][1] +1

trajectories = np.array([
    cursor.execute(
        "SELECT p.x_coordinate,p.y_coordinate \
        FROM positions as p \
        WHERE trajectory_id ="+str(i)+" ORDER BY p.frame_number ASC"
    ).fetchall() for i in range(nb_trajectory)
])

H = np.loadtxt("laurier-homography.txt")
h = inv(H)

pixel_trajectories = []
for trajectory in trajectories:
    new_points = []
    for point in trajectory:
        new_point = np.array([point[0],point[1],1])
        new_point = np.matmul(h,new_point)
        new_point = [new_point[0]/new_point[2],new_point[1]/new_point[2]]
        new_points.append(new_point)
    pixel_trajectories.append(new_points)

square_side_size = 10
discretized_pixel_trajectories = [discretize(square_side_size,trajectory) for trajectory in pixel_trajectories]

times=[]
start = time.time()
D = distance_matrix(discretized_pixel_trajectories[:])
end = time.time()-start
times.append(end)
print(end)

np.savetxt("Distances/cityblock_10.txt",D)


import email
import email.policy
import time
from datetime import datetime, timedelta

from mogo import Model, Field, EnumField, ReferenceField
from twisted.internet import defer

from ..common.db_common import get_db
from ..common.encoding import force_str, force_bytes

class RECIPIENT_STATUS:
    UNVERIFIED         = 'UNVERIFIED'       # Temporary state for existing recipients at satellite startup
    READY              = 'READY'
    FINISHED           = 'FINISHED'
    TIMEOUT            = 'TIMEOUT'
    GENERAL_ERROR      = 'GENERAL_ERROR'
    ERROR              = 'ERROR'
    WARNING            = 'WARNING'
    IN_PROGRESS        = 'IN PROGRESS'

recipient_status = (RECIPIENT_STATUS.UNVERIFIED,
                    RECIPIENT_STATUS.READY,
                    RECIPIENT_STATUS.IN_PROGRESS,
                    RECIPIENT_STATUS.WARNING,
                    RECIPIENT_STATUS.FINISHED,
                    RECIPIENT_STATUS.ERROR,
                    RECIPIENT_STATUS.TIMEOUT,
                    RECIPIENT_STATUS.GENERAL_ERROR,
                    )

class Mailing(Model):
    """Used to store headers and body."""
    # id              = models.IntegerField(primary_key=True)  # Should be the same as mailing_id in Master
    type            = Field()
    testing         = Field(bool, default=False)    # If True, emails are sent to a testing SMTP server instead of the real one.
    backup_customized_emails = Field(bool, default=False)  # If True, customized emails will be included in recipients reports.
    read_tracking   = Field(bool, default=True)     # If True, read tracking image are added to html bodies
    click_tracking  = Field(bool, default=False)    # If True, links found into html bodies are converted to allow clicks tracking
    body_downloaded = Field(bool, default=False)
    header          = Field()
    body            = Field()
    tracking_url    = Field()       # Base url for all tracking links
    deleted         = Field(bool, default=False)    # Mailing deletion requested. Will occur once all its recipients will be removed.
    dkim            = Field()  # dkim settings (dictionary). Fields are enabled (Default=True), selector, domain, privkey
    feedback_loop   = Field()  # Settings needed to implement the Google Feedback Loop requirements (dictionary)
                                # Fields are `campain_id`, `customer_id`, `mail_type_id`, `sender_id`
                                # and `dkim` which contains dkim settings for fbl domain.
                                # defaults are (in order): 'mailing.id', 'mailing.domain_name', 'mailing.type'.
                                # Other are mandatory.
    domain_name     = Field()   # sender domain
    return_path_domain = Field()   # domain used to fill Return-Path header. If None, header won't be added.
    url_encoding    = Field()

    created         = Field(datetime, default=datetime.utcnow)
    modified        = Field(datetime, default=datetime.utcnow)

    _id_type = int

    def __unicode__(self):
        return "Queue[%d]" % self.id

    def save(self, *args, **kwargs):
        if not self._id:
            raise ValueError("Mailing model: An id have to be provided")
            # super(Model, self).__setitem__(self._id_field, Sequence.get_next('mailing_id'))
        self.modified = datetime.utcnow()
        return super(Mailing, self).save(*args, **kwargs)

    def get_message(self):
        """
        Returns the mailing content as email message object.
        """
        mparser = email.parser.BytesFeedParser(policy=email.policy.default)
        mparser.feed(force_bytes(self.header))
        mparser.feed(force_bytes(self.body))
        return mparser.close()

class MailingRecipient(Model):
    # id              = AutoField(primary_key=True)
    # recipient_id     = models.IntegerField(db_index=True)   # ID on master
    mailing         = ReferenceField(Mailing, required=True)
    tracking_id     = Field()
    contact_data    = Field()  # Python dictionary containing all recipient fields
    email           = Field(required=True)
    mail_from       = Field(required=False)
    sender_name     = Field()
    domain_name     = Field(required=True)   # Recipient's domain name
    first_try       = Field(datetime)
    next_try        = Field(datetime)  # TODO maybe a int from EPOCH would be faster
    try_count       = Field(int)
    send_status     = EnumField(recipient_status, default=RECIPIENT_STATUS.READY)
    reply_code      = Field(int)
    reply_enhanced_code = Field()
    reply_text      = Field()
    smtp_log        = Field()
    in_progress     = Field(bool, default=False)  # added in temp queue
    created         = Field(datetime, default=datetime.utcnow)
    modified        = Field(datetime, default=datetime.utcnow)
    finished        = Field(bool, default=False)  # True if this recipient have been handled (successfully or not) and should be returned back to the master.

    def __unicode__(self):
        return self.email

    def save(self, *args, **kwargs):
        self.modified = datetime.utcnow()
        return super(MailingRecipient, self).save(*args, **kwargs)

    def set_send_mail_in_progress(self):
        self.send_status = RECIPIENT_STATUS.IN_PROGRESS
        if self.try_count is None:
            self.try_count = 0
        self.try_count += 1
        self.in_progress = True
        if not self.first_try:
            self.first_try = datetime.utcnow()
        self.next_try = datetime.utcnow()
        self.save()

    def update_send_status(self, send_status, smtp_code=None, smtp_e_code=None, smtp_message=None, in_progress=False,
                           smtp_log=None, target_ip=None):
        """
        Updates the contact status.
        """
        LiveStats.add_log(mailing_id = self.mailing.id, domain_name=self.domain_name,
                          mail_from=self.mail_from, mail_to=self.email,
                          send_status=send_status, reply_code=smtp_code, reply_enhanced_code=smtp_e_code,
                          reply_text=smtp_message, target_ip=target_ip)
        self.send_status = send_status
        if send_status == RECIPIENT_STATUS.FINISHED:
            self.next_try = datetime.utcnow()
        self.reply_code = smtp_code and smtp_code or None
        self.reply_enhanced_code = smtp_e_code and smtp_e_code or None
        self.reply_text = smtp_message and force_str(smtp_message, errors='replace') or None
        self.smtp_log = smtp_log and str(smtp_log, errors='replace') or None
        self.in_progress = in_progress
        self.save()
        #if send_status in (RECIPIENT_STATUS.ERROR, RECIPIENT_STATUS.GENERAL_ERROR):
            #self.contact.status = CONTACT_STATUS.ERROR
            #self.contact.save()
        #elif send_status == RECIPIENT_STATUS.FINISHED:
            #self.contact.status = CONTACT_STATUS.VALID
            #self.contact.save()

    def set_send_mail_next_time(self):
        """
        This implement the mailing specific strategy for retries and mark this entry as removable from queue.
        """
        self.in_progress = False
        if self.try_count < 3:
            self.next_try = datetime.utcnow() + timedelta(minutes=10)
        elif self.try_count < 10:
            self.next_try = datetime.utcnow() + timedelta(minutes=60)
        else:
            self.next_try = datetime.utcnow() + timedelta(hours=6)
        self.finished = True
        self.save()

    def mark_as_finished(self):
        self.finished = True
        self.save()

class HourlyStats(Model):
    date        = Field(datetime)
    epoch_hour  = Field(int)
    sent        = Field(int, default=0)
    failed      = Field(int, default=0)
    tries       = Field(int, default=0)  # Total tentatives count, including sent, failed and temporary failed.
    up_to_date  = Field(bool, default=False)  # If false, this entry needs to be sent to the CloudMaster.

    @staticmethod
    def __generic_update(operations):
        r = HourlyStats.update({'epoch_hour': int(time.time() / 3600)},
                               dict(operations, **{'$set': {'up_to_date': False}}),
                               upsert=True,
                               w=1)
        if r is None or not r['updatedExisting']:
            # entry = HourlyStats.search_or_create(epoch_hour=int(time.time() / 3600))
            entry = HourlyStats.grab(r['upserted'])
            entry.update(date=datetime.utcnow().replace(minute=0, second=0, microsecond=0))

    @staticmethod
    def add_sent():
        HourlyStats.__generic_update({'$inc': {'sent': 1, 'tries': 1}})

    @staticmethod
    def add_failed():
        HourlyStats.__generic_update({'$inc': {'failed': 1, 'tries': 1}})

    @staticmethod
    def add_try():
        HourlyStats.__generic_update({'$inc': {'tries': 1}})

class DomainStats(Model):
    """
    Tracks DNS resolution statistics as well as handled recipients count per domains.
    Also tracks any DNS error on domains resolution. It allows to take decision for domain's recipients if error
    is fatal (no-retry) or not (retry).
    For DNS error, there are two levels:
        - recoverable errors: these errors can be due to temporary network problems. So they should never be fatal for
         concerned recipients.
        - fatal errors: these errors are clearly identified as fatal, i.e. we CAN'T address these recipients in any way
         (for example, the DNS really answer us that the domain doesn't exist). In this case, we will try again later
         (in case in unexpected error with the DNS) but only few times (5 by default).
    """
    domain_name     = Field(required=True)  # Recipient's domain name

    # at recipient level (+1 for each recipient)
    sent        = Field(default=0)
    failed      = Field(default=0)
    tries       = Field(default=0)  # help_text="Total tentatives count, including sent, failed and temporary failed.")

    consecutive_sent = Field(default=0)
    consecutive_failed = Field(default=0)  # including softbounce and hardbounce

    # at DNS level (+1 for each DNS query)
    dns_tries           = Field(default=0)  # help_text="Total tentatives count, including fatal and temporary failed.")
    dns_temp_errors     = Field(default=0)  # help_text="Errors due to temporal circumstances. Its can be solved later.")
    dns_fatal_errors    = Field(default=0)
    dns_last_error      = Field()           # help_text="Full class name of the exception.")

    dns_cumulative_temp_errors  = Field(default=0)  # help_text="This counter is never reset")
    dns_cumulative_fatal_errors = Field(default=0)  # help_text="This counter is never reset")

    created         = Field(datetime, default=datetime.utcnow)
    modified        = Field(datetime, default=datetime.utcnow)

    def save(self, *args, **kwargs):
        self.modified = datetime.utcnow()
        return super(DomainStats, self).save(*args, **kwargs)

    @staticmethod
    def get_exception_fullname(ex):
        return "%s.%s" % (ex.__class__.__module__, ex.__class__.__name__)

    def check_error(self, ex):
        return DomainStats.get_exception_fullname(ex) == self.dns_last_error

    @staticmethod
    def __generic_update(domain, operations):
        operations.setdefault('$set', {})['modified'] = datetime.utcnow()
        r = DomainStats.update({'domain_name': domain},
                               operations,
                               upsert=True)
        # if r is None or not r['updatedExisting']:
        #     entry = DomainStats.search_or_create(domain_name=domain)
        #     kwargs = {}
        #     for key, value in operations['$inc'].items():
        #         kwargs[key] = value
        #     entry.update(date=datetime.utcnow().replace(minute=0, second=0, microsecond=0), **kwargs)

    @staticmethod
    def add_sent(domain):
        DomainStats.__generic_update(domain, {'$inc': {'sent': 1, 'tries': 1, 'consecutive_sent': 1},
                                              '$set': {'consecutive_failed': 0}})

    @staticmethod
    def add_failed(domain):
        DomainStats.__generic_update(domain, {'$inc': {'failed': 1, 'tries': 1, 'consecutive_failed': 1},
                                              '$set': {'consecutive_sent': 0}})

    @staticmethod
    def add_try(domain):
        DomainStats.__generic_update(domain, {'$inc': {'tries': 1, 'consecutive_failed': 1},
                                              '$set': {'consecutive_sent': 0}})

    @staticmethod
    def add_dns_success(domain):
        DomainStats.__generic_update(domain, {'$inc': {'dns_tries': 1},
                                              '$set': {'dns_temp_errors': 0,
                                                       'dns_fatal_errors': 0,
                                                       'dns_last_error': None}})

    @staticmethod
    def add_dns_temp_error(domain, ex):
        DomainStats.__generic_update(domain, {'$inc': {'tries': 1,
                                                       'dns_tries': 1,
                                                       'dns_temp_errors': 1,
                                                       'dns_cumulative_temp_errors': 1},
                                              '$set': {'dns_last_error': DomainStats.get_exception_fullname(ex)}})

    @staticmethod
    def add_dns_fatal_error(domain, ex):
        DomainStats.__generic_update(domain, {'$inc': {'tries': 1,
                                                       'failed': 1,
                                                       'dns_tries': 1,
                                                       'dns_fatal_errors': 1,
                                                       'dns_cumulative_fatal_errors': 1},
                                              '$set': {'dns_last_error': DomainStats.get_exception_fullname(ex)}})

    @staticmethod
    def get_domains_notation() -> dict:
        pipeline = [{
            "$match": {"$or": [{"consecutive_sent": {"$gte": 0}}, {"consecutive_failed": {"$gte": 0}}]}
        }, {
            "$addFields": {
                "age_hours": {
                    "$divide": [{
                        "$subtract": [datetime.utcnow(), "$modified"]
                    }, 3600000]
                }
            }
        }, {
            "$project": {
                "domain_name":        1,
                "age_hours":          1,
                "consecutive_sent":   1,
                "consecutive_failed": 1,
                "note":               {
                    "$divide": [{
                        "$subtract": ["$consecutive_sent",
                                      {"$subtract": [{"$exp": {"$min": ["$consecutive_failed", 5]}}, 1]}]
                    }, {
                        "$max": [0.1, "$age_hours"]
                    }]
                }
            }
        }, {
            "$sort": {
                "domain_name": 1
            }
        }]
        results = DomainStats._get_collection().aggregate(pipeline)
        return {r['domain_name']: r['note'] for r in results}

class DomainConfiguration(Model):
    domain_name = Field(required=True)
#   - 'active_relayers': list of active relayers for this domain
    mx_servers = Field()  # list of MX's IPs addresses
    mx_last_updated = Field(datetime)   # datetime of the last update of MX list
    max_relayers = Field(int)   # the maximum simultaneous relayers for this domain (taken from DB
                                # or None to use the default rule = half of the MX servers)
    cnx_per_mx = Field(int)     # the maximum simultaneous connections per MX server
    max_mx = Field(int)         # the maximum simultaneous connected MX servers

class ActiveQueue(Model):
    domain_name = Field(required=True)
    recipients = Field()
    created = Field(datetime, default=datetime.utcnow)

class LiveStats():
    """
    Register all tries to allow to compute real time statistics on errors, success, softbounces, etc...
    Statistics should be by domain, by MX and by mailing
    """
    # mailing_id      = Field(int)
    # domain_name     = Field()
    # ip              = Field()
    # mail_from       = Field()
    # recipient       = Field()
    # date            = Field()
    # send_status     = EnumField(recipient_status)
    # reply_code      = Field(int)
    # reply_enhanced_code = Field()
    # reply_text      = Field()

    @staticmethod
    def add_log(mailing_id, domain_name, mail_from, mail_to, send_status, reply_code, reply_enhanced_code, reply_text,
                target_ip):
        db = get_db()
        now = datetime.utcnow()
        l = [
            db.live_stats.insert_one({'date': now,
                                      'mailing_id': mailing_id, 'domain_name': domain_name, 'ip': target_ip,
                                      'mail_from': mail_from, 'mail_to': mail_to, 'send_status': send_status,
                                      'reply_code': reply_code, 'reply_enhanced_code': reply_enhanced_code,
                                      'reply_text': reply_text}),
            db.live_stats2.insert_one({'date': now,
                                       'mailing_id': mailing_id, 'domain_name': domain_name, 'ip': target_ip,
                                       'mail_from': mail_from, 'mail_to': mail_to, 'send_status': send_status,
                                       'reply_code': reply_code, 'reply_enhanced_code': reply_enhanced_code,
                                       'reply_text': reply_text})
        ]

        return defer.DeferredList(l)


import pkg_resources
from pip.req import parse_requirements
from setuptools import find_packages, setup

# Utility function to read the README file.
# Used for the long_description.  It's nice, because now 1) we have a top level
# README file and 2) it's easier to type in the README file than to put a raw
# string in below.

def read(fname):
    return open(pkg_resources.resource_filename(__name__, fname)).read()

# parse_requirements() returns generator of pip.req.InstallRequirement objects
install_reqs = parse_requirements('requirements.txt', session=False)

# reqs is a list of requirement
# e.g. ['django==1.5.1', 'mezzanine==1.4.6']
reqs = [str(ir.req) for ir in install_reqs]

setup(
    name="pythontest",
    version="0.0.1",
    author="Sridhar Bulusu",
    author_email="sridhar249@gmail.com",
    description="Python testing repository",
    license="BSD",
    keywords="python test",
    url="https://github.com/sbulusu/pythontest",
    packages=find_packages(),
    long_description=read('README.md'),
    classifiers=[
        "Development Status :: 3 - Alpha",
        "Topic :: Utilities",
        "License :: OSI Approved :: BSD License",
    ],
    install_requires=reqs
)


# https://velog.io/@soobin519/Python-%EB%B0%B1%EC%A4%80-2631-%EC%A4%84%EC%84%B8%EC%9A%B0%EA%B8%B0

import sys

n = int(sys.stdin().readline())

dp_table = [1] * (n+1)
nums = [0]
for i in range(n):
    nums.append(int(sys.stdin().readline()))

#가장 긴 증가하는 수열 찾기
for i in range(1,n+1):
    for j in range(1,i):
        if nums[j] < nums[i]:
            dp_table[i]=max(dp_table[i],dp_table[j]+1)

#n- 긴 증가하는 부분수열의 길이
print(n-max(dp_table))


#!/usr/bin/python3
'''ping sweep utility to automate and capture some of the results of
a ping sweep across the network

Usage:
        ./pysweep.py <ip> <cidr>

If <cidr> is not specified, default is "/27".

Sample:
        ./pysweep.py 192.168.0.23 /27
        ./pysweep.py 192.168.0.23
        ./pysweep.py 192.168.0.23 /24
'''
import subprocess
import sys
from datetime import datetime
import ipaddress

# global variables
detected_ip_list = []
sys.tracebacklimit = 0 # comment this to see tracebacks

def create_ip_list(ip, cidr="/27"):
    '''create a list of IP addresses'''
    ipcidr = ip + cidr
    try:
        net_ips = ipaddress.ip_network(ipcidr, strict=False)
    except ValueError:
        print('\nPlease make sure that you entered valid IP or CIDR\n')
    except TypeError:
        print('\nPlease make sure that you entered valid IP or CIDR\n')
    else:
        ip_list = [str(xip) for xip in net_ips.hosts()]
        return ip_list

def process_list(begin_time, end_time):
    '''Process List: loop over the list of detected IP addresses,
    outputs to stdout and write to file'''
    global detected_ip_list
    if detected_ip_list == []:
        print("\nSaw nothing on the network.\n")
    else:
        summary = ''
        summary += "Detected Hosts:\n===============\n"
        for ip in detected_ip_list:
            summary += f"{ip}\n"
        scan_duration = end_time - begin_time
        summary += f"\nTotal time to scan took: {scan_duration}"
        print(summary)

        with open('pingsweep-results.txt', 'w') as f:
            f.write(summary)

def fping_ip(ip):
    '''This will attempt to fping each IP in the network. Only handling SubprocessError'''
    global detected_ip_list
    try:
        output = subprocess.run(["fping", "-a", "-C", "5", "-q", ip], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
    except subprocess.SubprocessError:
        print("There was an error in the command invocation.")
    else:
        if output.returncode == 0:
            output_b = output.stdout
            output_str = output_b.decode("utf-8")
            ip, response = output_str.split(':')
            print(f"Host {ip.strip()} is detected online. Response time(s) were: {response.strip()}")
            detected_ip_list.append(ip.strip())

def main(ip, cidr):
    begin_time = datetime.now()
    ip_target_list = create_ip_list(ip, cidr)
    for ip in ip_target_list:
        fping_ip(ip)
    end_time = datetime.now()
    process_list(begin_time, end_time)

if __name__ == "__main__":
    # main("192.168.0.257", "/27") # for testing
    argv_len = len(sys.argv)
    if argv_len == 3:
        main(sys.argv[1], sys.argv[2])
    elif argv_len == 2:
        main(sys.argv[1], "/27")
    else:
        sys.exit('\ntoo many or not enough arguments.\nUSAGE: ./pysweep.py <ip> <cidr>\n')


# A bright white bag, which can hold your shiny gold bag directly.
# A muted yellow bag, which can hold your shiny gold bag directly, plus some other bags.
# A dark orange bag, which can hold bright white and muted yellow bags, either of which could then hold your shiny gold bag.
# A light red bag, which can hold bright white and muted yellow bags, either of which could then hold your shiny gold bag.

import re
import time

bagexp = re.compile("^(\d+) ([a-z ]+) bags?\.?$")
def count_bags(bag):
    count, description = bagexp.match(bag).groups()
    return (int(count), description)

def ruleparser(rule):
    main_bag, contents = rule.split(" bags contain ")
    if contents == "no other bags.":
        return main_bag, []
    return main_bag, [count_bags(bag) for bag in contents.split(', ')]

def contains_gold(bag_name, rules):
    if bag_name == "shiny gold":
        return True
    return any(contains_gold(name, rules) for _, name in rules[bag_name])

def at_least_one_shiny_goldbag(rules):
    print('Total number of bag colors that contain at least one shiny gold bag =',sum((contains_gold(name, rules) and 1 or 0) for name in rules if name != "shiny gold"))

f = open('input.txt', 'r')
data = f.read().splitlines()
rules = dict([ruleparser(line) for line in data])
at_least_one_shiny_goldbag(rules)


'''
mystr = 'Sa'
x=len(mystr)
y=mystr[len(mystr)-2:-1]
print(x)
print(y)
'''
def Selectivelist(list1):
	newlist = [ ]
	for i in list1:
		if(i > 10):
			l1=str(i)
			c=int(l1[len(l1)-2:-1])
			if(c==7):
				if(i%41==0):
					newlist.append(i)
	print(newlist)
	return(newlist)

Mylist1=[45,33,7777,78,374,24,574,764548576,779]
list2=Selectivelist(Mylist1)

offile = "Harshout1.txt"
outf = open(offile,"w")

for i in list2:
	l1=str(i)
	print(l1)
	outf.write("%s\n" % l1)


import base64
import argparse
import sys

def toBase64(text):
    #bs = base64.b64encode(text.encode('utf-8'))
    #bytes(data,‘utf-8’)
    text = bytes(text,'utf-8')
    bs = base64.b64encode(text).decode('utf-8')
    print('加密结果:',bs +'
')
    text = text + b"="
    print('解码结果:',str(base64.b64decode(text), 'gbk') + '
')

if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument('-t', '--text', type=str)
    args = parser.parse_args()
    print(toBase64(args.text))


from unittest import TestCase
from Inventory import Inventory
from Item import Item
from Local import Local
from FrameworkException import *

__author__ = 'Thadeu Jose'

class TestInventory(TestCase):

  def test_addItem(self):
    inventory = Inventory()
    item1 = Item('Test1','Test')
    item2 = Item('Test2','Test')
    inventory.addItem(item1)
    self.assertTrue(item1 in inventory)
    inventory.addItem(item2)
    self.assertTrue(item1 in inventory)
    self.assertTrue(item2 in inventory)

  def test_removeItem(self):
    inventory = Inventory()
    item1 = Item('Test1','Test')
    item2 = Item('Test2','Test')
    item3 = Item('Test3','Test')
    inventory.addItem(item1)
    inventory.addItem(item2)
    inventory.addItem(item3)
    inventory.removeItem(item2)
    self.assertNotIn(item2,inventory)

  def test_removeItem_ItemException(self):
    inventory = Inventory()
    local = Local('Test1','Test')
    with self.assertRaises(ItemException):
      inventory.addItem(local)

  def test_removeItem_EmptyInventoryException(self):
    inventory = Inventory()
    item1 = Item('Test1','Test')
    with self.assertRaises(EmptyInventoryException):
      inventory.removeItem(item1)

  def test_removeItem_ItemNotFoundException(self):
    inventory = Inventory()
    item1 = Item('Test1','Test')
    item2 = Item('Test2','Test')
    inventory.addItem(item1)
    with self.assertRaises(ItemNotFoundException):
      inventory.removeItem(item2)

  def test_print(self):
    inventory = Inventory()
    inventory.addItem(Item('Test1','Test'))
    inventory.addItem(Item('Test2','Test'))
    inventory.addItem(Item('Test2','Test'))
    inventory.addItem(Item('Test2','Test'))
    resp = str(inventory)
    self.assertEqual(resp,'Test1x1,Test2x3')


"""
Scanner module

This module implements local package scanner.
"""
import subprocess
import logging
import config
from pathlib import Path
import json

logging.basicConfig(level=logging.DEBUG, format=config.LOG_FORMAT, filename=config.LOG_FILE)
logger = logging.getLogger(__name__)

class Package:
	"""
	Represents a package.
	"""
	def __init__(self, name="", version="", architecture="", vendor="", description="", cves:dict=None, cpeid="", pdict:dict=None):
		self.name = name
		self.version = version
		self.architecture = architecture
		self.vendor = vendor
		self.description = description
		self.cves = cves
		self.cpeid = cpeid

		if pdict:
			if "name" in pdict: self.name = pdict["name"]
			if "version" in pdict: self.version = pdict["version"]
			if "architecture" in pdict: self.architecture = pdict["architecture"]
			if "vendor" in pdict: self.vendor = pdict["vendor"]
			if "description" in pdict: self.description = pdict["description"]
			if "cves" in pdict: self.cves = pdict["cves"]
			if "cpeid" in pdict: self.cpeid = pdict["cpeid"]

	def __str__(self):
		return f"\nName:{self.name}\n" \
				f"Version:{self.version}\n" \
				f"Arch:{self.architecture}\n" \
				f"Vendor:{self.vendor}\n" \
				f"Description:{self.description}\n" \
				f"CVEs:{str(self.cves)}\n" \
				f"cpeid:{self.cpeid}"

	def updatePackage(self, name=None, version=None, architecture=None, vendor=None, description=None, cves:dict=None, cpeid:dict=None):
		if name: self.name = name
		if version: self.version = version
		if architecture: self.architecture = architecture
		if vendor: self.vendor = vendor
		if description: self.description = description
		if cves: self.cves = cves
		if cpeid: self.cpeid = cpeid

class PackageContainer:
	"""
	Represents a package container
	"""
	def __init__(self, json_list=[]):
		self.packages = []

		if json_list:
			for entry in json_list:
				self.packages.append(Package(pdict=entry))
			logger.info("Loaded PackageContainer from JSON dict entries")

	def __str__(self):
		retstr = ""
		for p in self.packages:
			retstr += str(p) + "\n"
		return retstr

	def __iter__(self):
		return self.packages.__iter__()

	def __next__(self):
		return self.packages.__next__()

	def __getitem__(self, key):
		return self.packages.__getitem__(key)

	def size(self) -> int:
		"""
		Return container size.
		"""
		return len(self.packages)

	def add(self, package : Package) -> None:
		"""
		Add new package.
		"""
		self.packages.append(package)

	def toJSON(self) -> str:
		"""
		Format to JSON.
		"""
		new_packages = []
		for p in self.packages:
			new_packages.append(p.__dict__)
		json_out = json.dumps(new_packages, indent=4)
		return json_out

	def toFile(self, file_path) -> None:
		"""
		Save JSON representation of package container to file file_path.
		"""
		json_repr = self.toJSON()

		with open(file_path, "w") as f:
			f.write(json_repr)

class PackageScanner:
	"""
	Used for scanning local system for installed packages.
	"""
	def __init__(self):
		self.installed_packages = PackageContainer()
		self.package_manager = None

	def getInstalledPackages(self) -> PackageContainer:
		"""
		Get all installed packages on this machine.
		"""
		self.getPackageManager()
		if self.package_manager == "apt":
			packages = subprocess.check_output(["apt", "list", "--installed"], encoding='UTF-8', universal_newlines=True)
			packages = packages.split("\n")[1:-1]
		else:
			logger.error("Package manager not supported for extracting packages.")
			raise ValueError("Package manager unsupported")

		# Parse packages to self.installed_packages
		self.parsePackages(packages)

		logger.info("Installed packages collected")
		return self.installed_packages

	def getPackageManager(self) -> None:
		"""
		Get installed package manager and check for support.
		"""
		for pkgmgr in config.SUPPORTED_PACKAGE_MGRS:
			if subprocess.run(["which", pkgmgr]).returncode == 0:
				self.package_manager = pkgmgr
				return
		logger.error("Supported package manager not found, aborting.")
		raise ValueError("Package manager unsupported")

	def saveScanResults(self, out_path=None) -> None:
		"""
		Save results of last run to a file.
		"""
		scan_dir = Path(config.PKG_SCAN_DIR)
		if not scan_dir.is_dir():
			scan_dir.mkdir()
			logger.info(f"Created scan results directory at {config.PKG_SCAN_DIR}")

		json_results = self.installed_packages.toJSON()

		scan_file = Path(config.PKG_SCAN_FILE)
		results_path = scan_dir / scan_file
		with open(results_path, "w+") as f:
			f.write(json_results)

		logger.info(f"Scan results saved to:{results_path}")

	def parsePackages(self, packages_list) -> None:
		"""
		Parse package to extract relevant inormation.
		"""
		if self.package_manager == "apt":
			for package in packages_list:
				package = package.strip().split(" ")
				name = package[0].split("/")[0]
				version = package[1]
				architecture = package[2]
				self.installed_packages.add(Package(name=name, version=version, architecture=architecture))
		else:
			logger.error("Package manager parser not supported.")
			raise ValueError("Package manager unsupported")
		logger.info("Packages parsed successfully")


from collections import ChainMap
from typing import List

import gym
import numpy as np
import torch

from searl.neuroevolution.components.utils import to_tensor, Transition

class MPEvaluation():
    """
    evaluates and population and stores transitions an a push_queue

    """

    def __init__(self, config, logger, push_queue=None):

        self.rng = np.random.RandomState(config.seed.evaluation)
        self.cfg = config
        self.log = logger
        self.push_queue = push_queue
        self.eval_episodes = config.eval.eval_episodes

    def test_individual(self, individual, epoch):
        return_dict = self._evaluate_individual(individual, self.cfg, self.cfg.eval.test_episodes, epoch, False)
        fitness = np.mean(return_dict[individual.index]["fitness_list"])
        return fitness

    @staticmethod
    def _evaluate_individual(individual, config, num_episodes, seed, exploration_noise=False, start_phase=False):

        actor_net = individual.actor

        num_frames = 0
        fitness_list = []
        transistions_list = []
        episodes = 0

        env = gym.make(config.env.name)
        env.seed(seed)
        actor_net.eval()

        with torch.no_grad():
            while episodes < num_episodes or num_frames < config.eval.min_eval_steps:
                episode_fitness = 0.0
                episode_transitions = []
                state = env.reset()
                t_state = to_tensor(state).unsqueeze(0)
                done = False
                while not done:
                    if start_phase:
                        action = env.action_space.sample()
                        action = to_tensor(action)
                    else:
                        action = actor_net(t_state)
                    action.clamp(-1, 1)
                    action = action.data.numpy()
                    if exploration_noise is not False:
                        action += config.eval.exploration_noise * np.random.randn(config.action_dim)
                        action = np.clip(action, -1, 1)
                    action = action.flatten()

                    step_action = (action + 1) / 2  # [-1, 1] => [0, 1]
                    step_action *= (env.action_space.high - env.action_space.low)
                    step_action += env.action_space.low

                    next_state, reward, done, info = env.step(step_action)  # Simulate one step in environment

                    done_bool = 0 if num_frames + 1 == env._max_episode_steps else float(done)

                    t_next_state = to_tensor(next_state).unsqueeze(0)

                    episode_fitness += reward
                    num_frames += 1

                    transition = Transition(state, action, next_state, np.array([reward]),
                                            np.array([done_bool]).astype('uint8'))
                    episode_transitions.append(transition)
                    t_state = t_next_state
                    state = next_state
                episodes += 1
                fitness_list.append(episode_fitness)
                transistions_list.append(episode_transitions)

        return {individual.index: {"fitness_list": fitness_list, "num_episodes": num_episodes, "num_frames": num_frames,
                                   "id": individual.index, "transitions": transistions_list}}

    def evaluate_population(self, population: List, exploration_noise=False, total_frames=1, pool=None):
        population_id_lookup = [ind.index for ind in population]
        new_population_mean_fitness = np.zeros(len(population))
        new_population_var_fitness = np.zeros(len(population))

        start_phase = total_frames <= self.cfg.rl.start_timesteps
        if start_phase:
            self.log("start phase", time_step=total_frames)

        args_list = [(ind, self.cfg, self.eval_episodes, self.rng.randint(0, 100000), exploration_noise, start_phase)
                     for ind in population]
        result_dicts = [pool.apply(self._evaluate_individual, args) for args in args_list]
        result_dict = dict(ChainMap(*result_dicts))

        eval_frames = 0
        for ind_id, value_dict in result_dict.items():
            pop_idx = population_id_lookup.index(ind_id)
            new_population_mean_fitness[pop_idx] = np.mean(value_dict['fitness_list'])
            new_population_var_fitness[pop_idx] = np.var(value_dict['fitness_list'])
            eval_frames += value_dict['num_frames']

            population[pop_idx].train_log["eval_eps"] = self.eval_episodes

            for transitions in value_dict['transitions']:
                if self.cfg.nevo.ind_memory:
                    population[pop_idx].replay_memory.add(transitions)
                else:
                    self.push_queue.put(transitions)

        for idx in range(len(population)):
            population[idx].train_log["post_fitness"] = new_population_mean_fitness[idx]
            population[idx].train_log["index"] = population[idx].index
            self.log.csv.log_csv(population[idx].train_log)
            population[idx].train_log.update({"pre_fitness": new_population_mean_fitness[idx], "eval_eps": 0})
            population[idx].fitness.append(new_population_mean_fitness[idx])
            if len(population[idx].fitness) > 1:
                population[idx].improvement = population[idx].fitness[-1] - population[idx].fitness[-2]
            else:
                population[idx].improvement = population[idx].fitness[-1]

        return new_population_mean_fitness, new_population_var_fitness, eval_frames


def main():
    n = int(input("Rows: "))
    pyramid(n)
def pyramid(i):
    k=i
    for r in range(i):
        print(" "*k,end="")
        print("* "*(r+1),end="")
        print()
        k=k-1
main()


#若该函数在home.py 中，在my_view 中from home import send_email,运行时home.py 中先import my_view
#,然后在my_view 中from home import send_email，但是在home 中 import view 还没有完成，所以app.register_blueprint(my_view.views) 导入不成功
#应该算是循环导入问题
from flask_mail import Message
from flask import render_template,current_app
from threading import  Thread
from . import mail

def send_async_email(app,msg):
    with app.app_context():
        mail.send(msg)

def send_email(to,subject,template,**kwargs):
    app = current_app._get_current_object()
    msg = Message(app.config['MAIL_SUBJECT_PREFIX']+''+subject,sender=app.config['MAIL_SENDER'],recipients=[to])
    msg.body = render_template(template + '.txt', **kwargs)
    msg.html = render_template(template + '.html', **kwargs)
    thr = Thread(target=send_async_email,args=[app,msg])
    thr.start()
    return thr


import os
import bot_implementation
import discord
from ffz_download import Download

# bot implementation

class Main:
    def __init__(self):
        self.ffz = Download()

    def get_ffz(self):
        self.ffz.get_download_links()
        self.run_bot()

    def run_bot(self):
        # discord bot run
        intents = discord.Intents.default()
        intents.message_content = True
        client = bot_implementation.MyClient(intents=intents)
        #discord bot not defined
        client.run('set_discord_bot')

if __name__ == '__main__':
    # create "mydir" folder in the same directory as main.py if it doesn't exist
    if not os.path.exists("mydir"):
        os.makedirs("mydir")

    run = Main()
    run.get_ffz()


# 问题描述
# 根据以下规则缩写单词：只保留首尾字母，中间缩写以中间部分的字符串长度表示。
# 例如：
# (1) it ---- it(没有缩写)
# (2) d|uc|k ---- d2k(缩去2个字符)
# (3) s|omentim|e ---- s6e(缩去6个字符)
# 假设有一个字典和一个单词，判断这个单词的缩写在字典中是否唯一

# 示例
# 输入：["deer", "door", "cake", "card"]，字典中所有单词的缩写为["d2r","d2r","c2e","c2d"]
# isUnique("dear")输出为False; isUnique("cart")输出为True; isUnique("cane")输出为False;
# isUnique("make")输出为True

# 源码实现
class ValidWordAbbr:
    def __init__(self, dictionary):
        self.map = {}
        for word in dictionary:
            abbr = self.word_to_abbr(word)
            if abbr not in self.map:
                self.map[abbr] = set()
            self.map[abbr].add(word)

    def word_to_abbr(self, word):
        if len(word) <= 1:
            return word
        return word[0] + str(len(word[1:-1])) + word[-1]

    def isUnique(self, word):
        abbr = self.word_to_abbr(word)
        if abbr not in self.map:
            return True
        for word_in_dict in self.map[abbr]:
            if word != word_in_dict:
                return False
        return True

# 主函数
if __name__ == '__main__':
    dic = ["deer", "door", "cake", "card"]
    s = ValidWordAbbr(dic)
    print("输入字典：", dic)
    print("输入单词：dear")
    print("输出：", s.isUnique("dear"))
    print("输入单词：cart")
    print("输出：", s.isUnique("cart"))

# 运行结果
# 输入字典： ['deer', 'door', 'cake', 'card']
# 输入单词：dear
# 输出： False
# 输入单词：cart
# 输出： True

强化提升/例175.单词缩写集.py


import os
from urllib.request import urlretrieve

import pandas as pd

URL = "https://data.seattle.gov/api/views/65db-xm6k/rows.csv?accessType=DOWNLOAD"

def get_fremont_data (filename = 'Fremont.csv', url = URL, force_download = False):
    '''Download and cache the fremont data
    Parameters
    __________
    filename : string (optional)
        location to save the data
    url: string (optional)
        webloc of data
    force_download: bool (optional)
        if True, force the download

    Returns
    ---------
    data: pandas.DataFrame
        Fremont data in dataframe
    '''
    if force_download or not os.path.exists(filename):
        urlretrieve(url, filename)

    data = pd.read_csv("Fremont.csv", index_col = 'Date')
    try:
        data.index = pd.to_datetime(data.index, format = "%m/%d/%Y %H:%M:%S %p")
    except TypeError:
        data.index = pd.to_datetime(data.index)

    data.columns = ['West', 'East']
    data['Total'] = data['West'] + data['East']
    return data


"""
n=int(input())
l=list(map(int,input().split()))
c=1
a=l[0]
for i in l:
    if i==a:
        a-=1
    else:
        c+=1
        a=i-1
print(c)
"""
n=int(input())
l=list(map(int,input().split()))
c=1
a=l[0]
l.remove(a)
while True:
    if len(l)==0:
        break
    else:
        if a-1 in l:
            l.remove(a-1)
            a-=1
        else:
            c+=1
            a=l[0]
            l.remove(a)
print(c)


#!/usr/bin/python3.5
import socket
#创建一个socket：
s = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
#绑定端口
#SOCK_DGRAM指定端口类型是UDP，绑定端口和tcp一样，但不需要listen()
#直接接收来自任何客户端的数据:
s.bind(('127.0.0.1',9999))
print('Bind UDP on 9999...')
while True:
	#接收数据:
	data,addr = s.recvfrom(2014)
	#recvfrom()方法返回数据和客户端的地址与端口
	#服务器收到数据后 直接调用sendto()就可以把数据发送给客户端
	print('Received from %s:%s.' % addr)
	#s.sendto(b'Hello,%s' % data ,addr)
	reply = 'Hello,%s!' % data.decode('utf-8')
	s.sendto(reply.encode('utf-8'),addr)