#Write a function called find_median. find_median
#should take as input a string representing a filename.
#The file corresponding to that filename will be a list
#of integers, one integer per line. find_median should
#return the median of the numbers in the file.
#
#If there is an odd number of values in the file, then
#find_median will return the middle value from the numbers
#in the file after they're sorted.
#
#If there is an even number of values in the file, then
#find_median should return the average of the two middle
#values after they're sorted.
#
#For example, in the dropdown in the top left you'll find a
#file named FindMedianInput.txt. There are 19 numbers in
#this file, so the median is the value at index 10 after
#sorting them: 16.
#
#You may assume that all lines in the file will contain a
#positive integer (greater than 0). There may be duplicates.

#Write your function here!

import os

def find_median( file ):

# Allows access to the file (was having issues opening file even thought it
# was in the same folder)
    THIS_FOLDER = os.path.dirname(os.path.abspath(__file__ ))
    my_file = os.path.join(THIS_FOLDER, file )

# reads the file contents
    input_list = []
    inputFile = open( my_file , 'r' )
    # inputFile = open( file , 'r' )

# Creates list from file contents
    for i in inputFile:
        input_list.append(i)

# Replaces carriage return from list & sorts
    final_list = [x.replace('\n', '') for x in input_list]

    final_list = list(map(int,final_list))
    final_list.sort()

# Calculates the halfway point and rounds down if float
    half = int(len(final_list) / 2)

# Tests if list item is even
    if len(final_list) % 2 == 0:

# If length is even, average the 2 center numbers
        median_a = final_list[half]
        median_b = final_list[half - 1]

# Finds the average and returns the integer (removes floating point)
        avg = (median_a + median_b) / 2
        # avg = int(avg)
        return avg

    else:

# If length of the list is odd, return the center number
        return final_list[half]

#Below are some lines of code that will test your function.
#You can change the value of the variable(s) to test your
#function with different inputs.
#
#If your function works correctly, this will originally
#print: 16 42 53.0 25.0
print(find_median("FindMedianInput.txt"))
print(find_median("FindMedianInput1.txt"))
print(find_median("FindMedianInput2.txt"))
print(find_median("FindMedianInput3.txt"))


from sourpea.primitives import *
from sourpea.util import *
import pandas as pd
import os
_dir=os.path.dirname(__file__)
### REGULAR FACTORS
Ak6TKQz1wz=Factor('aFFrDTJF~',["NCeyfqWILr5RzI",Level("YH%njwHgJe",5),'pPr08Ddvqy','DM?fq Bzq',"DpD|IK Boe"])
UjhTMAufZVB=Factor("KJgiTHr7lW",['}LY',Level('chk>mOUZsDPlO',3),Level(']~@FmCBJsA',8),Level('RUDwvZ?',8),'AQ}RRYJf2)<Uje'])

### EXPERIMENT
design=[Ak6TKQz1wz,UjhTMAufZVB]
crossing=[Ak6TKQz1wz,UjhTMAufZVB]
### APPENDIX
block=Block(design,crossing,[])
sequence_code_1=trials_from_csv(os.path.join(_dir, "out_code_1/5_2_0_0.csv"))
nr_factors=2
nr_levels=5
test_code_1=block.test(sequence_code_1)
try:
	sequence_code_2=trials_from_csv(os.path.join(_dir, "out_code_2/5_2_0_0.csv"))
	test_code_2=block.test(sequence_code_2)
except:
	test_code_2={"pValue":0}
df=pd.read_csv(os.path.join(_dir, "result_sour.csv"))
df.loc[len(df.index)] = [test_code_1["pValue"], test_code_2["pValue"], nr_factors, nr_levels]
df.to_csv(os.path.join(_dir, "result_sour.csv"), index=False)


from collections import deque

class Solution:
    def removeStars(self, s: str) -> str:
        res = deque()
        skip = 0

        for i in range(len(s) - 1, -1, -1):
            char = s[i]

            if char == "*":
                skip += 1
            elif skip > 0:
                skip -= 1
            else:
                res.appendleft(char)

        return "".join(res)


"""Miscellaneous file utility functions."""

import logging
import os
import errno

LOGGER = logging.getLogger(__name__)

def create_file(path):
    """
    Check if a file exists.

    If it does not, creates an empty file with the given path. Will create directories that don't
    exist in the path.

    :param path: The path to create.
    :raises OSError: This shouldn't happen, but unexpected OSErrors will get raised (we catch
        EEXist already).
    :returns: ``None``.
    """
    LOGGER.debug('Creating new file: {}'.format(path))
    if not os.path.exists(path):
        # Make directory
        try:
            os.makedirs(os.path.dirname(path))
        except OSError as err:
            if err.errno == errno.EEXIST:
                msg = ('Directory already created, or race condition? Check '
                       'path: {}'.format(path))
                LOGGER.error(msg)
            else:
                msg = 'Unexpected OSError: {}'.format(err)
                LOGGER.error(msg)
                raise OSError(msg)
        # Make file
        with open(path, 'a+') as f:
            f.close()


import bpy
from mathutils import Vector, Matrix
import math
import time
import os
import json

bpy.context.user_preferences.view.show_splash = False # don't show splash

_cg = None
_is_hipoly = None

_args = json.loads(os.getenv("BCG_ARGS"))

def v2normal(v):
	return (v[1], -v[0])

def vadd(v0,v1):
	r = []
	for i in range(len(v0)):
		r.append(v0[i]+v1[i])
	return r

def vsub(v0,v1):
	r = []
	for i in range(len(v0)):
		r.append(v0[i]-v1[i])
	return r

def vdot(v0,v1):
	z = 0
	for i in range(len(v0)):
		z += v0[i]*v1[i]
	return z

def _isincos(x, n):
	x = int(x)
	n = int(n)
	x4 = x*4
	if (x4 % n) == 0:
		isin = lambda i: [0,1,0,-1][i%4]
		icos = lambda i: isin(i+1)
		idx = int(x4/n)
		return (isin(idx), icos(idx))
	else:
		phi = (x/float(n)) * 2.0 * math.pi
		return (math.sin(phi), math.cos(phi))

class _Timer(object):
	def __init__(self, msg):
		self.msg = msg

	def __enter__(self):
		self.t0 = time.time()

	def __exit__(self,a,b,c):
		dt = time.time() - self.t0
		print("%s (took %.2f s)" % (self.msg, dt))

def _join(objs = []):
	nobjs = []
	for obj in objs:
		if obj is None:
			continue
		elif len(obj.data.vertices) == 0:
			bpy.data.objects.remove(obj)
		else:
			nobjs.append(obj)
	objs = nobjs

	if len(objs) == 0:
		mesh = bpy.data.meshes.new(name="join")
		mesh.from_pydata([], [], [])
		obj = bpy.data.objects.new("dummy", mesh)
		bpy.context.scene.objects.link(obj)
		return obj
	if len(objs) == 1:
		return objs[0]
	ctx = bpy.context.copy()
	ctx['active_object'] = objs[0]
	ctx['selected_objects'] = objs
	ctx['selected_editable_bases'] = [bpy.context.scene.object_bases[obj.name] for obj in objs]
	bpy.ops.object.join(ctx)
	return objs[0]

def _dupe(src_obj, name = None):
	dst_obj = src_obj.copy()
	dst_obj.data = src_obj.data.copy()
	if name is not None: dst_obj.name = name
	bpy.context.scene.objects.link(dst_obj)
	return dst_obj

class _CG(object):
	def __init__(self, name):
		self.name = name
		self.optree = []
		self.stack = [self.optree]

	def enter(self, o):
		children = []
		self.stack[-1].append((o, children))
		self.stack.append(children)

	def exit(self):
		self.stack.pop()
		assert len(self.stack) >= 1

	def emit(self, o):
		self.stack[-1].append(o)

	def construct(self, debug = False):
		def crec(ns):
			objs = []
			debug_objs = []
			for n in ns:
				if type(n) is tuple:
					robjs, rdebug_objs = crec(n[1])
					obj = n[0].render(robjs)
					objs.append(obj)
					debug_objs += [n[0].debug_render(o) for o in rdebug_objs]
					if isinstance(n[0], Debug):
						dname = self.name + ".Debug"
						if n[0].tag is not None:
							dname += "." + n[0].tag
						debug_objs.append(_dupe(obj, name = dname))
				else:
					objs.append(n.render())
			return (objs, debug_objs)
		objs, debug_objs = crec(self.optree)
		obj = _join(objs)
		obj.name = self.name
		#obj.color = [1,0,0,0.2] # TODO useful for debugging, but requires an "object color material"
		return obj

	def dump(self):
		def drec(ns, depth = 0):
			for n in ns:
				name = None
				if type(n) is tuple:
					name = n[0].name
				else:
					name = n.name
				print(". " * depth + name)
				if type(n) is tuple:
					drec(n[1], depth+1)
		drec(self.optree)

class _Pair(object):
	def __init__(self, a, b):
		self.a = a
		self.b = b

	def __enter__(self):
		global _cg
		self.a.__enter__()
		self.b.__enter__()

	def __exit__(self,a,b,c):
		global _cg
		self.b.__exit__(None,None,None)
		self.a.__exit__(None,None,None)

	def __add__(self, other):
		return _Pair(self, other)

class _Group(object):
	def __enter__(self):
		global _cg
		assert _cg is not None
		_cg.enter(self)

	def __exit__(self,a,b,c):
		global _cg
		_cg.exit()

	def __add__(self, other):
		return _Pair(self, other)

	def render(self, args):
		return _join(args)

	def debug_render(self, obj):
		return obj

class _Transform(_Group):
	def render(self, args):
		for obj in args:
			obj.matrix_world = self._tx * obj.matrix_world
		return _join(args)

	def debug_render(self, obj):
		return self.render([obj])

class _Boolean(_Group):
	# solver can be 'CARVE' or 'BMESH'
	def __init__(self, solver='CARVE'):
		self.solver = solver

	def render(self, args):
		if len(args) <= 1: return _join(args)
		a = args[0]
		b = _join(args[1:])
		bop = a.modifiers.new(type="BOOLEAN", name="bool")
		bop.object = b
		bop.operation = self._op
		bop.solver = self.solver
		bpy.context.scene.objects.active = a
		bpy.ops.object.modifier_apply(apply_as='DATA', modifier='bool')
		bpy.data.objects.remove(b)
		return a

class Group(_Group):
	pass

class Debug(_Group):
	def __init__(self, tag=None):
		self.tag = tag

class Translate(_Transform):
	def __init__(self, x=0, y=0, z=0):
		self.tv = Vector((x,y,z))
		self.name = "Translate(%f,%f,%f)" % (x,y,z)
		self._tx = Matrix.Translation(self.tv)

class Rotate(_Transform):
	def __init__(self, deg=0, axis="Z", rad=None):
		if isinstance(axis, tuple) or isinstance(axis, list):
			axis = Vector(axis)
		self.axis = axis
		if rad is not None:
			self.rad = rad
		elif (deg%90) == 0 and axis in ["X","Y","Z"]:
			s, c = _isincos(deg, 360)
			if axis == "X":
				self._tx = Matrix((
					(  1,  0,  0,  0),
					(  0,  c, -s,  0),
					(  0,  s,  c,  0),
					(  0,  0,  0,  1)
				))
			elif axis == "Y":
				self._tx = Matrix((
					(  c,  0,  s,  0),
					(  0,  1,  0,  0),
					( -s,  0,  c,  0),
					(  0,  0,  0,  1)
				))
			elif axis == "Z":
				self._tx = Matrix((
					(  c, -s,  0,  0),
					(  s,  c,  0,  0),
					(  0,  0,  1,  0),
					(  0,  0,  0,  1)
				))
			else:
				raise RuntimeError("unexpected axis value %s" % axis)
			self.rad = (deg/180.0) * math.pi
		else:
			self.rad = (deg/180.0) * math.pi
			self._tx = Matrix.Rotation(self.rad, 4, self.axis)

		self.name = "Rotate(rad=%f,axis=%s)" % (self.rad, axis)

class Union(_Boolean):
	_op = "UNION"
	name = "Union"

class Difference(_Boolean):
	_op = "DIFFERENCE"
	name = "Difference"

class Intersection(_Boolean):
	_op = "INTERSECT"
	name = "Intersection"

class Hull(_Group):
	name = "Hull"
	def render(self, args):
		obj = _join(args)
		bpy.context.scene.objects.active = obj
		bpy.ops.object.mode_set(mode = 'EDIT')
		bpy.ops.mesh.convex_hull()
		bpy.ops.object.mode_set(mode = 'OBJECT')
		return obj

# TODO .. at least convex minkowski sum should be easy... non-convex requires
# decomposition into convex sub-polyhedra and then pairwise doing convex
# minkowski sum on them
"""
class Minkowski(_Group):
	pass
"""

# TODO smoothing
class polyhedron(object):
	def __init__(self, vertices, faces, name="tmp"):
		self.vertices = vertices
		self.faces = faces
		self.name = name
		global _cg
		_cg.emit(self)
	def render(self):
		mesh = bpy.data.meshes.new(name=self.name)
		mesh.from_pydata(self.vertices, [], self.faces)
		obj = bpy.data.objects.new(self.name, mesh)
		bpy.context.scene.objects.link(obj)
		return obj

def cube(sx=1.0, sy=1.0, sz=1.0, center=False):
	dx=0.0;dy=0.0;dz=0.0
	if center:
		dx=-sx/2.0
		dy=-sy/2.0
		dz=-sz/2.0

	vertices = []
	for z in range(2):
		for y in range(2):
			for x in range(2):
				vertices.append((
					x*sx+dx,
					y*sy+dy,
					z*sz+dz))
	# vertices are now indexed by an xyz bit pattern e.g. for x+y-z- it's
	# 001 (1), and x-y+z+ is 110 (6), etc

	faces = []
	for normal_axis in range(3):
		for sign in [0,1]:
			# face normals must always point away from the cube
			# center. and blender is right handed, so...
			#     finger0 x finger1 = finger2
			# meaning if finger0 and finger1 are edges in a
			# polygon, then its winding must be clockwise when seen
			# from front
			#   x+: y+z- -> y-z- -> y-z+ -> y+z+
			#   y+: z+x- -> z-x- -> z-x+ -> z+x+
			#   z+: x+y- -> x-y- -> x-y+ -> x+y+ -> ...
			# so the pattern is:
			#   00110011001100110 for (axis+1)%3
			#   01100110011001100 for (axis+2)%3
			# played from left to right for normal-positive faces
			# and from right to left for normal-negative faces
			# so:
			faces.append([
				  (sign << normal_axis)
				+ ((((i+sign*2) >> 1) & 1) << ((normal_axis+1)%3))
				+ ((((i+1)      >> 1) & 1) << ((normal_axis+2)%3))
				for i in range(4)
			])
	polyhedron(vertices, faces, name="cube")

# segments is an array of (r,z) pairs (radius,z-position)
# if loop is True, the last segment will be connected to the first segment
# decompose_index can be used to extract
def cylinder_segments(segments, loop=False, fn=32):
	assert(len(segments)>=2)

	vertices = []
	seginfo = []
	for r,z in segments:
		seginfo.append((len(vertices), r==0))
		if r != 0:
			for i in range(fn):
				s, c = _isincos(i, fn)
				x = r * c
				y = r * s
				vertices.append((x,y,z))
		else:
			vertices.append((0,0,z))

	faces = []
	n = len(segments)
	ns = n-1
	if loop: ns += 1
	for i0 in range(ns):
		i0 = i0%n
		i1 = (i0+1)%n
		s0offset, s0singular = seginfo[i0]
		s1offset, s1singular = seginfo[i1]
		if s0singular and s1singular: continue # segment would be a line; don't render it

		for j in range(fn):
			j0 = j % fn
			j1 = (j0+1) % fn
			face = []
			if s0singular:
				face.append(s0offset)
			else:
				face.append(s0offset + j0)
				face.append(s0offset + j1)
			if s1singular:
				face.append(s1offset)
			else:
				face.append(s1offset + j1)
				face.append(s1offset + j0)
			faces.append(face)

	if not loop:
		if not seginfo[0][1]: faces.append([i + seginfo[0][0] for i in range(fn-1,-1,-1)])
		if not seginfo[-1][1]: faces.append([i + seginfo[-1][0] for i in range(fn)])

	polyhedron(vertices, faces, name="cylinder_segments")

def n_hull(v,ctor):
	sz = len(v)
	n = 2**sz
	with Hull():
		for i in range(n):
			dx = 0
			dy = 0
			dz = 0
			if i&1: dx = v[0]
			if i&2: dy = v[1]
			if i&4: dz = v[2]
			with Translate(dx,dy,dz):
				ctor()

def square_hull(sx,sy,ctor):
	n_hull((sx,sy),ctor)

def cube_hull(sx,sy,sz,ctor):
	n_hull((sx,sy,sz),ctor)

# decomposes into convex cylinder segments (useful e.g. if you want a convex
# hull of each convex group)
def decompose_cylinder_segments(segments, epsilon=1.0/16.0):
	groups = []
	group = []
	prev_point = None
	prev_vec = None
	for r,z in segments:
		point = (r,z)
		if prev_point is not None:
			vec = vsub(point, prev_point)
			dr,dz = vec
			veps = (0,epsilon)
			if dz < 0:
				raise RuntimeError("dz must be zero or positive")
			elif dz == 0:
				if len(group) >= 2:
					group.append(vadd(point,veps))
					groups.append(group)
					group = []
				else:
					group = []
			elif prev_vec is not None:
				cross = vdot(v2normal(vec), prev_vec)
				if cross < 0:
					if dr >= 0:
						group += [vadd(prev_point,veps)]
						groups.append(group)
						group = [prev_point]
					else:
						groups.append(group)
						group = [vsub(prev_point,veps),prev_point]
				prev_cross = cross

			prev_vec = vec
		group.append(point)
		prev_point = (r,z)
	if len(group) > 0: groups.append(group)

	return groups

def sphere(r=1.0, fs=20, fn=32):
	segments = []
	for i in range(fs+1):
		if i == 0:
			segments.append((0,-r))
		elif i == fs:
			segments.append((0,r))
		else:
			s, c = _isincos(i, fs*2)
			z = r * -c
			rs = r * s
			segments.append((rs,z))
	cylinder_segments(segments=segments, fn=fn)

def cylinder(r1=1.0, r2=1.0, h=1.0, fn=32, r=None):
	if r is not None:
		r1 = r
		r2 = r
	cylinder_segments(segments = [(r1,0), (r2,h)], fn=fn)

def torus(r1=1.0, r2=0.2, fs=20, fn=32):
	segments = []
	for i in range(fs):
		s, c = _isincos(i, fs)
		z = r2 * s
		rs = r1 + r2 * c
		segments.append((rs,z))
	cylinder_segments(segments=segments, loop=True, fn=fn)

# returns True if this is a high polygon pass, otherwise False
def hipoly():
	global _is_hipoly
	assert _is_hipoly is not None
	return _is_hipoly

# returns hipoly_val if hipoly() is True, otherwise lopoly_val
def if_hipoly(hipoly_val, lopoly_val):
	if hipoly():
		return hipoly_val
	else:
		return lopoly_val

# cg: constructive geometry pass: typically called twice for low/high poly; see hipoly()
# prep: mesh preparation; do culling/seaming here
# paint: texture painting...
# instance: (optional) object instancing
# godot_export: material setup, resource binding, etc (TODO there should also
#               be a global export for doing the final preparation stuff...)
def mkobj(name, cg=None, prep=None, paint=None, instance=None, godot_export=None):
	assert(cg is not None)
	global _cg

	# TODO quick preview for either of these? i.e. only render one of them
	passes = [(False, name+".Lo")]
	if "preview" not in _args:
		passes += [(True, name+".Hi")]

	for hi, pname in passes:
		global _is_hipoly
		_is_hipoly = hi
		with _Timer("PASS cg for %s" % pname):
			_cg = _CG(pname)
			cg()
			obj = _cg.construct()
			if len(obj.data.vertices) == 0:
				bpy.data.objects.remove(obj)

		_cg = None
		_is_hipoly = None

def clear():
	for bo in bpy.data.objects:
		bpy.data.objects.remove(bo)

def save_blend(name):
	bpy.ops.wm.save_as_mainfile(filepath = "%s.blend" % name)


from apscheduler.schedulers.background import BackgroundScheduler
from core.models import RegisteredAssets
from core.utils import update_asset_price

def start():
    scheduler = BackgroundScheduler()

    for asset in RegisteredAssets.objects.all():

        scheduler.add_job(update_asset_price, 'interval', days=asset.frequency, args=[asset])

    scheduler.start()

def create(asset):
    scheduler = BackgroundScheduler()
    scheduler.add_job(update_asset_price, 'interval', days=asset.frequency, args=[asset])
    scheduler.start()


"""
@ART 基础数据数据结构
"""
from uuid import uuid1
from dataclasses import dataclass, field
from typing import *
from shapely.geometry import Point, LineString, Polygon

from treelib import Tree, Node

class GlobalTree:

    def __init__(self, tree=None, data_objects=None):
        self.tree = tree
        self.data_objects = data_objects

    # # 添加object
    # def add_object(self, one_object: DataObject, level):
    #     if self.tree.depth > 1:
    #         pass
    #
    # # 删除object
    # def delete_object(self, object_index: int):
    #     if tree.contains(object_index):
    #         tree.remove_node(object_index)
    #
    #
    # def insert_object(self, object_index: int, position):
    #
    #
    # def replace_object(self, one_object: DataObject, position):
    #
    #
    # def move_object_to_another_tree_position(self, position):

@dataclass(order=True, unsafe_hash=True)
class DataElement:
    """
    数据结构中最小的图形和语义信息储存类
    结构特征：用于存储每一个最基本的geometry对象（点/线/几何形状）；其中包含语义属性及几何属性；不存在任何嵌套与包含关系
    """
    # 几何属性
    geometry: Union[Point, LineString, Polygon] = field(default=None)
    shadow: Polygon = field(default=None)  # 几何物件对应的阴影, 仅包括geometry_realistic_state为True的Polygon

    # 语义属性
    id: str = field(default_factory=uuid1)     # 物件ID
    type: str = field(default="")             # 图层名
    group_list: tuple = field(default=None)  # 编组信息
    has_shadow: bool = field(default=False)    # 几何对象是否有阴影

@dataclass(order=True, unsafe_hash=True)
class DataObject:
    """
    物件类，逻辑结构
    结构特征：1.用于存储dxf文件中的一个Group单元；
            2.可以由ObjectElement组成，可以由DataObject组成，也可以两者共同组成
    """
    # 几何属性
    elements: List = field(default_factory=list)  # 所有dataElements

    # 语义属性
    id: str = field(default_factory=uuid1)  # 物件ID
    index: int = field(default=0)  # 組索引
    name: str = field(default=None)  # 编组名字
    global_tree: GlobalTree = field(default_factory=GlobalTree) # 全局树
    # tree: Tree = field(default_factory=Tree) # 关系树
    floor: int = field(default=0)  # 层数
    height: float = field(default=0.0)  # 高度
    annotations: str = field(default=None)  # 所有文字标注

    # 基准渲染层级
    zorder: int = field(default=0)

    @property
    def tree(self):
        if self.global_tree.tree.depth() > 1 and self.index in self.global_tree.tree.nodes:
            return self.global_tree.tree.subtree(self.index)
        else:
            return None

    # 所有DataElement
    def all_elements(self) -> List[DataElement]:
        elements = []
        object_indexes = self.tree.all_nodes()
        for index in object_indexes:
            elements.extend(self.global_tree.data_objects[index].elements)
        return elements

    # 所有DataObject
    def all_objects(self) -> List[DataElement]:
        objects = []
        object_indexes = self.tree.all_nodes()
        for index in object_indexes:
            objects.extend(self.global_tree.data_objects[index])
        return objects

    # 添加element
    def add_element(self, element: DataElement):
        if isinstance(element, DataElement) and element.geometry is not None:
            self.elements.append(element)
        else:
            raise Exception("物件中没有输入的元素ID")

    # 删除element
    def delete_element(self, element_id: str):
        if element_id in [item.id for item in self.elements]:
            index = max(self.elements, key=lambda x: x.id == element_id)
            self.elements.pop(index)
        else:
            raise Exception("物件中没有输入的元素ID")

def assemble_tree(data_elements:List[DataElement], data_objects:dict):
    """
    用于组装data_objects的关系树，传入是目前已有的element元素以及obj字典
    :param data_elements:
    :param data_objects:
    :return:
    """
    group_info = [each.group_list for each in data_elements]
    group_info = list(set(filter(lambda each: len(each)>0, group_info)))

    # 先构造一个全局的树，包含所有的树结构和层级
    global_tree = Tree() # 全局树
    global_tree.create_node("global_tree", "root")
    # 组装树
    for each in group_info:
        cur_order = list(each)
        cur_order.reverse()
        for i in range(len(cur_order)):
            all_node_tag = [node.tag for node in global_tree.all_nodes()]
            if i == 0 and cur_order[i] not in all_node_tag:
                global_tree.create_node(cur_order[i],cur_order[i],parent="root")
            elif i!=0 and cur_order[i] not in all_node_tag:
                global_tree.create_node(cur_order[i],cur_order[i],parent=cur_order[i-1])
    # 创建一个全局树，并把所有的对应的data object放进去
    cur_global_tree = GlobalTree(tree=global_tree, data_objects=data_objects)

    # 遍历全部data_objects对象，把全局树先放进去
    for each in data_objects.values():
        each.global_tree=cur_global_tree


#!bin/python3

n = int(input())
a = list(map(int, input().split(' ')))
i = n-1
temp = a[i]
while i != 0 and a[i] < a[i-1]:
    a[i] = a[i-1]
    print(' '.join(map(str, a)))
    a[i-1] = temp
    i -= 1
else:
    a[i] = temp
    print(' '.join(map(str, a)))


from math import ceil

def TextboxCount(lines): #this function takes as input a list of lines, and returns the numbers of characters and lines of the textbox
    n = [] #character count for each line
    l = len(lines) #number of lines
    for x in lines:
        n.append(len(x)-1) #is off by 1 for every line due to counting the line break
    return n, l;

def TextboxLengthNonJP(lines): #function takes lines as input and times how long the textbox will last
    n, l = TextboxCount(lines)
    if l == 0:
        return 0
    elif l == 1: #the length is max between time it takes for the blue line to appear and time it takes for all the characters to appear
        chara_time = 1 + 2*4 + 3 + (n[0]-5)*2 #1 QF for 1st and 2nd, 4QFs for 3rd and 4th, 3 QFs for 5th, 2 for the remaining characters in the line
        band_time_togo = 28 #ceil(1.109/.04)
        time = max(chara_time, band_time_togo)
    elif l == 2:
        chara_time_body = 1 + 2*4 + 3 + (n[0]-5)*2 #time for charas on the 1st line
        chara_time_tail = 1 + (n[1]-2)*2 #time for the charas on the 2nd line to appear
        band_timer = 2-((chara_time_body-1) * 0.04) #band timer that does not account for the >= 1 requirement
        remaining_band_timer = max(1.0, band_timer) #what the band timer is at on the QF it is allowed to go below 1
        band_time_togo = ceil((remaining_band_timer+0.109)/0.04) #time for the blue band to finish appearing
        time = chara_time_body + max(chara_time_tail, band_time_togo)
    else:
        chara_time_body = 1 + 2*4 + 3 + 1 + (n[0]+n[1]-7)*2
        chara_time_tail = 1 + (n[2]-2)*2
        band_timer = 3-((chara_time_body-1) * 0.04)
        remaining_band_timer = max(1.0, band_timer)
        band_time_togo = ceil((remaining_band_timer+0.109)/0.04)
        time = chara_time_body + max(chara_time_tail, band_time_togo)
    #time += 1.5 #avg timeloss from potentially starting on any QF
    return time

def TextboxLengthJP(lines): #function takes lines as input and times how long the textbox will last
    n, l = TextboxCount(lines)
    if l == 0:
        return 0
    elif l == 1: #the length is max between time it takes for the blue line to appear and time it takes for all the characters to appear
        chara_time = 1 + 10 + 8 + 4 + (n[0]-4)*3 #1 QF for 1st, 10QFs for 2nd, 8QF for 3rd, 4 QFs for 4th, 3 for the remaining characters in the line
        band_time_togo = 28 #ceil(1.109/.04)
        time = max(chara_time, band_time_togo)
    elif l == 2:
        chara_time_body = 1 + 10 + 8 + 4 + (n[0]-4)*3 #time for charas on the 1st line
        chara_time_tail = 1 + (n[1]-2)*3 #time for the charas on the 2nd line to appear
        band_timer = 2-((chara_time_body-1) * 0.04) #band timer that does not account for the >= 1 requirement
        remaining_band_timer = max(1.0, band_timer) #what the band timer is at on the QF it is allowed to go below 1
        band_time_togo = ceil((remaining_band_timer+0.109)/0.04) #time for the blue band to finish appearing
        time = chara_time_body + max(chara_time_tail, band_time_togo)
    else:
        chara_time_body = 1 + 10 + 8 + 4 + 1 + (n[0]+n[1]-6)*3
        chara_time_tail = 1 + (n[2]-2)*3
        band_timer = 3-((chara_time_body-1) * 0.04)
        remaining_band_timer = max(1.0, band_timer)
        band_time_togo = ceil((remaining_band_timer+0.109)/0.04)
        time = chara_time_body + max(chara_time_tail, band_time_togo)
    #time += 1.5 #avg timeloss from potentially starting on any QF
    return time

def LanguageTime(contents, isJP):
    total_time = 0
    tag_times = {}
    box_times = {}
    curr_lines = [] #represents the textbox currently being read
    for line in contents: #iterate through all the lines
        if line.startswith("/"):    #test if we are in a textbox or at the end of one
            #we are on a / so at the end of 1 textbox and at the start of the next.
            #we add the time spent on the box and move empty the current working lines
            tag_end = line.find(":")
            if tag_end == -1:
                tag_end = len(line) # if line doesn't have a tag delimiter just assume the whole annotation is the tag
            tag = line[2:tag_end]

            # time the textbox using the appropriate language mechanics
            if isJP:
                box_time = TextboxLengthJP(curr_lines)
            else:
                box_time = TextboxLengthNonJP(curr_lines)

            # update our various timing data
            if tag in tag_times:
                tag_times[tag] += box_time
            else:
                tag_times[tag] = box_time
            box_times[line[2:]] = box_time
            total_time += box_time
            curr_lines = []
        else:
            curr_lines.append(line)  #we are in the middle of a textbox so we add the line to the working set of lines
    return total_time, tag_times, box_times

# f = open("FormattedJapanese.txt","r")
# contentsJ = f.readlines()
# totalJ, tagJ, boxJ = LanguageTime(contentsJ, True)
# print(totalJ)
# f = open("AnnotatedJapanese.txt","r")
# contentsJ = f.readlines()
# totalJ, tagJ, boxJ = LanguageTime(contentsJ, True)
# print(totalJ)
# f = open("AnnotatedEnglish.txt","r")
# contentsE = f.readlines()
# totalE, tagE, boxE = LanguageTime(contentsE, False)
# print(totalE)
# jsum = 0
# esum = 0
# for tag in boxJ:
#     if tag.startswith('noki3'):
#         print(tag, boxJ[tag])
#     pass


import requests
from time import localtime, strftime
import copy
from operator import itemgetter

#########  PARAMETERS #########

# Default values
IATA_departure = 'SXF'  # Flight departure location, IATA code
IATA_arrival = ''       # Flight arrival location, IATA code (optional)
Language = 'pl'         # Language in which airport names are displayed
Limit = '100'           # Maximum number of displayed flights
Offset = '0'            # ? No idea, no official API documentation
Flex_in = '0'           # The number of extra days to include with DateIn
Flex_out = '0'          # The number of extra days to include with DateOut
Price_value = '200'     # Maximum prize for a one-way or two-way ticket
dep_out_date_from = '2018-04-28' # Earliest departure date of an outbound flight
dep_out_date_to = '2018-05-03'   # Latest departure date of an outbound flight
dep_in_date_from ='2018-05-11'   # Earliest departure date of an inbound flight
dep_in_date_to = '2018-05-30'    # Latest departure date of an inbound flight

def change_parameters():
    ''' User defines other parameters than default ones.
    Variables must be defined as global, until the code will not be
    rewritten with classes.
    '''

    global dep_out_date_from
    global dep_out_date_to
    global dep_in_date_from
    global dep_in_date_to
    global IATA_departure
    global IATA_arrival
    global Price_value

    choice = None
    while choice != "0":
        print \
        ("""
        --------------- Changing flight search details ---------------

        0 - Back to the main menu
        1 - Change: Earliest departure date of an outbound flight
        2 - Change: Latest departure date of an outbound flight
        3 - Change: Earliest departure date of an inbound flight
        4 - Change: Latest departure date of an inbound flight
        5 - Change: Flight departure location
        6 - Change: Flight arrival location
        7 - Change: Maximum price for one-way or two-way ticket

        """)

        choice = input("Choose: ")
        print()

        if choice == "0":
            print("Back to the main menu")
        elif choice == "1":
            dep_out_date_from = input("Earliest departure date of an outbound flight (YYYY-MM-DD): ")
        elif choice == "2":
            dep_out_date_to = input("Latest departure date of an outbound flight (YYYY-MM-DD): ")
        elif choice == "3":
            dep_in_date_from = input("Earliest departure date of an inbound flight (YYYY-MM-DD): ")
        elif choice == "4":
            dep_in_date_to = input("Latest departure date of an inbound flight (YYYY-MM-DD): ")
        elif choice == "5":
            IATA_departure = input("Flight departure location, three-letter IATA airport code: ")
        elif choice == "6":
        	iata = input('Do you want to change destination (press 1) or erase it completely, so that many locations are searched? (press 2): ')
        	if iata == "1":
        		IATA_arrival = input("Flight arrival location, three-letter IATA airport code: ")
        	if iata == "2":
        		IATA_arrival=''
        		print('/nArrival location erased!')
        elif choice == "7":
        	Price_value = input("Maximum price for one-way or two-way ticket (in departure location currency): ")
        else:
            print(" !!!!!!!!! Wrong option !!!!!!!!! ")

def show_parameters():
    ''' Displaying current parameters values'''

    print("Earliest departure date of an outbound flight: " + str(dep_out_date_from) + '\n')
    print("Latest departure date of an outbound flight: " + str(dep_out_date_to) + '\n')
    print("Earliest departure date of an inbound flight: " + str(dep_in_date_from) + '\n')
    print("Latest departure date of an inbound flight: " + str(dep_in_date_to) + '\n')
    print("Maximum price for a one-way or two-way ticket (in departure location currency): " + str(Price_value) + '\n')
    print("Departure from: " + str(IATA_departure) + '\n')
    if IATA_arrival:
        print("Arrival in: " + str(IATA_arrival ) + '\n')
    else:
    	print("Arrival in: not specified")

def get_url(ways):
    '''Creating an URL to query Ryanair website'''

    if ways ==1:
        if IATA_arrival:
            return 'https://api.ryanair.com/farefinder/3/oneWayFares?'  + \
            '&arrivalAirportIataCode=' + IATA_arrival + \
            '&departureAirportIataCode=' + IATA_departure + \
            '&language=' + Language +   '&limit=' + Limit + '&FlexDaysIn=' + \
            Flex_in + '&FlexDaysOut=' + Flex_out +'&market=' + Language + '-' + \
            Language + '&offset=' + Offset + '&outboundDepartureDateFrom=' + \
            dep_out_date_from + '&outboundDepartureDateTo=' + \
            dep_out_date_to + '&priceValueTo=' + Price_value
        else:
            return 'https://api.ryanair.com/farefinder/3/oneWayFares?'  + \
            '&departureAirportIataCode=' + IATA_departure + \
            '&language=' + Language +   '&limit=' + Limit + '&FlexDaysIn=' + \
            Flex_in + '&FlexDaysOut=' + Flex_out +'&market=' + Language + '-' + \
            Language + '&offset=' + Offset + '&outboundDepartureDateFrom=' + \
            dep_out_date_from + '&outboundDepartureDateTo=' + \
            dep_out_date_to + '&priceValueTo=' + Price_value

    if ways == 2:
        if IATA_arrival:
            return 'https://api.ryanair.com/farefinder/3/roundTripFares?' + \
            '&arrivalAirportIataCode=' + IATA_arrival + \
            '&departureAirportIataCode=' + IATA_departure + \
            '&inboundDepartureDateFrom=' + dep_in_date_from + \
            '&inboundDepartureDateTo=' + dep_in_date_to + \
            '&language=' + Language +   '&limit=' + Limit + '&FlexDaysIn=' + \
            Flex_in + '&FlexDaysOut=' + Flex_out +'&market=' + Language + '-' + \
            Language + '&offset=' + Offset + '&outboundDepartureDateFrom=' + \
            dep_out_date_from + '&outboundDepartureDateTo=' + \
            dep_out_date_to + '&priceValueTo=' + Price_value
        else:
            return 'https://api.ryanair.com/farefinder/3/roundTripFares?' + \
            '&departureAirportIataCode=' + IATA_departure + \
            '&inboundDepartureDateFrom=' + dep_in_date_from + \
            '&inboundDepartureDateTo=' + dep_in_date_to + \
            '&language=' + Language +   '&limit=' + Limit + '&FlexDaysIn=' + \
            Flex_in + '&FlexDaysOut=' + Flex_out +'&market=' + Language + '-' + \
            Language + '&offset=' + Offset + '&outboundDepartureDateFrom=' + \
            dep_out_date_from + '&outboundDepartureDateTo=' + \
            dep_out_date_to + '&priceValueTo=' + Price_value

def find_fares(ways):
    '''Getting JSON data containing lowest fares from Ryanair website'''

    # Connecting to Ryanair website
    url = get_url(ways)
    r = requests.get(url)
    if r.ok:
        print("Status code:", r.status_code)
    else:
        print("HTTP %i - %s, Message %s" % (r.status_code, r.reason, r.text))

    # Saving response
    result  = r.json()
    return result['fares']

def get_vals(flight, key, one, two = 0):
    '''Fares is a list of dictionaries that consist of 3 keys: outbound, inbound, summary
    We need to dig deeper inside their values, sub-values and sub-subvalues'''

    temp = []
    if two:
        temp = [v[one][two] for k,v in flight.items() if k == key]
    else:
        temp = [v[one] for k,v in flight.items() if k == key]
    return temp[0]

def clean_results(ways):
    ''' Results from JSON file are in a really ugly form. Let's make it more readable'''

    fares = find_fares(ways)
    flights_clean = []
    lowest_fares = {}

    for flight in fares:
        # Przygotowujemy slownik dla każdego kolejnego lotniska z listy
        lowest_fares['airport'] = get_vals(flight, 'outbound', 'arrivalAirport', 'name')
        lowest_fares['currency'] = get_vals(flight, 'outbound','price', 'currencyCode')
        lowest_fares['date'] =  get_vals(flight, 'outbound','departureDate')[:10]
        if ways == 2: lowest_fares['date_back'] = get_vals(flight,'inbound','departureDate')[:10]
        lowest_fares['price_main'] = int(get_vals(flight, 'summary', 'price', 'valueMainUnit'))
        lowest_fares['price_frac'] = int(get_vals(flight, 'summary', 'price', 'valueFractionalUnit'))
        lowest_fares['price_total'] = lowest_fares['price_main'] + lowest_fares['price_frac']/100
        flights_clean.append(copy.copy(lowest_fares)) # nasza zbiorcza lista wzbogaca sie o kolejny slownik-lotnisko, ALE UWAGA! Musi byc kopia, bo inaczej dane sie nadpisuja

    # itemgetter: sort the list of dictionaries by the price
    return sorted(flights_clean, key=itemgetter('price_main'), reverse=False)

def print_results(ways, flights_clean):
    ''' Printing out to the screen the lowest fares sorted by price '''

    print("\n\n" + IATA_departure, end='')

    if ways == 1:
        print(" - One-way trip: " + str(len(flights_clean)) + " offer(s) \n\n")
    if ways == 2:
        print(" - Two-way trip: " + str(len(flights_clean)) + " offer(s) \n\n")

    for flight in flights_clean:
        print (flight['airport'], end=": " )
        print (str(flight['price_total']) + ' ' + flight['currency'], end='')
        if ways == 1:
            print(" on " + flight['date'], end="\n\n")
        if ways == 2:
            print(" on " + str(flight['date']) + ' - ' + str(flight['date_back']), end="\n\n")

def txt_results(ways, flights_clean):
    ''' Saving the lowest fares to Ryanair.txt file in the current directory '''

    with open("Ryanair.txt", 'a') as f:
        f.write("================================================ \n\n")
        f.write("Script was initialized: ")
        f.write(strftime('%Y-%m-%d %H:%M:%S', localtime()))
        f.write('\n\n')
        f.write("----------------------------------------------- \n\n")
        f.write(IATA_departure)

        if ways == 1:
            f.write('- One-way trip: \n\n')
        if ways == 2:
            f.write('- Two-way trip: \n\n')

        for flight in flights_clean:
            f.write(str(flight['airport']) + ": ")
            f.write(str(flight['price_total']) + ' ')
            f.write(str(flight['currency']) + ' on ')
            if ways == 1:
                f.write(str(flight['date']) + "\n\n")
            if ways == 2:
                f.write(str(flight['date']) + " - ")
                f.write(str(flight['date_back']) + "\n\n")

def n_way(ways):
    ''' Getting clean results for one-way or two-way flights and printing them (to the screen + into txt file) '''

    flights_clean = clean_results(ways)
    print_results(ways, flights_clean)
    # txt_results(ways, flights_clean)
    # send_mail(toaddr="XYZ@gmail.com", subject="Wyszukiwarka lotow Ryanair", body="Patrz: załącznik", att_path="C:\\1. Patryk\\Data science\\Python\\Kody\\Raporty", att_filename="Ryanair.txt")


#!/usr/bin/env python
# -*- coding: utf-8 -*-
import numpy as np
import rospy
# メッセージの型等のimport
from robot_manipulation.msg import pack_current_position
from sensor_msgs.msg import Image
from cv_bridge import CvBridge
from robot_manipulation import video_capture
import cv2 as cv
import numpy as np
from robot_manipulation import CameraCalibration
from time import sleep

class Publishers():
    def __init__(self):
        # Publisherを作成
        self.pub = rospy.Publisher('/pack_cur_pos', pack_current_position, queue_size=1)
        # messageの型を作成
        self.msg = pack_current_position()

    def make_msg(self, img):
        # 引数のimgは画像のnumpy配列

        # 画像からパック座標を推定
        mm_x,mm_y=video_capture.img2mm(img)
        if np.isnan(mm_x) or np.isnan(mm_y):
            print('no data')
            return
        print(f'mm_x={mm_x}, mm_y={mm_y}')
        self.msg.x = int(mm_x) #pack x座標
        self.msg.y = int(mm_y) #pack y座標
        self.msg.header.stamp = rospy.Time.now()
        self.pub.publish(self.msg)

class Subscribe_publishers:
    def __init__(self, pub: 'Publishers'):
        self.pub = pub
        # Subscriberを作成
        rospy.Subscriber("usb_cam/image_raw", Image, self.callback, queue_size=1)
        ws='/home/ishii/dobot_ws'  # Please modify here by your work spase directory
        self.cal = CameraCalibration(ws+'/src/robot_manipulation/src/robot_manipulation/calibration_params.npz')
        self.publisher = rospy.Publisher('usb_cam/image_raw/calib', Image, queue_size=1)

    def callback(self, img_msg):
        try:
            bridge = CvBridge()
            img = bridge.imgmsg_to_cv2(img_msg, "bgr8")
            img = self.cal.undistort(img)
            image_message = bridge.cv2_to_imgmsg(img, encoding="bgr8")
        except Exception as err:
            print(err)
        # publish
        self.publisher.publish(image_message)
        self.pub.make_msg(img)

def main():
    # nodeの立ち上げ
    rospy.init_node('image2positon')

    # クラスの作成
    pub = Publishers()
    sub = Subscribe_publishers(pub)

    rospy.spin()

if __name__ == '__main__':
    main()


from argparse import (
    ArgumentParser,
    Namespace,
    _SubParsersAction,
)
import logging
import pathlib

import rlp

from eth_utils import ValidationError

from eth.abc import ChainAPI
from eth.db.atomic import AtomicDB
from eth.db.backends.level import LevelDB
from eth.exceptions import HeaderNotFound
from eth.vm.forks.frontier.blocks import FrontierBlock
from eth.vm.interrupt import EVMMissingData

from trinity.config import (
    Eth1AppConfig,
    TrinityConfig,
)
from trinity.extensibility import Application
from trinity.initialization import (
    ensure_eth1_dirs,
    initialize_database,
)
from .rlp_decode import decode_all

def get_chain(trinity_config: TrinityConfig) -> ChainAPI:
    app_config = trinity_config.get_app_config(Eth1AppConfig)

    ensure_eth1_dirs(app_config)

    base_db = LevelDB(db_path=app_config.database_dir)
    chain_config = app_config.get_chain_config()
    chain = chain_config.full_chain_class(AtomicDB(base_db))

    initialize_database(chain_config, chain.chaindb, base_db)

    return chain

class ImportBlockComponent(Application):
    """
    Import blocks an RLP encoded file.
    """
    logger = logging.getLogger('trinity.components.BlockImport')

    @classmethod
    def configure_parser(cls,
                         arg_parser: ArgumentParser,
                         subparser: _SubParsersAction) -> None:

        import_parser = subparser.add_parser(
            'import',
            help='Import blocks from a file (RLP encoded)',
        )

        import_parser.add_argument(
            'file_path',
            type=pathlib.Path,
            help='Specify the file to import from'
        )

        import_parser.set_defaults(func=cls.run_import)

    @classmethod
    def run_import(cls, args: Namespace, trinity_config: TrinityConfig) -> None:
        with open(args.file_path, 'rb') as import_file:
            # This won't handle large files.
            # TODO: Make this stream based: https://github.com/ethereum/trinity/issues/1282
            file_bytes = import_file.read()

        blocks = decode_all(file_bytes, sedes=FrontierBlock)

        cls.logger.info("Importing %s blocks", len(blocks))

        chain = get_chain(trinity_config)

        for block in blocks:
            try:
                chain.import_block(block)
            except (EVMMissingData, ValidationError) as exc:
                cls.logger.error(exc)
                cls.logger.error("Import failed")
            else:
                cls.logger.info("Successfully imported %s", block)

class ExportBlockComponent(Application):
    """
    Export blocks to an RLP encoded file.
    """
    logger = logging.getLogger('trinity.components.BlockExport')

    @classmethod
    def configure_parser(cls,
                         arg_parser: ArgumentParser,
                         subparser: _SubParsersAction) -> None:

        export_parser = subparser.add_parser(
            'export',
            help='Export blocks to a file (RLP encoded)',
        )

        export_parser.add_argument(
            'file_path',
            type=pathlib.Path,
            help='Specify the file to export to'
        )

        export_parser.add_argument(
            'block_number',
            type=int,
            help='Specify the block number to be exported'
        )

        export_parser.add_argument(
            "--append",
            action="store_true",
            help="Disable peer discovery",
        )

        export_parser.add_argument(
            "--overwrite",
            action="store_true",
            help="Disable peer discovery",
        )

        export_parser.set_defaults(func=cls.run_export)

    @classmethod
    def run_export(cls, args: Namespace, trinity_config: TrinityConfig) -> None:
        chain = get_chain(trinity_config)
        try:
            block = chain.get_canonical_block_by_number(args.block_number)
        except HeaderNotFound:
            cls.logger.error("Block number %s does not exist in the database", args.block_number)
            return

        cls.logger.info("Exporting %s", block)

        block_bytes = rlp.encode(block)

        if args.file_path.exists() and not (args.append or args.overwrite):
            cls.logger.error(
                "%s does exist. Must use `--append` or `--overwrite` to proceed.", args.file_path
            )
            return

        parent_dir = args.file_path.parent

        if not parent_dir.exists():
            parent_dir.mkdir(parents=True)

        write_mode = 'w+b' if not args.append else 'a+b'

        cls.logger.info("Writing %s bytes to %s", len(block_bytes), args.file_path)

        with open(args.file_path, write_mode) as export_file:
            export_file.write(block_bytes)

        cls.logger.info("Successfully exported %s", block)


import pandas as pd
import random
import numpy as np
import visual_test as v

data1 = [1, 2, 3, 2, 1, 2, 3]
data2 = data1.copy()
random.shuffle(data2)

data1d = pd.DataFrame(data1)
data2d = pd.DataFrame()
data2d['x'] = data1
data2d['y'] = data2
list2d = [[data1[i], data2[i]] for i in range(len(data1))]

from data_filter import filtered_data as fd
mlist = []
fd(mlist, machine = 'FL02', sensor = 'drive_gear_V_eff')

#v.Plot(data = data1d, kind = 'scatter', marker = 'D', color = 'r', s = 3)
#v.Plot(data = data1d, kind = 'scatter', marker = 'D', ccolor = 'b', s = 3, legend = True, name = 'drek')

a = np.array(data2d)

#v.Plot(data = a, kind = 'scatter', marker = 'x', color = 'r', s = 15, figure = 'prasac')
#v.Plot(data = a, kind = 'line', c = 'r', legend = True, name = 'drek', figure = 'prasac')

b = np.arange(1, 100, 0.5)
c = b + np.random.rand(len(b)) * 50
df = pd.DataFrame()
df['x'] = b
df['y'] = c

v.Plot(data = df, kind = 'line', figure = 'konj', name = 'random')
v.Plot(data = df, kind = 'line', figure = 'konj', name = 'mean', feature = 'rol-mean', window = 10)

v.Plot(data = mlist, kind = 'scatter', marker = 'x', s = 0.1, color = 'r', figure = 'mes')
v.Plot(data = mlist, figure = 'mes', kind = 'scatter', marker = 'x', s = 0.1, color = 'b', feature = 'rol-mean', window = '1d')
v.Plot(data = mlist, figure = 'mes', kind = 'line',  color = 'y', feature = 'rol-mean', window = '15d')

v.Merge([['konj', 'mes'], ['t', 't']])


import unittest

from cart import Cart
from cashier import Cashier

class TestEcommerce(unittest.TestCase):

    # Iteration 1
    def test_can_create_an_empty_cart(self):
        cart = self.__empty_cart()

        self.assertTrue(cart.is_empty())

    def test_add_a_book_to_an_empty_cart(self):
        cart = self.__empty_cart()
        book = "book 1"
        cart.add_book(book)

        self.assertFalse(cart.is_empty())
        self.assertEqual(cart.count_book(book), 1)

    def test_be_able_to_add_more_than_one_book(self):
        cart = self.__empty_cart()
        cart.add_book("book 1")
        cart.add_book("book 2")
        cart.add_book("book 3")

        self.assertFalse(cart.is_empty())
        self.assertEqual(cart.count_book("book 1"), 1)
        self.assertEqual(cart.count_book("book 2"), 1)
        self.assertEqual(cart.count_book("book 3"), 1)

    def test_can_add_more_than_one_of_the_same_book(self):
        cart = self.__empty_cart()
        book = "book 1"
        cart.add_book(book, 2)

        self.assertEqual(cart.count_book(book), 2)

    def test_not_be_able_to_add_negative_quantity_of_books(self):
        cart = self.__empty_cart()
        book = "book 1"

        with self.assertRaises(Exception) as context:
            cart.add_book(book, -1)

        self.assertEqual(str(context.exception), Cart.INVALID_QUANTITY_MSG)
        self.assertEqual(cart.count_book(book), 0)

    def test_can_only_add_books_from_tus_libros(self):
        cart = self.__empty_cart()
        book = "external book"

        with self.assertRaises(Exception) as context:
            cart.add_book(book)

        self.assertEqual(str(context.exception), Cart.INVALID_BOOK_MSG)
        self.assertEqual(cart.count_book(book), 0)

    # Iteration 2
    def test_can_not_checkout_empty_cart(self):
        cart = self.__empty_cart()

        cashier = Cashier()

        with self.assertRaises(Exception) as context:
            cashier.checkout(cart)

        self.assertEqual(str(context.exception), Cashier.EMPTY_CART_MSG)

    def test_can_checkout_a_cart_with_one_book_of_10_pesos(self):
        cart = self.__empty_cart()
        book = "book 1"
        cart.add_book(book)

        cashier = Cashier()

        ticket_total = cashier.checkout(cart)

        self.assertEqual(ticket_total, 10)
        self.assertTrue(cart.is_empty())

    def __empty_cart(self):
        catalog = ['book 1', 'book 2', 'book 3']
        return Cart(catalog)

if __name__ == '__main__':
    unittest.main()


l = [1, 2, 2, 5, 8, 4, 4, 8]

def c1():
    l1 = range (min(l), max(l)+1)
    l11 = []
    for a in l1:
        if a in l:
            l11.append(a)
    print('#1: ', len(l11))
c1()

def c2():
    import collections
    a = collections.Counter(l)
    b = (list(a.items()))
    print('#2: ', len(b))
c2()

def c3():
    print('#3: ',len(set(l)))

c3()

def c4():
    n = 0
    c = []
    for a in l:
        if a not in c:
            n += 1
            c.append(a)
    print(n)
c4()

Advance List Programs/1.count unique values .py


import csv
from collections import defaultdict
import datetime

#-----Extras------

def ingresarGenerico(strg):
    return int(input(strg))

def verificarDNI(strg):
    ver = int(input(strg))
    while(ver>99999999 or ver<10000000):
        print("Valor invalido!")
        ver = int(input(strg))
    return ver

def verificarValor(strg):
    return float(input(strg))

def verificarFechas(strg):
    print(strg)

    año = int(input("Ingrese el año: "))
    while (año<=0):
        print("Año invalido!")
        año = int(input("Ingrese el año: "))

    mes = int(input("Ingrese el mes: "))
    while (mes<=0 or 13<=mes):
        print("Mes invalido!")
        mes = int(input("Ingrese el mes: "))

    dia = int(input("Ingrese el día: "))
    if(mes==1 or mes==3 or mes==5 or mes==7 or mes==9 or mes==11):
        ultimo=31
    elif(mes==4 or mes==6 or mes==8 or mes==10 or mes==12):
        ultimo=30
    else:
        ultimo=29

    while(dia<=0 or ultimo<dia):
        print("Dia invalido!")
        dia = int(input("Ingrese el día: "))

    fecha = datetime.datetime(año,mes,dia)
    return fecha.strftime("%Y-%m-%d")

def verificarTipo(strg):
    ver = input(strg)
    while(ver.lower()!="depositado" and ver.lower()!="emitido"):
        print("Valor invalido, los tipos de cheques son 'depositado' o 'emitido'")
        ver = input(strg)
    return ver

def verificarEstado(strg):
    ver = input(strg)
    while(ver.lower()!="aprobado" and ver.lower()!="pendiente" and ver.lower()!="rechazado"):
        print("Valor invalido, los estados de cheques son 'aprobado','pendiente' o 'rechazado'")
        ver = input(strg)
    return ver

def mostrarTitulo():
    print(f"|NroCheque|CodigoBanco|CodigoSucursal|NumeroCuentaOrigen|NumeroCuentaDestino|Valor|FechaOrigen|FechaPago|DNI|Estado|Tipo")

def mostrarDatos(dict):
    print(f"|{dict['NroCheque']}|{dict['CodigoBanco']}|{dict['CodigoSucursal']}|{dict['NumeroCuentaOrigen']}|{dict['NumeroCuentaDestino']}|{dict['Valor']}|{dict['FechaOrigen']}|{dict['FechaPago']}|{dict['DNI']}|{dict['Estado']}|{dict['Tipo']}|")

def crearArchivo(filtro,opcion):
    with open (f"{filtro}_{datetime.datetime.now().strftime('%Y-%m-%d')}_.csv","w",newline='') as wfile:
        with open("cheques.csv","r") as rfile:
            writer = csv.writer(wfile)
            reader = csv.DictReader(rfile)
            writer.writerow(reader.fieldnames)
            for row in reader:
                dni = row["DNI"]
                dni = int(dni)
                if(dni==filtro and opcion==1):
                    writer.writerow(row.values())
                elif(row['Tipo']==filtro and opcion==2):
                    writer.writerow(row.values())
                elif(row['Estado']==filtro and opcion==3):
                    writer.writerow(row.values())

def crearArchivoFechas(strg1,strg2):
    with open (f"FECHAS_{datetime.datetime.now().strftime('%Y-%m-%d')}_.csv","w",newline='') as wfile:
        with open("cheques.csv","r") as rfile:
            writer = csv.writer(wfile)
            reader = csv.DictReader(rfile)
            writer.writerow(reader.fieldnames)
            for row in reader:
                if(strg1<row["FechaOrigen"]<strg2):
                    writer.writerow(row.values())

#----Agregar---------

def agregar():
    with open ("cheques.csv","r") as lectura:
        reader = csv.reader(lectura)
        for row in reader:
            ultimo = row[0]
        ultimo = int(ultimo)
    with open ("cheques.csv","+a",newline='') as salida:
        writer = csv.writer(salida)
        NroCheque = ultimo + 1
        CodigoBanco = ingresarGenerico("Ingrese el codigo de Banco: ")
        CodigoSucursal = ingresarGenerico("Ingrese el codigo de la sucursal: ")
        NumeroCuentaOrigen = verificarDNI("Ingrese el numero de cuenta de origen: ")
        NumeroCuentaDestino = verificarDNI("Ingrese el numero de la cuenta de destino: ")
        Valor = verificarValor("Ingrese el valor del cheque: ")
        FechaOrigen = verificarFechas("Ingrese la fecha de origen del cheque: ")
        FechaPago = verificarFechas("Ingrese la fecha de pago del cheque: ")
        dni = verificarDNI("Ingrese su numero de DNI: ")
        Estado = verificarEstado("Ingrese el estado del cheque: ")
        Tipo = verificarTipo("Ingrese el tipo de cheque: ")
        writer.writerow([NroCheque,CodigoBanco,CodigoSucursal,NumeroCuentaOrigen,NumeroCuentaDestino,Valor,FechaOrigen,FechaPago,dni,Estado,Tipo])
        print("Agregados de manera exitosa")

#----Fin Agregar----------

#----Inicio Filtrado--------

def filtrado(filtro,opcion,salida):
    if(salida == 1):
        with open("cheques.csv","r") as file:
            reader = csv.DictReader(file)
            if(salida == 1):
                mostrarTitulo()
                for row in reader:
                    dni = row["DNI"]
                    dni = int(dni)
                    if(dni==filtro and opcion==1):
                        mostrarDatos(row)
                    elif(row["Tipo"]==filtro and opcion==2):
                        mostrarDatos(row)
                    elif(row["Estado"]==filtro and opcion==3):
                        mostrarDatos(row)
    elif(salida == 2):
        crearArchivo(filtro,opcion)

def filtradoFechas(strg1,strg2,salida):
    if(salida==1):
        with open("cheques.csv","r") as file:
            reader = csv.DictReader(file)
            for row in reader:
                if(strg1<row["FechaOrigen"]<strg2):
                    mostrarDatos(row)
    elif(salida==2):
        crearArchivoFechas(strg1,strg2)

def menuFiltros():
    opcion = 0
    strg = ""
    strg1 = ""
    strg2 = ""
    salida = int(input("Ingrese '1' si desea una salida por pantalla o '2' si la desea creando un archivo csv: "))
    while(opcion>0 or opcion<=4):
        print("Seleccione uno de los siguientes filtros: ")
        print("1-Por un DNI particular")
        print("2-Por el tipo de cheque")
        print("3-Estado del cheque")
        print("4-Rango de fechas")
        print("5-Salir")
        opcion = int(input())
        if(opcion==1):
            strg = verificarDNI("Ingrese el DNI a filtrar: ")
            filtrado(strg,opcion,salida)
        elif(opcion==2):
            strg = verificarTipo("Ingrese el tipo de cheque: ")
            filtrado(strg,opcion,salida)
        elif(opcion==3):
            strg =verificarEstado("Ingrese el estado del cheque: ")
            filtrado(strg,opcion,salida)
        elif(opcion==4):
            strg1 = verificarFechas("Ingrese la primera fecha: ")
            strg2 = verificarFechas("Ingrese la segunda fecha: ")
            filtradoFechas(strg1,strg2,salida)
        elif(opcion==5):
            break
        else:
            print("Ingrese una opción valida!")

def filtrar():
    menuFiltros()
    print("Filtrado exitoso")

#----Fin Filtrado----

#---Inicio Salir

def salir():
    print("Fin")

#----Fin salir----

#---Inicio Menu----

def menu():
    opcion = 0
    while(opcion>0 or opcion<=3):
        print("Bienvenido al menu")
        print("Seleccione una de las opciones para continar")
        print("1-Agregar")
        print("2-Filtrar")
        print("3-Salir")
        opcion = int(input())
        if(opcion==1):
            agregar()
        elif(opcion==2):
            filtrar()
        elif(opcion==3):
            salir()
            break
        else:
            print("La opción ingresada no es valida, ingrese una opción válida")

#-----Fin Menu-----

#----MAIN------
menu()
#----FIN MAIN-----


import json
import os

# class Employee:
#     def __init__(self, name, surname):
#         self.first_name = name
#         self.last_name = surname
#         self.salary = 1000

#     def increase_salary(self):
#         self.salary += 100

#     def decrease_salary(self):
#         self.salary -= 100

# bob = Employee('Bob', 'Jones')
# sam = Employee('Sam', 'Heckley')

# class Animal:
#     def __init__(self, name, age) -> None:
#         self.name = name
#         self.age = age
#         self.legs_count = 4

#     def make_sound(self):
#         print('unknown sound')

# class Cat(Animal):
#     pass

# class Dog(Animal):
#     def make_sound(self):
#         print('Woof')

# tom = Cat('tom', 4)
# goofy = Dog('goofy', 6)

# print(tom.age)
# tom.make_sound()
# goofy.make_sound()

# class Mammal:
#     def __init__(self, color, has_tail=True, legs_count=4, sound=None) -> None:
#         self.color = color
#         self.has_tail = has_tail
#         self.legs_count = legs_count

#     def make_sound(self):
#         if self.sound is not None:
#             print(self.sound)
#         else:
#             print('')

# class PetMammal(Mammal):
#     def __init__(self, name, color, has_tail=True, legs_count=4, sound=None) -> None:
#         self.name = name
#         super().__init__(color, has_tail, legs_count, sound)

# class Cat(Mammal):
#     def make_sound(self) -> None:
#         print(f'{self.color} cat says ', end='')
#         super().make_sound()

# class PetCat(PetMammal):
#     def make_sound(self) -> None:
#         print(f'{self.name} says ', end='')
#         super().make_sound()

# class Dog(Mammal):
#     def make_sound(self) -> None:
#         print(f'{self.color} dog says ', end='')
#         super().make_sound()

# class PetDog(PetMammal):
#     def make_sound(self) -> None:
#         print(f'{self.name} says ', end='')
#         super().make_sound()

# class Tiger:
#     interests = ['sleeping', 'eating']

#     def __init__(self, name):
#         self.name = name

# bob = Tiger('Bob')
# print(bob.interests)
# bob.interests = ['doing nothing']
# print(bob.interests)

# print('---')

# maddy = Tiger('Madelyn')
# maddy.interests = ['sleeping', 'eating', 'playing']
# print(Tiger.interests)
# print(maddy.interests)

# print('---')
# Tiger.interests = []

# simon = Tiger('Simon')
# print(simon.interests)\

# class Numbers:
#     def __init__(self) -> None:
#         self._data = []

#     def add(self, value):
#         self._data.append(value)

#     def get(self, index):
#         return self._data[index]

#     def get_length(self):
#         return len(self._data)

#     def __len__(self):
#         return len(self._data)

# class NumbersIter:
#     def __init__(self, instance) -> None:
#         self.instance = instance
#         self.position = - 1

#     def __next__(self):
#         self.position += 1
#         if self.position < len(self.instance):
#             return self.instance[self.position]
#         else:
#             raise StopIteration

# class Numbers:
#     def __init__(self) -> None:
#         self._data = [1, 2, 3, 4]

#     def __len__(self):
#         return len(self._data)

#     def __getitem__(self, index):
#         return self._data[index]

#     def __setitem__(self, index, value):
#         self._data[index] = value

#     def __str__(self):
#         return str(self._data)

#     def __repr__(self):
#         return self._data

#     def __iter__(self):
#         return NumbersIter(self)

# class NumbersIterator:
#     def __init__(self, numbers_instance: 'Numbers') -> None:
#         self._numbers_to_iterate = numbers_instance
#         self._position = -1

#     def __next__(self) -> int:
#         self._position += 1
#         if self._position < len(self._numbers_to_iterate):
#             return self._numbers_to_iterate.get(self._position)
#         else:
#             raise StopIteration

# class Numbers:
#     def __init__(self) -> None:
#         self._data = [1, 2, 3, 4]

#     def __getitem__(self, index: int) -> int:
#         return self._data[index]

#     def __setitem__(self, index: int, value: int) -> None:
#         self._data[index] = value

#     def __iter__(self):
#         # Если метода __contains__ нет, то код:
#         # numbers = Numbers()
#         # value in numbers
#         # вызовет __iterator__
#         # и при помощи полученного итератора переберет все значения
#         print('inside __iter__')
#         return NumbersIterator(self)

#     def __contains__(self, value: int) -> bool:
#         # Если метод __contains__ есть, то код:
#         # numbers = Numbers()
#         # value in numbers
#         # вызовет его
#         print('inside __contains__')
#         return value in self._data

#     def __len__(self) -> int:
#         return len(self._data)

#     def __str__(self) -> str:
#         # Показать строковое представление объекта для человека
#         return str(self._data)

#     def __repr__(self) -> str:
#         # От representation - показать "техническое" строковое представление для программиста
#         return f'<Объект Numbers c числами {self._data}>'

# разделение и ответственность!

class Student:
    def __init__(self, name: str, last_name: str, age: int) -> None:
        self.name = name
        self.last_name = last_name
        self.age = age

    def __repr__(self) -> str:
        return f'{self.name}, {self.last_name}, {self.age}'

# class Program:
#     def __init__(self, students=None) -> None:
#         # self.students = []
#         # if students is not None:
#         #     self.students = students
#         if students == None:
#             self.students = []
#         else:
#             self.students = students

#     def list(self) -> list[Student]:
#         return self.students

#     def add_student(self, first_name: str, last_name: str, age: int):
#         new_student = Student(first_name=first_name, last_name=last_name, age=age)
#         self.students.append(new_student)

class InMemoryStudentsRepository:
    def __init__(self) -> None:
        self.students = []

    def get_all_students(self):
        return self.students

    def add_student(self, student: Student):
        self.students.append(student)

class JsonFileStudentsRepository:
    """
    Репозиторий для хранения данных о студентах в JSON-файлах следующего формата:
    [
        {"first_name" <first_name>, "last_name": <last_name>, "age": <age>},
        ...
    ]
    """
    def __init__(self, filename) -> None:
        self.filename = filename

    def get_all_students(self):
        student_records = self._read_records_from_file()
        students = self._parse_student_records_from_file(student_records)
        return students

    def add_student(self, student: Student):
        student_records = self._read_records_from_file()
        new_student_record = self._conver_student_to_dict(student)
        student_records.append(new_student_record)
        self._write_student_records_to_file(student_records)

    def _write_student_records_to_file(self, student_records: list[dict]) -> None:
        """Записать на диск набор записей (словарей нужного формата)."""
        with open(self.filename, 'w') as data_file:
            data_file.write(json.dumps(student_records))

    def _read_records_from_file(self) -> list[dict]:
        """Прочесть с диска набор записей (словарей нужного формата)."""
        # Если файла еще нет, надо его создать и сохранить в него пустой список студентов"""
        if not os.path.exists(self.filename):
            self._write_student_records_to_file([])

        # try:
        #     with open(self.filename, 'r') as data_file:
        #         data = data_file.read()
        # except FileNotFoundError:
        #     self._write_student_records_to_file([])

        # А теперь, когда он точно существует, можно просто его смело читать
        with open(self.filename, 'r') as data_file:
            data = data_file.read()
        return json.loads(data)

    def _parse_student_records_from_file(self, student_records: list[dict]) -> list[Student]:
        """Сконвертировать набор записей (словарей нужного формата) в набор объектов Student."""
        result = []
        for record in student_records:
            student = Student(first_name=record['first_name'], last_name=record['last_name'], age=record['age'])
            result.append(student)
        return result

    def _conver_student_to_dict(self, student: Student) -> dict:
        """Сконвертировать объект Student в словарь подходящего для записи в файл формата."""
        return {
            'name': student.name,
            'last_name': student.last_name,
            'age': student.age
        }

class ConsoleUI:

    @staticmethod
    def get_action():
        return ConsoleUI._get_user_input('enter a command: ')

    @staticmethod
    def get_student_data() -> tuple(str, str, int):
        first_name = ConsoleUI._get_user_input('Введите имя студнта: ')
        last_name = ConsoleUI._get_user_input('Введите фамилию студента: ')
        age = ConsoleUI._get_user_input('Введите возраст студента: ', converter_func=int)
        return (first_name, last_name, age)

    @staticmethod
    def list_students(students: list[Student]) -> None:
        print(students)

    @staticmethod
    def _get_user_input(prompt_text: str, converter_func = str):
        user_input = input(prompt_text)
        return converter_func(user_input)

    @staticmethod
    def list_available_actions():
        print('add', 'list', 'delete', 'quit')

if __name__ == '__main__':
     # Репозиторий нужен для взаимодействия с хранилищем данных
    student_repository = JsonFileStudentsRepository(filename='students.json')
    ui_functions = ConsoleUI

    ui_functions.list_available_actions()
    while True:
        ui_functions.list_available_actions()
        selected_action = ui_functions.get_action()

        if selected_action == 'help':
            ui_functions.list_available_actions()
        elif selected_action == 'list':
            students = student_repository.get_all_students()
            ui_functions.list_students()
        elif selected_action == 'add':
            first_name, last_name, age = ui_functions.get_student_data()
            new_student = Student(first_name=first_name, last_name=last_name, age=age)
            student_repository.add_student(new_student)
        elif selected_action == 'qConsoleUIt':
            break


import csv
import math
from operator import indexOf
list = [0,0,0,0,0,0,0]
temp = 0
with open('list.csv', newline='') as f:
    read = csv.reader(f, delimiter=',')
    for row in read:
        list[temp] = row
        temp += 1
url = input()
final = ""
'''
for i in range(1, 6):
    final += list[0][indexOf(list[i], url[i - 1])]
print(final)
'''
for i in range(0, len(url)):
    final += list[0][indexOf(list[i % 6 + 1], url[i])]
print(final)


print('作业1-for循环写九九乘法表')
for i in range(1,10):
     print('''
''')
     for j in range(1,i+1):
          print(j,'*',i,'=',i*j,end=' ')

print(''''
''')

print('作业2- 移除重复元素')
list = [i for i in range(10)]
list.extend(j for j in range(10) if j%2==0)
print('原    数    组：',list)
result = []
for k in list:
     if result.count(k) ==0:
          result.append(k)
list.clear()
list=result.copy()
print('去重后数组：',list)


import numpy as np
import cv2
import matplotlib.pyplot as plt
import torch
from scipy import signal

def compute_light_percentage(image, thresh):
    # 计算亮度大于某个阈值的占比
    assert len(image.shape) == 2
    img_h, img_w = image.shape[:2]
    dark_area = (image >= thresh).sum()
    area = img_h * img_w
    return 1.0 * dark_area / area

def compute_dark_percentage(image, thresh):
    # 计算亮度黑于某个阈值的占比
    assert len(image.shape) == 2
    img_h, img_w = image.shape[:2]
    dark_area = (image <= thresh).sum()
    area = img_h * img_w
    return 1.0 * dark_area / area

def avg_filt_1d(vector, kernel_size):
    # 对向量进行卷积平滑操作
    """
    Args:
            vector (array): Input vector
            kernel_size (int): kernel size of average filtering
    Returns:
            vector (array): Smoothed vector
    """
    kernel = np.ones([kernel_size]) / kernel_size
    return np.convolve(vector, kernel, mode='same')

def padding(image, pad_h, pad_w):
    # 给图片添加padding
    image_shape = np.array(image.shape)
    h, w = image_shape[:2]
    pad_shape = image_shape.copy()
    pad_shape[0] = pad_h
    pad_shape[1] = pad_w
    image_pad = np.zeros(pad_shape, dtype=image.dtype)
    image_pad[:h, :w, ...] = image
    return image_pad

def get_median(vector):
    # 获取向量的中位数
    assert len(vector) >= 1
    return np.sort(vector)[int(len(vector) / 2)]

def graytoprofile(gray):
    # 边缘检测
    kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))
    dilate = cv2.dilate(gray, kernel)
    erode = cv2.erode(gray, kernel)
    profile = cv2.absdiff(dilate, erode)
    return profile

def sqrt_var_hist(histogram):
    # 求直方图的方差开根号
    return np.sqrt(np.var(histogram))

#   阿里 的代码 start
def detect_dark_to_light(vector, gray_thresh):
    u"""
            - 从左检测一个向量从暗到亮的跳变点
            Args:
                    vector (array): Vector with shape (N,)
                    gray_thresh (float): Gray threshold
            Returns:
                    index (int): index of the boundary

            Examples:
                    Assume len(vector)=100, gray_thresh=80
                    1. Normal vector
                    vector: [ 10,  10,  10, 200, 200, 200...] -> return 3
                    2. Noisy vector
                    vector: [ 10, 200,  10,  10, 200, 200...] -> return 4
                    3. All dark vector
                    vector: [ 10,  10,  10,  10,  10,  10...] -> return 100
                    4. All light vector
                    vector: [200, 200, 200, 200, 200, 200...] -> return 0
            """
    min_step = 5
    gray_sum = vector[:min_step].sum()
    if gray_sum / min_step >= gray_thresh:
        return 0
    num_points = len(vector)
    vector = np.concatenate([vector, vector[-(min_step - 1):]])
    for i in range(1, len(vector) - min_step + 1):
        gray_sum -= vector[(i - 1)]
        gray_sum += vector[(i + min_step - 1)]
        if gray_sum / min_step >= gray_thresh:
            return i

    return num_points

def remove_baseline_shift(vector, step=10):
    """
    Args:
            vector (array): Numpy vector with shape (num_points,)
            step (int): Kernel size of average filtering
    Returns:
            vector (array): Vector with baseline shift removed
    """
    if step % 2 == 0:
        step += 1
    vector_smoothed = signal.medfilt(vector, step)
    avg_smoothed = avg_filt_1d(vector, kernel_size=step)
    temp_step = int(len(vector) / 40)
    center_ind = int(len(vector) / 2)
    x1 = center_ind - temp_step
    x2 = center_ind + temp_step
    vector_smoothed[x1:x2] = avg_smoothed[x1:x2]
    return vector - vector_smoothed

def compute_l1_dis_matrix(vector1, vector2):
    """
        Args:
                vector1 (array): Vector with shape (N,)
                vector2 (array): Vector with shape (M,)
        Returns:
                dis_matrix (array): Distance matrix with shape (N, M)
        """
    return np.abs(vector1[(Ellipsis, None)] - vector2[(None, Ellipsis)])

def compute_nms_mask_1d(vector, scores, distance_thresh):
    assert len(vector) == len(scores)
    dis_matrix = compute_l1_dis_matrix(vector, vector)
    dis_matrix += (np.eye(len(vector)) * 100000.0).astype(vector.dtype)
    order = scores.argsort()[::-1]
    mask = np.ones([len(vector)]).astype(np.bool)
    for ind in order:
        if mask[ind] == False:
            continue
        v = vector[ind]
        dis = dis_matrix[ind]
        mask[dis <= distance_thresh] = False

    return mask

def nms_1d(vector, scores, distance_thresh):
    mask = compute_nms_mask_1d(vector, scores, distance_thresh)
    return vector[mask]

def compute_local_minimum_mask(vector):
    """
        Args:
                vector (array)
        Returns:
                is_minimum (array): bool vector
        """
    if len(vector) <= 3:
        return np.zeros([len(vector)], dtype=np.bool)
    v = vector
    is_minimum = (v[1:-1] - v[:-2] <= 0) * (v[1:-1] - v[2:] <= 0)
    is_minimum = np.concatenate([is_minimum[0:1], is_minimum, is_minimum[-1:]])
    return is_minimum

def detect_negative_impulse_2(vector):
    """
        Args:
                vector (array): Input vector with shape (num_points,)
        Returns:
                inds ()
        """
    is_minimum = compute_local_minimum_mask(vector)
    mean_value = vector.mean()
    low_value = vector[vector.argsort()][:10].mean()
    thresh = low_value * 0.3 + mean_value * 0.7
    picked_inds = np.where((vector < thresh) * is_minimum)[0]
    return picked_inds

def detect_negative_impulse(vector, diff_thresh=3.0, nms_thresh=None, debug=False):
    # 检测负脉冲
    is_minimum = compute_local_minimum_mask(vector)
    if nms_thresh is not None:
        minimum_inds = np.where(is_minimum)[0]
        minimum_inds = nms_1d(minimum_inds, scores=-vector[minimum_inds], distance_thresh=nms_thresh)
        is_minimum[...] = False
        is_minimum[minimum_inds] = True
    center = get_median(vector)
    median_distance = get_median(np.abs(vector - center))
    v = vector[is_minimum]
    order = v.argsort()
    v_sort = np.sort(v)
    order_diff = v_sort[2:] - v_sort[:-2]
    if debug:
        plt.figure()
        plt.subplot(2, 1, 1)
        plt.plot(order_diff)
        plt.plot(order_diff, '.')
        plt.plot([0, len(order_diff)], [5 * median_distance, 5 * median_distance])
        plt.subplot(2, 1, 2)
        plt.plot(vector)
        inds = np.where(is_minimum)[0]
        plt.plot(inds, vector[inds], '.')
        plt.show()
    impulse_inds = np.where(order_diff > diff_thresh)[0]
    if len(impulse_inds) == 0:
        return np.zeros([0])
    else:
        impulse_inds = impulse_inds[(impulse_inds < int(len(v) * 0.66))]
        if len(impulse_inds) == 0:
            return np.zeros([0])
        impulse_ind = impulse_inds[(-1)]
        if order_diff[impulse_ind] < 5:
            impulse_ind -= 1
        thresh = v_sort[impulse_ind]
        picked_inds = np.where((vector <= thresh) * is_minimum)[0]
        if debug:
            plt.figure(figsize=(10, 10))
            plt.subplot(3, 1, 1)
            plt.plot(order_diff)
            plt.plot(order_diff, '.')
            plt.plot([0, len(order_diff)], [diff_thresh, diff_thresh])
            plt.xlim([0, len(order_diff) - 1])
            plt.subplot(3, 1, 2)
            plt.plot(vector)
            inds = np.where(is_minimum)[0]
            plt.plot(inds, vector[inds], '.')
            plt.xlim([0, len(vector) - 1])
            plt.subplot(3, 1, 3)
            plt.plot(vector)
            plt.plot(picked_inds, vector[picked_inds], '.')
            plt.plot([0, len(vector)], [thresh, thresh])
            plt.xlim([0, len(vector) - 1])
            plt.show()
        if debug:
            plt.figure()
            plt.subplot(2, 1, 1)
            plt.plot(order_diff)
            plt.plot(order_diff, '.')
            plt.subplot(2, 1, 2)
            plt.plot(vector)
            plt.plot(picked_inds, vector[picked_inds], '.')
            plt.plot([0, len(vector)], [thresh, thresh])
            plt.show()
        return picked_inds

# 阿里的代码end

def plt_show_cv2(image):
    # plt 显示 opencv 格式的图片
    plt.figure(1)
    if len(image.shape) == 2:
        ## 把单通道的灰度图转换成三通道的灰度图
        image = np.concatenate(
            (np.expand_dims(image, axis=2), np.expand_dims(image, axis=2), np.expand_dims(image, axis=2)), axis=-1)
        # plt.imshow(image,cmap='gray',interpolation='bicubic')#显示灰度图
    else:
        image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
    plt.imshow(image)
    plt.show()

def crop_image_like(image, crop_bbox):
    """
    获取bbox对应的图片
    :param image:
    :param crop_bbox:
    :return:
    """
    xmin, ymin, xmax, ymax = crop_bbox
    if xmax == -1:
        xmax = image.shape[1] + 1
    if ymax == -1:
        ymax = image.shape[0] + 1
    image_crop = image[ymin:ymax + 1, xmin:xmax + 1, ...]
    return image_crop

def cv2ToTorch(img):
    """单张cv2的格式转torch 的tensor"""
    img = img[:, :, ::-1].transpose(2, 0, 1)  # BGR to RGB, to cxhxw
    img = np.ascontiguousarray(img, dtype=np.float32)
    img = torch.from_numpy(img)
    return img

def group_consecutive(a, trod=10):
    """将连续的值分组
    [1, 2, 3, 7, 8, 9, 10, 100, 101, 102, 103]->[array([1, 2, 3]), array([ 7,  8,  9, 10]), array([100, 101, 102, 103])]
    """
    return np.split(a, np.where(np.diff(a) >= trod)[0] + 1)

def detect_best_drop_line(col_histogram,nInteral=5):
    # 求突然上升很大值的位置
    """
    求突然上升很大值和突然下降很大值的位置
    col_histogram = np.sum(subImg2, axis=0)
    nInteral = 20
    cols_minInterval = subImg2.shape[1] // nInteral
    ## left
    left_scope_diff = [np.sum(col_histogram[idx - nInteral:idx].astype(np.int)) - np.sum(
        col_histogram[idx:idx + nInteral].astype(np.int))
                       for idx in range(nInteral, cols_minInterval - nInteral)]
    left_edge = nInteral + np.argmax(left_scope_diff)
    ## right
    right_scope_diff = [np.sum(col_histogram[idx - nInteral:idx].astype(np.int)) - np.sum(
        col_histogram[idx:idx + nInteral].astype(np.int))
                        for idx in range(subImg2.shape[1] - cols_minInterval + nInteral, subImg2.shape[1] - nInteral)]
    right_edge = subImg2.shape[1] - cols_minInterval + nInteral + np.argmin(right_scope_diff)
    """
    # col_histogram = np.sum(vector, axis=0)
    cols_minInterval = col_histogram.shape[0] // nInteral
    left_scope_diff = [np.sum(col_histogram[idx - nInteral:idx].astype(np.int)) - np.sum(
        col_histogram[idx:idx + nInteral].astype(np.int))
                       for idx in range(nInteral, cols_minInterval - nInteral)]
    return nInteral + np.argmax(left_scope_diff)

def skimage2opencv(src):
    src *= 255
    src.astype(int)
    cv2.cvtColor(src,cv2.COLOR_RGB2BGR)
    return src

def opencv2skimage(src):
    cv2.cvtColor(src,cv2.COLOR_BGR2RGB)
    src.astype(np.float32)
    src /= 255
    return src


# 主业务逻辑中的视图和路由的定义
from flask import Flask, render_template, request, session, redirect
# 导入蓝图程序，用于构建路由
from . import cart
# 导入db，用于操作数据库
from .. import db
# 导入实体类，用于操作数据库
from ..models import *
from ..seller.redis_store import r
import json
# 返回购物车数据

path = "http://127.0.0.1:5000/static/image/"
@cart.route('/get_cart')
def get_cart():
    token = request.args.get("token")
    if not r.get(token):
        return "登录失效",403
    cid = r.get(token)
    cart = Cart.query.filter_by(customer_id=cid).first()
    cp_products = cart.cp_products.all()
    products = []
    for i in cp_products:
        products.append(i.products)
    store = []
    product = []
    for i in products:
        pd = {}
        seller = i.seller
        if seller not in store:
            store.append(seller)
        num = Cprelate.query.filter_by(
            product_id=i.id, cart_id=cart.id).first().num
        pd['id'] = i.id
        pd['store_id'] = seller.id
        pd['url'] = path + i.pictures.filter_by(type_id=1).first().picture_name
        pd['text'] = i.description
        pd['price'] = i.price
        pd['remaining'] = i.remain
        pd['product_checked'] = True
        if num == 1:
            pd['delStatus'] = 'disabled'
            pd['addStatus'] = 'normal'
        elif num == i.remain:
            pd['delStatus'] = 'normal'
            pd['addStatus'] = 'disabled'
        else:
            pd['delStatus'] = 'normal'
            pd['addStatus'] = 'normal'
        pd['quantity'] = num
        product.append(pd)

    def make_store(i):
        s = {}
        s['name'] = i.seller_name
        s['kind_checked'] = False
        s['store_id'] = i.id
        return s
    store = list(map(make_store, store))

    res = {}
    res['store'] = store
    res['product'] = product
    res["cart_id"] = cart.id
    return json.dumps(res)

@cart.route('/delete_cart', methods=['GET','POST'])
def delete_cart():
    if request.method == "POST":
        token = request.form.get("token")
        if not r.get(token):
            return "登录失效",403
        cid = r.get(token)
        pid = json.loads(request.form.get('pid'))
        cart = Cart.query.filter_by(customer_id=cid).first()
        for cprel in cart.cp_products:
            if cprel.product_id in pid:
                db.session.delete(cprel)
        return '成功删除'

@cart.route('/add_cart', methods=["GET", "POST"])
def add_cart():
    if request.method=="GET":
        sell_num = request.args.get("quantity")
        product_id = request.args.get("product_id")
        token = request.args.get("token")
        if not r.get(token):
            return "登录失效",403
        customer_id = r.get(token)
        cart = Cart.query.filter_by(customer_id=customer_id).first()
        cprelate = Cprelate.query.filter_by(cart_id=cart.id,product_id=product_id).first()
        if not cprelate:
            cprelate = Cprelate(product_id=product_id, cart_id=cart.id, num=sell_num)
        else:
            cprelate.num = sell_num
        db.session.add(cprelate)
        return "购物车加入成功"

@cart.route("/update_cart", methods=["GET", "POST"])
def update_cart():
    if request.method=="POST":
        cart_id = request.form.get("cart_id")
        products = json.loads(request.form.get("product"))
        for product in products:
            cprelate = Cprelate.query.filter_by(product_id=product['id'],cart_id=cart_id).first()
            if product["quantity"] == cprelate.num:
                return "不用更新"
            else:
                cprelate.num = product["quantity"]
                db.session.add(cprelate)
                return "更新成功"
        return "购物车为空了"


import copy
import random

from eth_utils import ValidationError
from eth_utils.toolz import assoc
import pytest

from eth2._utils.bls import bls
from eth2.beacon.attestation_helpers import (
    is_slashable_attestation_data,
    validate_indexed_attestation,
    validate_indexed_attestation_aggregate_signature,
)
from eth2.beacon.helpers import compute_signing_root, get_domain
from eth2.beacon.signature_domain import SignatureDomain
from eth2.beacon.types.attestation_data import AttestationData
from eth2.beacon.types.attestations import Attestation, IndexedAttestation
from eth2.beacon.types.forks import Fork

@pytest.mark.parametrize(("validator_count",), [(40,)])
def test_verify_indexed_attestation_signature(
    slots_per_epoch,
    validator_count,
    genesis_state,
    config,
    privkeys,
    sample_attestation_params,
    sample_indexed_attestation_params,
    sample_fork_params,
):
    state = genesis_state.set("fork", Fork.create(**sample_fork_params))
    attestation = Attestation.create(**sample_attestation_params)

    valid_params = _correct_indexed_attestation_params(
        validator_count,
        attestation,
        sample_indexed_attestation_params,
        privkeys,
        state,
        config,
    )
    valid_votes = IndexedAttestation.create(**valid_params)

    validate_indexed_attestation_aggregate_signature(
        state, valid_votes, slots_per_epoch
    )

    invalid_params = _corrupt_signature(slots_per_epoch, valid_params, state.fork)
    invalid_votes = IndexedAttestation.create(**invalid_params)
    with pytest.raises(ValidationError):
        validate_indexed_attestation_aggregate_signature(
            state, invalid_votes, slots_per_epoch
        )

def _get_indices_and_signatures(validator_count, state, config, attestation, privkeys):
    num_indices = 5
    assert validator_count >= num_indices
    indices = random.sample(range(validator_count), num_indices)
    indices.sort()

    privkeys = [privkeys[i] for i in indices]
    domain = get_domain(
        state=state,
        signature_domain=SignatureDomain.DOMAIN_BEACON_ATTESTER,
        slots_per_epoch=config.SLOTS_PER_EPOCH,
    )
    signing_root = compute_signing_root(attestation.data, domain)

    signatures = tuple(map(lambda key: bls.sign(key, signing_root), privkeys))
    return (indices, signatures)

def _run_verify_indexed_vote(
    slots_per_epoch, params, state, max_validators_per_committee, should_succeed
):
    votes = IndexedAttestation.create(**params)
    if should_succeed:
        validate_indexed_attestation(
            state, votes, max_validators_per_committee, slots_per_epoch
        )
    else:
        with pytest.raises(ValidationError):
            validate_indexed_attestation(
                state, votes, max_validators_per_committee, slots_per_epoch
            )

def _correct_indexed_attestation_params(
    validator_count, attestation, params, privkeys, state, config
):
    valid_params = copy.deepcopy(params)

    (attesting_indices, signatures) = _get_indices_and_signatures(
        validator_count, state, config, attestation, privkeys
    )

    valid_params["attesting_indices"] = attesting_indices

    signature = bls.aggregate(*signatures)

    valid_params["signature"] = signature

    return valid_params

def _corrupt_attesting_indices(params):
    corrupt_attesting_indices = (
        params["attesting_indices"][1],
        params["attesting_indices"][0],
    ) + tuple(params["attesting_indices"][2:])

    return assoc(params, "attesting_indices", corrupt_attesting_indices)

def _corrupt_attesting_indices_max(max_validators_per_committee, params):
    corrupt_attesting_indices = [i for i in range(max_validators_per_committee + 1)]
    return assoc(params, "attesting_indices", corrupt_attesting_indices)

def _corrupt_signature(slots_per_epoch, params, fork):
    return assoc(params, "signature", b"\x12" * 96)

@pytest.mark.parametrize(("validator_count",), [(40,)])
@pytest.mark.parametrize(
    ("param_mapper", "should_succeed", "needs_fork", "is_testing_max_length"),
    [
        (lambda params: params, True, False, False),
        (_corrupt_attesting_indices, False, False, False),
        (_corrupt_signature, False, True, False),
    ],
)
def test_validate_indexed_attestation(
    slots_per_epoch,
    validator_count,
    genesis_state,
    param_mapper,
    should_succeed,
    needs_fork,
    is_testing_max_length,
    privkeys,
    sample_indexed_attestation_params,
    sample_fork_params,
    max_validators_per_committee,
    config,
):
    state = genesis_state.set("fork", Fork.create(**sample_fork_params))
    attestation = IndexedAttestation.create(**sample_indexed_attestation_params)

    params = _correct_indexed_attestation_params(
        validator_count,
        attestation,
        sample_indexed_attestation_params,
        privkeys,
        state,
        config,
    )
    if needs_fork:
        params = param_mapper(slots_per_epoch, params, state.fork)
    elif is_testing_max_length:
        params = param_mapper(max_validators_per_committee, params)

    else:
        params = param_mapper(params)
    _run_verify_indexed_vote(
        slots_per_epoch, params, state, max_validators_per_committee, should_succeed
    )

@pytest.mark.parametrize(("validator_count",), [(40,)])
def test_verify_indexed_attestation_after_fork(
    genesis_state,
    slots_per_epoch,
    validator_count,
    privkeys,
    sample_attestation_params,
    sample_indexed_attestation_params,
    config,
    max_validators_per_committee,
):
    # Test that indexed data is still valid after fork
    # Indexed data slot = 10, fork slot = 15, current slot = 20
    past_fork_params = {
        "previous_version": (0).to_bytes(4, "little"),
        "current_version": (1).to_bytes(4, "little"),
        "epoch": 15,
    }

    state = genesis_state.mset("slot", 20, "fork", Fork.create(**past_fork_params))
    attestation = Attestation.create(**sample_attestation_params)

    valid_params = _correct_indexed_attestation_params(
        validator_count,
        attestation,
        sample_indexed_attestation_params,
        privkeys,
        state,
        config,
    )
    _run_verify_indexed_vote(
        slots_per_epoch, valid_params, state, max_validators_per_committee, True
    )

@pytest.mark.parametrize(
    ("is_double_vote," "is_surround_vote,"),
    [(False, False), (False, True), (True, False), (True, True)],
)
def test_is_slashable_attestation_data(
    sample_attestation_data_params, is_double_vote, is_surround_vote
):
    data_1 = AttestationData.create(**sample_attestation_data_params)
    data_2 = AttestationData.create(**sample_attestation_data_params)

    if is_double_vote:
        data_2 = data_2.set(
            "beacon_block_root",
            (int.from_bytes(data_1.beacon_block_root, "little") + 1).to_bytes(
                32, "little"
            ),
        )

    if is_surround_vote:
        data_1 = data_1.transform(
            ("source", "epoch"), data_2.source.epoch - 1
        ).transform(("target", "epoch"), data_2.target.epoch + 1)

    assert is_slashable_attestation_data(data_1, data_2) == (
        is_double_vote or is_surround_vote
    )


import os,sys,glob,time,collections,gc,random
import numpy as np
from netCDF4 import Dataset,num2date
import dimarray as da
import subprocess as sub

try:
	model=sys.argv[1]
except:
	model = 'CAM4-2degree'

scenario = 'Plus20-Future'
seed = 'v2'

print(model,scenario,seed)

try:
	sys.path.append('/p/projects/ikiimp/HAPPI/HAPPI_Peter/persistence_in_HAPPI/')
	os.chdir('/p/projects/ikiimp/HAPPI/HAPPI_Peter/')
	in_path='/p/tmp/pepflei/HAPPI/raw_data/'+model+'/'
	out_path='/p/tmp/pepflei/HAPPI/raw_data/reg_merge/'+model+'/'
	home_path = '/p/projects/ikiimp/HAPPI/HAPPI_Peter/persistence_in_HAPPI/'

except:
	sys.path.append('/global/homes/p/pepflei/persistence_in_models/')
	os.chdir('/global/homes/p/pepflei/')

os.system('mkdir '+in_path+scenario.replace('Future','Artificial-'+str(seed)))
os.system('mkdir '+in_path+scenario.replace('Future','Artificial-'+str(seed))+'/pr/')

import __settings
model_dict=__settings.model_dict
landmask = da.read_nc('masks/landmask_'+model_dict[model]['grid']+'.nc')['landmask']

state_count_fut = da.read_nc('/p/projects/ikiimp/HAPPI/HAPPI_Peter/data/'+model+'/state_stats/pr_*'+scenario+'*')
state_count_hist = da.read_nc('/p/projects/ikiimp/HAPPI/HAPPI_Peter/data/'+model+'/state_stats/pr_*All-Hist*')

hist_files=sorted(glob.glob(in_path+'All-Hist/pr/*_All-Hist*state.nc'))

# get seasonal indices
seasons={'MAM':{'months':[3,4,5],'index':0}, 'JJA':{'months':[6,7,8],'index':1}, 'SON':{'months':[9,10,11],'index':2}, 'DJF':{'months':[12,1,2],'index':3}}
nc_in=da.read_nc(hist_files[0])
if 'calendar' in nc_in['time'].attrs.keys():
	datevar = num2date(nc_in['time'].values,units = nc_in['time'].units,calendar = nc_in['time'].calendar)
else:
	datevar = num2date(nc_in['time'].values,units = nc_in['time'].units)
month=np.array([int(str(date).split("-")[1])	for date in datevar[:]])
season=month.copy()*np.nan
for sea in seasons.keys():
	season[np.where((month==seasons[sea]['months'][0]) | (month==seasons[sea]['months'][1]) | (month==seasons[sea]['months'][2]) )[0]]=seasons[sea]['index']
sea_indices = {}
for sea in range(4):
	sea_indices[sea] = np.array([],np.int)
	for i in range(100):
		sea_indices[sea] = np.append(sea_indices[sea],np.where(season==sea)[0] + i*season.shape[0])

nc = Dataset(hist_files[0])
lat = nc.variables['lat'][:]
lat_nh = lat[lat>0]
for file_name in hist_files:
	dataset = Dataset(file_name.replace('All-Hist',scenario.replace('Future','Artificial-'+str(seed))), 'w', format='NETCDF4_CLASSIC')
	lat_d = dataset.createDimension('lat', len(lat))
	lon_d = dataset.createDimension('lon', None)
	time_d = dataset.createDimension('time', nc.dimensions['time'].size)

	time_v = dataset.createVariable('time', np.float64, ('time',)); time_v[:] = nc.variables['time'][:]
	dataset.variables['time'].units = nc.variables['time'].units
	dataset.variables['time'].calendar = nc.variables['time'].calendar

	lat_v = dataset.createVariable('lat', np.float32,('lat',)); lat_v[:] = lat
	lon_v = dataset.createVariable('lon', np.float32,('lon',))

	for key in ['dry','5mm']:
		globals()[key] = dataset.createVariable(key, np.int8,('time','lat','lon'))

	dataset.close()

lat_nh = lat[lat>0]
lat_i = np.where(lat>0)[0]
for yi,y in zip(lat_i,lat_nh):
	hist_merge = {}
	nc = Dataset(hist_files[0])
	hist_merge['dry'] = nc['dry'][:,yi,:]
	hist_merge['5mm'] = nc['5mm'][:,yi,:]
	hist_merge['run_id'] = np.zeros([nc.dimensions['time'].size]) * 0

	for i_run,file_name in enumerate(hist_files[1:]):
		print(file_name)
		nc = Dataset(file_name)
		hist_merge['dry'] = np.concatenate((hist_merge['dry'], nc['dry'][:,yi,:]))
		hist_merge['5mm'] = np.concatenate((hist_merge['5mm'], nc['5mm'][:,yi,:]))
		hist_merge['run_id'] = np.concatenate((hist_merge['run_id'], np.zeros([nc.dimensions['time'].size]) + i_run+1))

	for xi,x in enumerate(nc.variables['lon'][:]):
		print(xi)
		orig_dry = hist_merge['dry'][:,xi].copy()
		orig_wet = hist_merge['5mm'][:,xi].copy()

		arti_dry = hist_merge['dry'][:,xi].copy()
		arti_wet = hist_merge['5mm'][:,xi].copy()

		if landmask[y,x]!=0:

			for sea,season_name in {0:'MAM',1:'JJA',2:'SON',3:'DJF'}.items():

				dry_change = int(state_count_fut['dry'][season_name,y,x] - state_count_hist['dry'][season_name,y,x])
				wet_change = int(state_count_fut['5mm'][season_name,y,x] - state_count_hist['5mm'][season_name,y,x])

				if dry_change < 0:
					# remove dry states
					candidates = np.where(arti_dry[sea_indices[sea]]==1)[0]
					random_ = np.array(random.sample(candidates,-1*dry_change))
					arti_dry[sea_indices[sea][random_]] = 0

				if wet_change < 0:
					# remove wet states
					candidates = np.where(arti_wet[sea_indices[sea]]==1)[0]
					random_ = np.array(random.sample(candidates,-1*wet_change))
					arti_wet[sea_indices[sea][random_]] = 0

				if dry_change > 0:
					# add dry states
					candidates = np.where((arti_wet[sea_indices[sea]]!=1) & (arti_dry[sea_indices[sea]]!=1))[0]
					random_ = np.array(random.sample(candidates,dry_change))
					arti_dry[sea_indices[sea][random_]] = 1

				if wet_change > 0:
					# add wet states
					candidates = np.where((arti_wet[sea_indices[sea]]!=1) & (arti_dry[sea_indices[sea]]!=1))[0]
					random_ = np.array(random.sample(candidates,wet_change))
					arti_wet[sea_indices[sea][random_]] = 1

				if np.sum(arti_dry[sea_indices[sea]]) - np.sum(orig_dry[sea_indices[sea]]) != dry_change:
					asdasd
				if np.sum(arti_wet[sea_indices[sea]]) - np.sum(orig_wet[sea_indices[sea]]) != wet_change:
					asdasd

				gc.collect()

			if np.sum(arti_dry) - np.sum(orig_dry) != sum(state_count_fut['dry'][:,y,x] - state_count_hist['dry'][:,y,x]):
				asdasd
			if np.sum(arti_wet) - np.sum(orig_wet) != sum(state_count_fut['5mm'][:,y,x] - state_count_hist['5mm'][:,y,x]):
				asdasd

		for i_run,file_name in enumerate(hist_files):
			dataset = Dataset(file_name.replace('All-Hist',scenario.replace('Future','Artificial-'+str(seed))), 'a', format='NETCDF4_CLASSIC')

			dataset.variables['dry'][:,yi,xi] = arti_dry[hist_merge['run_id'] == i_run]
			dataset.variables['5mm'][:,yi,xi] = arti_wet[hist_merge['run_id'] == i_run]
			dataset.variables['lon'][xi] = x
			dataset.close()

#


"""
This is a giant list of console commands that deal with and often implement the elements system in the program.
"""

def plugin(kernel, lifecycle=None):
    _ = kernel.translation
    if lifecycle == "postboot":
        init_commands(kernel)

def init_commands(kernel):
    self = kernel.elements

    _ = kernel.translation

    # ==========
    # UNDO/REDO COMMANDS
    # ==========
    @self.console_command(
        "save_restore_point",
    )
    def undo_mark(data=None, **kwgs):
        self.undo.mark()

    @self.console_command(
        "undo",
    )
    def undo_undo(command, channel, _, **kwgs):
        if not self.undo.undo():
            # At bottom of stack.
            channel("No undo available.")
            return
        self.validate_selected_area()
        channel(f"Undo: {self.undo}")
        self.signal("refresh_scene", "Scene")
        self.signal("rebuild_tree")

    @self.console_command(
        "redo",
    )
    def undo_redo(command, channel, _, data=None, **kwgs):
        if not self.undo.redo():
            channel("No redo available.")
            return
        channel(f"Redo: {self.undo}")
        self.validate_selected_area()
        self.signal("refresh_scene", "Scene")
        self.signal("rebuild_tree")

    @self.console_command(
        "undolist",
    )
    def undo_list(command, channel, _, **kwgs):
        for entry in self.undo.undolist():
            channel(entry)

    # --------------------------- END COMMANDS ------------------------------