import pickle
from collections import deque
from functools import reduce
from math import pi
from math import sqrt

import gym
import torch
import torch.nn.functional as F
import torch.optim as optim

from base.control import Control
from base.environment import Environment
from dataset.control_dataset import ControlDataset
from nn.expert_policy import long_term_MPC
from nn.simple_action import SimpleNetwork
from utils.geo import to_relative_coords

N = 30
INF = float('inf')
MAX_steer = pi
MIN_steer = -pi
MAX_a = 10
MIN_a = -10
MAX_v = 100
MIN_v = 0

class Test:
    def __init__(self, env: Environment, control_layer=None):
        self.env = env
        self.dt = self.env.dt
        self.long_term_planning_length = self.env.long_term_planning_length
        self.control_layer = control_layer

    def run(self):
        frame = 0

        track_history, traj_history = dict(), dict()
        track_history['x'], track_history['y'] = [], []
        traj_history['x'], traj_history['y'] = [], []
        track = self.env.get_track()

        self.control_layer.eval()
        self.env.reset()
        done = False
        curr_pos = self.env.get_car().get_position()
        prev_pos = (curr_pos.x - 10, curr_pos.y + 10)
        with torch.no_grad():
            while not done:
                print("Frame: {}".format(frame))
                long_term_xs, long_term_ys = self.env.calc_long_term_targets()
                car_x, car_y, _, _, theta = self.env.observe()

                ind = self.env.get_current_waypoint_index() - 2
                track_history['x'].append(track[max(0, ind)])
                track_history['y'].append(track[max(0, ind)])
                traj_history['x'].append(car_x)
                traj_history['y'].append(car_y)

                rel_long_term_targets = to_relative_coords(car_x, car_y, theta, long_term_xs, long_term_ys)
                control_traj = self.control_layer(torch.FloatTensor(rel_long_term_targets).cuda()).detach().cpu().numpy()

                _, _, done, _ = self.env.step(Control(control_traj[0], control_traj[1], control_traj[2]))

                curr_pos = self.env.get_car().get_position()
                dist = (curr_pos.x - prev_pos[0]) ** 2 + (curr_pos.y - prev_pos[1]) ** 2
                print(dist)
                if dist < 5 * 1e-4:  # Hyper parameter
                    print("Out of boundary!")
                    break
                prev_pos = (curr_pos.x, curr_pos.y)

                self.env.render()
                frame += 1

        with open("../saved/episode.pkl", "wb") as f:
            pickle.dump({"track": track_history, "traj": track_history})

class ControlLayerLearner:

    def __init__(self, env: Environment, lr=0.01):
        self.env = env
        self.dt = self.env.dt
        self.long_term_planning_length = self.env.long_term_planning_length
        self.expert = long_term_MPC

        self.control_layer = SimpleNetwork(self.long_term_planning_length * 2, self.long_term_planning_length * 3).cuda()
        self.optimizer = optim.Adam(self.control_layer.parameters(), lr=lr)

        self.init_dataset_size = 20000
        self.dataset_prime_size = 500
        self.M = 1
        self.waypoints_threshhold = 1e-3
        self.epoches = 4000

    def init_dataset(self, save=True):
        dataset = ControlDataset()
        cnt = 0
        while dataset.size() < self.init_dataset_size:
            done = False
            self.env.reset()
            new_dataset = ControlDataset()
            curr_pos = self.env.get_car().get_position()
            prev_pos = (curr_pos.x - 10, curr_pos.y + 10)
            out_of_boundary = False

            targets = deque(maxlen=self.long_term_planning_length)
            controls = deque(maxlen=self.long_term_planning_length)

            while not out_of_boundary and not done and dataset.size() < self.init_dataset_size:
                # Input
                target_xs, target_ys = self.env.calc_long_term_targets()
                car_x, car_y, _, _, theta = self.env.observe()
                rel_targets = to_relative_coords(car_x, car_y, theta, target_xs, target_ys)
                targets.append(rel_targets)

                # Output
                control, expert_long_term_xs, expert_long_term_ys = self.expert(self.env.car, target_xs, target_ys, self.dt)
                controls.append(control)

                if len(controls) == N:
                    target0 = targets[0]

                    control_traj = tuple(reduce(lambda x, y: x + y, [c.to_tuple() for c in controls]))
                    new_dataset.record(target0, control_traj)

                    print("Dataset size: {}".format(cnt))
                    cnt += 1

                # Take control
                obs, _, done, _ = self.env.step(control)

                # Check if in lane
                curr_pos = self.env.get_car().get_position()
                dist = (curr_pos.x - prev_pos[0]) ** 2 + (curr_pos.y - prev_pos[1]) ** 2
                if dist < 1e-4:
                    out_of_boundary = True
                    print("Out of boundary!")
                prev_pos = (curr_pos.x, curr_pos.y)

            dataset += new_dataset

        if save:
            dataset.save()

        return dataset

    def _measure_action_diff(self, pnts1, pnts2):
        return sqrt(sum([(a - b) ** 2 for a, b in zip(pnts1, pnts2)]))

    def _train(self, dataset: ControlDataset):
        self.control_layer.train()
        epoch = 0
        while epoch < self.epoches:
            batch = dataset.fetch_random_batch()
            if not batch:
                break
            inputs, outputs = batch
            inputs = torch.FloatTensor(inputs).cuda()
            outputs = torch.FloatTensor(outputs).cuda()

            outputs_pred = self.control_layer(inputs)
            loss = F.mse_loss(outputs, outputs_pred)
            # if not epoch % 100:
            print("Epoch {}, loss: {}".format(epoch, loss))

            self.optimizer.zero_grad()
            loss.backward()
            self.optimizer.step()

            epoch += 1

    def _test(self):
        test = Test(self.env, self.control_layer)
        test.run()

    def run_dagger(self, dataset_path=None):

        # Build Dataset
        if dataset_path:
            dataset = ControlDataset()
            dataset.load(dataset_path)
        else:
            dataset = self.init_dataset()
        print("Done init")

        round = 0
        while True:
            # Train Policy NN with D
            self._train(dataset)
            self.save("../saved/action/nn_policy_{}.h5".format(round))
            return

            # Run Policy NN + label with LT-MPC
            dataset_prime = ControlDataset()
            step = 0
            curr_pos = self.env.get_car().get_position()
            prev_pos = (curr_pos.x - 10, curr_pos.y + 10)
            print("Round {}".format(round))

            # Collect new data
            while dataset_prime.size() < self.dataset_prime_size:
                self.env.reset()
                done = False
                out_of_boundary = False
                while not out_of_boundary and not done and dataset_prime.size() < self.dataset_prime_size:
                    # Make input
                    long_term_xs, long_term_ys = self.env.calc_long_term_targets()

                    car_x, car_y, _, _, theta = self.env.observe()
                    rel_long_term_waypoints = to_relative_coords(car_x, car_y, theta, long_term_xs, long_term_ys)

                    # NN plan
                    nn_action = self.action_layer(
                        torch.FloatTensor(rel_long_term_waypoints).cuda()).detach().cpu().numpy()

                    # DAgger
                    if not step % self.M:
                        expert_action, expert_xs, expert_ys = self.expert(self.env.car, long_term_xs, long_term_ys,
                                                                          self.dt)

                        diff = self._measure_action_diff(expert_action.to_tuple(), nn_action.to_tuple())
                        if diff > self.waypoints_threshhold:
                            dataset_prime.record(nn_action, rel_long_term_waypoints, rel_long_term_waypoints)

                        if not dataset_prime.size() % 100:
                            print("nn action: {}, expert action: {}".format(nn_action, expert_action))
                            print("New item: {}, Difference: {}\n\n".format(dataset_prime.size(), diff))

                    _, _, done, _ = self.env.step(nn_action)

                    # Stop if out of boundary
                    curr_pos = self.env.get_car().get_position()
                    dist = (curr_pos.x - prev_pos[0]) ** 2 + (curr_pos.y - prev_pos[1]) ** 2
                    if dist < 5 * 1e-4:  # Hyper parameter
                        print("Out of boundary!")
                        break
                    prev_pos = (curr_pos.x, curr_pos.y)
                    step += 1

            round += 1
            self._test()

            self.save("./saved/action/nn_policy_{}.h5".format(round))
            print("Model saved\n\n" + "=" * 50)

            # add D' to D
            dataset += dataset_prime

    def save(self, save_path):
        torch.save(self.control_layer.state_dict(), save_path)

if __name__ == '__main__':
    env = gym.make('CarRacing-v0')
    env = Environment(env=env, FPS=50.0)

    model_dict = "../saved/action/nn_policy_0.h5"
    control_layer = SimpleNetwork(60, 90).cuda()
    control_layer.load_state_dict(torch.load(model_dict))

    test = Test(env, control_layer)
    test.run()

    # dagger = ControlLayerLearner(env)
    # # dagger.run_dagger()
    # dagger.run_dagger('../cache/control_dataset.pkl')
    # # dagger.run_dagger("action_dataset.pkl")


from process_data import files_utils, mesh_utils
from custom_types import *
from options import GtOptions
import pickle
import os
import constants as const
from models.factory import Logger
from models.chamfer import ChamferLoss

class GroundTruthGenerator:

    @staticmethod
    def gravity_loss(mesh: T_Mesh, ds: mesh_utils.VerticesDS) -> T:
        vs, _ = mesh
        vs_ne = vs[ds.vertex2vertex] * ds.vertex2faces_ma[:, :, None]
        diff = (vs - vs_ne.sum(1) / ds.vs_degree[:, None]).abs()
        gravity_loss = diff.sum(1).mean()
        return gravity_loss

    @staticmethod
    def local_edge_entropy(mesh: T_Mesh) -> T:
        vs, faces = mesh
        vs_faces = vs[faces]
        lengths = list(map(lambda i: (vs_faces[:, (i + 1) % 3] - vs_faces[:, i]).norm(2, 1).unsqueeze(1), range(3)))
        lengths = torch.cat(lengths, 1)
        lengths /= lengths.sum(1)[:, None]
        negative_entropy = (lengths * torch.log(lengths)).sum(1)
        return negative_entropy.mean()

    @property
    def refinement(self) -> bool:
        return self.opt.num_levels == 0

    def __init__(self, opt: GtOptions, device: D):
        self.opt = opt
        self.level = self.opt.start_level
        self.device = device
        self.chamfer = ChamferLoss(device)
        self.scales = self.load_scales()
        self.target_mesh: Union[T_Mesh, N] = None
        self.target_transform = None
        self.source_mesh: Union[T_Mesh, N] = None
        self.ds_source: Union[mesh_utils.VerticesDS, N] = None
        self.logger = Logger(self.opt)

    def update_target(self):
        if (len(self.opt.switches) == 0 or self.opt.switches[-1] < self.level) and self.target_mesh is None:
            self.target_mesh = mesh_utils.load_mesh(f'{const.RAW_MESHES}/{self.opt.mesh_name}')
            self.target_mesh, self.target_transform = mesh_utils.to_unit_cube(self.target_mesh)

        elif self.level == 0:
            self.target_mesh = mesh_utils.load_mesh(f'{const.RAW_MESHES}/{self.opt.mesh_name}_0')
            self.target_mesh, self.target_transform = mesh_utils.to_unit_cube(self.target_mesh)

        elif self.level in self.opt.switches:
            self.target_mesh = mesh_utils.load_mesh(f'{const.RAW_MESHES}/{self.opt.mesh_name}_{self.level}')
            self.target_mesh = (self.target_mesh[0] - self.target_transform[0][None, :]) * self.target_transform[1], self.target_mesh[1]
            self.opt.gamma_edge_global = self.opt.gamma_edge_local = 0
        self.target_mesh = mesh_utils.to(self.target_mesh, self.device)

    def adjust_edge_scale(self) -> T_Mesh:
        if len(self.scales) == 0:
            mean_length = mesh_utils.edge_lengths(self.source_mesh,self.ds_source.edges_ind).mean().item()
            self.scales.append(1 / mean_length)
        else:
            self.scales.append(self.scales[0] * 2 ** self.level)
        return self.source_mesh[0] / (2 ** self.level), self.source_mesh[1]

    def triangulation_iter(self):

        def global_edge_loss():
            return mesh_utils.edge_lengths(self.source_mesh, self.ds_source.edges_ind).std()

        def local_edge_loss():
            return self.local_edge_entropy(self.source_mesh)

        def vs_loss():
            return self.gravity_loss(self.source_mesh, self.ds_source)

        loss = 0
        to_log = []
        for gamma, loss_func, name in zip(self.opt.triangulation_weights, [global_edge_loss, local_edge_loss, vs_loss],
                                          ['e_g', 'e_l', 'gravity',]):
            if gamma != 0:
                cur_loss = loss_func()
                loss += gamma * cur_loss
                to_log += [name, cur_loss]
        return loss, to_log

    def cp_iter(self, mesh: T_Mesh, *args):
        mcp_s2t, mcp_t2s = args
        distances_s2t = mcp_s2t(self.target_mesh, mesh[0]).mean()
        distances_t2s = mcp_t2s(mesh, self.target_mesh[0]).mean()
        loss = self.opt.gamma_distance_s2t * distances_s2t + self.opt.gamma_distance_t2s * distances_t2s
        return loss, ('d_s2t', distances_s2t, 'd_t2s', distances_t2s)

    def ch_iter(self):
        sampled_source = mesh_utils.sample_on_mesh(self.source_mesh, self.opt.num_samples[self.level])
        # sampled_target = mesh_utils.sample_on_sphere(self.target_mesh[0], self.opt.num_samples[self.level], self.device)
        sampled_target = mesh_utils.sample_on_mesh(self.target_mesh, self.opt.num_samples[self.level])
        chamfer_loss = self.chamfer(sampled_source, sampled_target)
        ch_loss = 0
        to_log = []
        for gamma, loss, name in zip(self.opt.chamfer_weights,
                                     chamfer_loss, ['dis_s2t', 'dis_t2s', 'n_s2t', 'n_t2s']):
            if gamma != 0:
                ch_loss += gamma * loss
                to_log += [name, loss]

        return ch_loss, to_log

    def optimize(self) -> T_Mesh:
        # mcp_s2t = MeshClosestPoint(self.target_mesh, self.source_mesh[0], self.ds_target).to(self.device)
        # mcp_t2s = MeshClosestPoint(self.source_mesh, self.target_mesh[0], self.ds_source).to(self.device)
        self.source_mesh[0].requires_grad = True
        optimizer = Optimizer([self.source_mesh[0]], lr=self.opt.lr)
        for i in range(self.opt.level_iters[self.level]):
            for iters, optim_func in zip([self.opt.triangulation_iters, self.opt.ch_iters], [self.triangulation_iter,
                                                                                self.ch_iter]):
                for _ in range(iters):
                    optimizer.zero_grad()
                    loss, log = optim_func()
                    if type(loss) is not int:
                        loss.backward()
                        optimizer.step()
                    self.logger.stash_iter(*log)
            self.logger.reset_iter()
        return (self.source_mesh[0].detach(), self.source_mesh[1])

    def load_scales(self) -> List:
        if os.path.isfile(f'{self.opt.cp_folder}/{self.opt.mesh_name}_scales.pkl'):
            with open(f'{self.opt.cp_folder}/{self.opt.mesh_name}_scales.pkl', 'rb') as f:
                scales = pickle.load(f)
            scales = scales[:self.level]
        else:
            scales = []
        return scales

    def save_scales(self):
        with open(f'{self.opt.cp_folder}/{self.opt.mesh_name}_scales.pkl', 'wb') as f:
            pickle.dump(self.scales, f, pickle.HIGHEST_PROTOCOL)

    def between_levels(self):
        self.logger.start()
        self.update_target()
        if self.source_mesh is None:
            last_mesh_path = f'{self.opt.cp_folder}/{self.opt.mesh_name}_level{self.level - 1 + self.refinement:02d}.obj'
            if self.level > 0 and os.path.isfile(last_mesh_path):
                self.source_mesh = mesh_utils.to(mesh_utils.load_mesh(last_mesh_path), self.device)
                self.source_mesh = self.source_mesh[0] * (2 ** self.level), self.source_mesh[1]
                self.target_mesh = self.target_mesh[0] * (2 ** self.level), self.target_mesh[1]
            else:
                mesh_path = f'{const.RAW_MESHES}/{self.opt.mesh_name}_template.obj'
                if not os.path.isfile(mesh_path) or not self.opt.pre_template:
                    # mesh_path = f'{const.RAW_MESHES}/icosahedron.obj'
                    self.source_mesh = mesh_utils.load_real_mesh(self.opt.template_name, self.opt.template_start, False)
                else:
                    self.source_mesh = mesh_utils.load_mesh(mesh_path)
                self.source_mesh = mesh_utils.to(mesh_utils.to_unit_cube(self.source_mesh)[0], self.device)
                scale = 1 / mesh_utils.edge_lengths(self.source_mesh).mean().item()
                self.target_mesh = self.target_mesh[0] * scale, self.target_mesh[1]
                self.source_mesh = self.source_mesh[0] * scale, self.source_mesh[1]
                self.target_transform = self.target_transform[0], self.target_transform[1] * scale

                if self.opt.template_start > 0 or os.path.isfile(mesh_path):
                    mesh_utils.export_mesh(self.source_mesh, f'{self.opt.cp_folder}/{self.opt.mesh_name}_template.obj')
        if self.level != 0 and not self.refinement:
            self.source_mesh = mesh_utils.Upsampler(self.source_mesh)(self.source_mesh)
        self.ds_source = mesh_utils.VerticesDS(self.source_mesh).to(self.device)

        self.save_scales()

    def generate_ground_truth_meshes(self):
        files_utils.init_folders(self.opt.cp_folder + '/')
        for i in range(self.opt.start_level, self.opt.start_level + self.opt.num_levels + self.refinement):
            self.between_levels()
            self.source_mesh = self.optimize()
            scaled_mesh = self.adjust_edge_scale()
            self.source_mesh = self.source_mesh[0] * 2, self.source_mesh[1]
            self.target_mesh = self.target_mesh[0] * 2, self.target_mesh[1]
            self.target_transform = self.target_transform[0], self.target_transform[1] * 2
            mesh_utils.export_mesh(scaled_mesh, f'{self.opt.cp_folder}/{self.opt.mesh_name}_level{self.level:02d}.obj')
            self.logger.stop(False)
            self.level += 1
        self.save_scales()

if __name__ == '__main__':
    device_ = CUDA(0)
    opt_ = GtOptions()
    args = GtOptions(online_demo=True)
    args.fill_args(tag='demo', mesh_name='cloud', template_name='sphere', num_levels=6)
    gt_gen = GroundTruthGenerator(args, CUDA(0))
    # gt_gen = GroundTruthGenerator(opt_, device_)
    # gt_gen.generate_ground_truth_meshes()


import sys
from rave_defines import UTF8, ODIM_SOURCE_FILE
import xml.etree.ElementTree as ET

## Dictionaries containing look-ups for identifiers except CTY.
# WMO, RAD, PLC, and SOURCE all use the NOD as the look-up
# NOD uses the WMO number as the look-up
# CCCC will be the same for all radars from a given country, so there'll be
# a lot of redundancy, but this is needed to create Odyssey file strings.
NOD, WMO, RAD, PLC, CCCC, WIGOS = {None:None}, {None:None}, {None:None}, {None:None}, {None:None}, {None:None}
SOURCE = {None:None}

initialized = 0

# Hack to come around string handling differences between py3 and py27.
# We might consider go all-in on unicode handling but that will require some time.
use_source_encoding=False
if sys.version_info < (3,):
    use_source_encoding=True

## Initializer. Reads XML and puts the values into dictionaries.
# Because all radars must have a NOD identifier, the other identifiers are looked up
# based on NOD.
def init():
    global initialized
    if initialized: return

    O = ET.parse(ODIM_SOURCE_FILE)
    DB = O.getroot()
    for country in list(DB):
        cccc, org = country.attrib["CCCC"], country.attrib["org"]
        for radar in list(country):
            nod = radar.tag
            CCCC[nod] = cccc
            keys = radar.attrib.keys()
            if "wmo" in keys:
                wmo = radar.attrib["wmo"]
                WMO[nod] = wmo
            else:
                wmo = None
            if "rad" in keys:
                rad = radar.attrib["rad"]
                RAD[nod] = rad
            else:
                rad = None
            if "plc" in keys:
                plc = radar.attrib["plc"]
                PLC[nod] = plc
            else:
                plc = None
            if "wigos" in keys:
                wigos = radar.attrib["wigos"]
                WIGOS[nod] = wigos
            else:
                wigos = None

            if wmo not in ("00000", None):
                NOD[wmo] = nod
                SOURCE[nod] = u"NOD:%s" % nod
                if wmo: SOURCE[nod] += ",WMO:%s" % wmo
                if rad: SOURCE[nod] += ",RAD:%s" % rad
                if plc: SOURCE[nod] += ",PLC:%s" % plc
                if wigos: SOURCE[nod] += ",WIGOS:%s" % wigos
            else:
                SOURCE[nod] = u"NOD:%s" % nod
                if rad: SOURCE[nod] += ",RAD:%s" % rad
                if org and wmo!=None: SOURCE[nod] += ",ORG:%s" % org
                if plc: SOURCE[nod] += ",PLC:%s" % plc
                if wigos: SOURCE[nod] += ",WIGOS:%s" % wigos
    initialized = 1

init()

## One-time function, so read radar-db from text file.
# @param filename string of the input file to read
# @ param xmlfile string of the output XML file to write. Defaults to \ref rave_defines.ODIM_SOURCE_FILE
def text2Element(filename, xmlfile=ODIM_SOURCE_FILE):
    import __builtin__
    from rave_IO import prettyprint

    E = R = None

    fd = open(filename)
    LINES = fd.readlines()
    LINES = LINES[0].split("\r")
    fd.close()

    ALL = ET.Element("radar-db", {"author" : "Daniel Michelson"})

    for L in LINES:
        l = L.split('\t')
        if len(l) == 3:
            if E:
                ALL.append(E)
            org, rad_prefix, country = l
            E = ET.Element(country, {"org":org})
        elif len(l) == 5:
            CCCC, nr, wmo, nod, plc = l
            E.attrib["CCCC"] = CCCC
            R = ET.Element(nod, {"wmo":wmo, "rad":"%s%s" % (rad_prefix,nr),
                                 "plc":plc.decode('utf-8')})
            E.append(R)
        else:
            print("FAILED to process %s" % l)

    ALL.append(E)

    fd = __builtin__.open(xmlfile, 'w')
    sys.stdout = fd
    print("<?xml version='1.0' encoding='%s'?>" % UTF8)
    prettyprint(ALL)
    fd.close()
    sys.stdout = sys.__stdout__

class ODIM_Source:
    ## Initializer
    # @param src string containing a '/what/source' attribute
    def __init__(self, src=None):
        self.source = src
        if not isinstance(self.source,bytes) and self.source is not None:
          self.source = bytes(self.source, UTF8)
        self.wmo = self.nod = self.rad = self.plc = self.org = self.cty = self.cmt = self.wigos = None
        if self.source: self.split_source()

    ## Splits the input string into identifier values
    def split_source(self):
        split = self.source.split(b',')
        for s in split:
            prefix, value = s.split(b':')
            prefix = prefix.lower()  # safety precaution in case someone changes case in their files
            if   prefix == b'wmo': self.wmo = value.decode(UTF8)  # Keep this as a string!
            elif prefix == b'rad': self.rad = value.decode(UTF8)
            elif prefix == b'plc': self.plc = value.decode(UTF8)
            elif prefix == b'nod': self.nod = value.decode(UTF8)
            elif prefix == b'org': self.org = value.decode(UTF8)
            elif prefix == b'cty': self.cty = value.decode(UTF8)
            elif prefix == b'cmt': self.cmt = value.decode(UTF8)
            elif prefix == b'wigos': self.wigos = value.decode(UTF8)

    def __str__(self):
        return "ODIM_Source(nod=%s, wmo=%s, rad=%s, plc=%s, org=%s, cty=%s, cmt=%s, wigos=%s" % \
            (self.nod or "", self.wmo or "", self.rad or "", self.plc or "", self.org or "", self.cty or "", self.cmt or "", self.wigos or "")

## Convenience function. Gets the NOD identifier from /what/source .
# Assumes that the NOD is there or can be looked up based on the WMO identifier.
# If WMO isn't there either, then a 'n/a' (not available) is returned.
# @param obj input SCAN or PVOL object
# @return the NOD identifier or 'n/a'
def NODfromSource(obj):
  S = ODIM_Source(obj.source)
  if S.nod: return S.nod
  else:
    try:
      return NOD[S.wmo]
    except KeyError:
      return 'n/a'

## Convenience function. Checks and, if necessary, reformats a complete /what/source attribute .
# Doesn't return anything.
# @param inobj input SCAN or PVOL object
def CheckSource(inobj):
    S = ODIM_Source(inobj.source)
    if not S.nod:
        try:
            S.nod = NOD[S.wmo]
            if SOURCE[S.nod] is not None:
              if use_source_encoding:
                inobj.source = SOURCE[S.nod].encode(UTF8)
              else:
                inobj.source = SOURCE[S.nod]
        except Exception as e:
            import traceback
            traceback.print_exc()

if __name__ == "__main__":
    pass


import gym
import torch
import torch.nn as nn
import matplotlib.pyplot as plt
from Utils import select_action, optimize_model, plot_durations
from ReplayMemory import ReplayMemory
from DQNet import DQNet
from itertools import count

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

env = gym.make('MountainCar-v0')
init_screen = env.reset()

args = {
    "BATCH_SIZE" : 50,
    "GAMMA" : 0.999,
    "EPS_START" : 0.9,
    "EPS_END" : 0.05,
    "EPS_DECAY" : 200,
    "TARGET_UPDATE" : 10
}
n_obs = env.observation_space.shape[0]
n_actions = env.action_space.n

policy_net = DQNet(n_obs, n_actions).to(device)
target_net = DQNet(n_obs, n_actions).to(device)
target_net.load_state_dict(policy_net.state_dict())
target_net.eval()

optimizer = torch.optim.RMSprop(policy_net.parameters())
memory = ReplayMemory(10000)

steps_done = 0

episode_durations = []

num_episodes = 3000
for i_episode in range(num_episodes):
    print("Episode", i_episode)
    state = torch.Tensor(env.reset()).to(device)
    next_state = torch.Tensor(env.reset()).to(device)

    for t in range(3000):
        if i_episode%1 == 0:
            env.render(mode='rgb_array')

        state = next_state.to(device)

        action = select_action(state, steps_done, policy_net, n_actions, args, device)
        next_state, reward, done, _ = env.step(action.item())
        reward = torch.tensor([reward], device=device)
        reward += next_state[0]
        next_state = torch.Tensor(next_state).to(device)

        """
        if not done:
            next_state = next_state - state
        else:
            next_state = None
        """

        memory.push(state, action, next_state, reward)

        optimize_model(policy_net, target_net, memory, optimizer, args, device)
        if done:
            episode_durations.append(t + 1)
            #plot_durations(episode_durations)
            #break

    if i_episode % args["TARGET_UPDATE"] == 0:
        target_net.load_state_dict(policy_net.state_dict())

print('Complete')
env.render()
env.close()
plt.ioff()
plt.show()


import discord
from pymongo import MongoClient
from bson.objectid import ObjectId
import os

client = discord.Client()
cli = MongoClient(os.getenv('MONGO'))
db = cli.heroku_zq5cdk49

bal = db.doc.find_one({'_id': ObjectId('5d5779523f5cc0f1bdd8511a')})
status = db.doc.find_one({'_id': ObjectId('5d5779523f5cc0f1bdd8511b')})
rqtype = db.doc.find_one({'_id': ObjectId('5d5779523f5cc0f1bdd8511c')})
rqdesc = db.doc.find_one({'_id': ObjectId('5d5779523f5cc0f1bdd8511d')})
rqserv = db.doc.find_one({'_id': ObjectId('5d5779523f5cc0f1bdd8511e')})
mess = db.doc.find_one({'_id': ObjectId('5d5779523f5cc0f1bdd8511f')})
slots = db.doc.find_one({'_id': ObjectId('5d5b51f233ba3bc7166344e3')})

typ = {}
version = "v1.2.5"

@client.event
async def on_ready():
    guild = client.get_guild(469591475999604746)
    channel = client.get_channel(612112677166252050)
    await channel.send(f"""<:bfyYes:613851579266760733> Bot started on **{version}**""")
    await client.change_presence(activity=discord.Activity(name=f"""{guild.member_count} members""", type=discord.ActivityType.watching))

@client.event
async def on_member_join(member):
    guild = client.get_guild(469591475999604746)  # Blob-ify
    guild1 = client.get_guild(591038750273044501)  # Pixel Blob Central FLAG!
    if member.guild == guild:
        await client.change_presence(activity=discord.Activity(name=f"""{guild.member_count} members""", type=discord.ActivityType.watching))
        channel = client.get_channel(469591475999604750)
        await channel.send(f""":tada: Hey fellow **blob {member.mention}**, welcome to **Blob-ify**! You're the **{member.guild.member_count}th** blob to join our growing blob community! To get started, please check <#470303845495341057>. In order to request a blob, please check <#526232642425978892>. Have fun! :heart:""")
    elif member.guild == guild1:
        channel = client.get_channel(591038750847533058)
        await channel.send(f""":tada: Hey fellow **blob {member.mention}**, welcome to **{member.guild.name}**! You're the **{member.guild.member_count}th** blob to join our growing blob community! Have fun! :heart:""")

@client.event
async def on_member_remove(member):
    guild = client.get_guild(469591475999604746)
    if member.guild == guild:
        await client.change_presence(activity=discord.Activity(name=f"""{guild.member_count} members""", type=discord.ActivityType.watching))

@client.event
async def on_message(message):
    guild = client.get_guild(469591475999604746)  # Blob-ify
    lower = message.content.lower()
    split = lower.split(" ")
    if message.author.id not in typ.keys():
        typ[message.author.id] = 0
    if str(message.author.id) not in status.keys():
        status[str(message.author.id)] = 0
    if str(message.author.id) not in bal.keys():
        bal[str(message.author.id)] = 0
    if message.author.guild != guild:
        typ[message.author.id] = -1
    if typ[message.author.id] == -1:
        if message.author.guild == guild:
            typ[message.author.id] = 0
    if lower == "cancel":
        if typ[message.author.id] > 0:
            await message.channel.send("<:bfyNo:613851611600781342> **The requested action has been canceled.**")
            typ[message.author.id] = 0
            rqtype[str(message.author.id)], rqdesc[str(message.author.id)], rqserv[str(message.author.id)] = "", "", ""
    elif message.author.id == 292953664492929025:
        if "w.exc" in message.content:
            mem = message.content.split(" ")
            user = mem[1]
            if user not in bal.keys():
                bal[user] = 0
            await message.channel.send("<:bfyYes:613851579266760733> 2 <:blobpoint:577932728033476611> have been added to your account.")
            bal[user] += 2
            channel = client.get_channel(470347448066375681)
            await channel.send(f"""**Bank Update:** Bal of {str(client.get_user(user))} now {bal[user]}""")
    else:
        if typ[message.author.id] <= 0:
            if lower == "w.help":
                embed = discord.Embed(title="Blob Bot Help", description="The full list of W1Z4RD's commands", color=0x0080c0)
                embed.add_field(name="w.request", value="Request a blob")
                embed.add_field(name="w.exchange", value="Exchange 2 BLOB POINTS for 2,500 BLOB COINS")
                embed.add_field(name="w.balance", value="Check your BLOB POINT balance")
                embed.add_field(name="w.request delete", value="Delete your current blob request")
                embed.set_thumbnail(url="https://cdn.discordapp.com/attachments/470304317748805652/581650589423763463/wiz.png")
                embed.set_footer(text=f"""Created by Tri#4823 ~ W1Z4RD {version}""")
                await message.channel.send(content=None, embed=embed)
            elif lower == "w.exchange":
                mem = str(message.author.id)
                truemem = str(message.author)
                if mem not in bal.keys():
                    bal[mem] = 0
                if bal[mem] > 1:
                    await message.channel.send("<:bfyYes:613851579266760733> <@266319920009183242> will complete the transaction within 24 hours.")
                    bal[mem] -= 2
                    channel = client.get_channel(470347448066375681)
                    await channel.send(f"""**Bank Update:** Bal of {truemem} now {bal[mem]}""")
                else:
                    await message.channel.send("<:bfyNo:613851611600781342> You do not have enough <:blobpoint:577932728033476611> to do so.")
            elif lower == "w.request":
                if slots["used"] < slots["max"] or guild.get_role(600678332320710666) in message.author.roles:
                    if status[str(message.author.id)] == 0:
                        embed = discord.Embed(title="W1Z Request Command", description="A full list of all blob types!", color=0x0080c0)
                        embed.set_image(url="https://cdn.discordapp.com/attachments/470304317748805652/624941100418859018/5309c984-4d97-40c1-bbeb-24f5045d5ddf.png")
                        embed.set_thumbnail(url="https://cdn.discordapp.com/attachments/470304317748805652/581650589423763463/wiz.png")
                        embed.set_footer(text=f"""Created by Tri#4823 ~ W1Z4RD {version}""")
                        await message.channel.send(content="__Please respond with the respective number, or `cancel`__", embed=embed)
                        typ[message.author.id] += 1
                    else:
                        await message.channel.send("<:bfyNo:613851611600781342> You currently have a request in the queue. Either wait until the request is done or delete your request to request again. You can also choose to edit your request.")
                else:
                    await message.channel.send("<:bfyNo:613851611600781342> The maximum amount of request slots has been reached. Either wait for a slot to open or boost the server to bypass this.")
            elif lower == "w.balance":
                await message.channel.send(f"""**Your Balance:** {bal[str(message.author.id)]} <:blobpoint:577932728033476611>""")
            elif lower == "w.bal":
                await message.channel.send(f"""**Your Balance:** {bal[str(message.author.id)]} <:blobpoint:577932728033476611>""")
            elif "w.say" == split[0]:
                admin = guild.get_role(471024426356310028)
                if admin in message.author.roles:
                    say = message.content.split(" ", 1)
                    await message.channel.send(f"""{say[1]}""")
                    await message.delete()
                else:
                    await message.channel.send("<:bfyNo:613851611600781342> You do not have the required permissions to use this command.")
            elif "w.add" == split[0]:
                admin = guild.get_role(471024426356310028)
                if admin in message.author.roles:
                    say = message.content.split(" ", 2)
                    user = client.get_user(int(say[1]))
                    if str(user.id) not in bal.keys():
                        bal[str(user.id)] = 0
                    bal[str(user.id)] += int(say[2])
                    await message.channel.send(f"""<:bfyYes:613851579266760733> **{say[2]}bp** has/have been added to {str(user)}'s balance""")
                    channel = client.get_channel(470347448066375681)
                    await channel.send(f"""**Bank Update:** Bal of {str(user)} now {bal[str(user.id)]}""")
                else:
                    await message.channel.send("<:bfyNo:613851611600781342> You do not have the required permissions to use this command.")
            elif "w.remove" == split[0]:
                admin = guild.get_role(471024426356310028)
                if admin in message.author.roles:
                    say = message.content.split(" ", 2)
                    user = client.get_user(int(say[1]))
                    if str(user.id) not in bal.keys():
                        bal[str(user.id)] = 0
                    bal[str(user.id)] -= int(say[2])
                    await message.channel.send(f"""<:bfyYes:613851579266760733> **{say[2]}bp** has/have been removed from {str(user)}'s balance""")
                    channel = client.get_channel(470347448066375681)
                    await channel.send(f"""**Bank Update:** Bal of {str(user)} now {bal[str(user.id)]}""")
                else:
                    await message.channel.send("<:bfyNo:613851611600781342> You do not have the required permissions to use this command.")
            elif "w.slots" == split[0]:
                admin = guild.get_role(471024426356310028)
                if admin in message.author.roles:
                    if "set" == split[1]:
                        slots["max"] = int(split[2])
                        await message.channel.send(f"""<:bfyYes:613851579266760733> Max slots now **{split[2]}**.""")
                    elif "check" == split[1]:
                        await message.channel.send(f"""There are **{slots["used"]} out of {slots["max"]} slots used.**""")
                    elif "forceremove" == split[1]:
                        if slots["used"] > 0:
                            slots["used"] -= 1
                            await message.channel.send(f"""<:bfyYes:613851579266760733> Used slots reduced by 1, now {slots["used"]}.""")
                        else:
                            await message.channel.send("<:bfyNo:613851611600781342> There are no requests in the queue or there are no slots used.")
                    elif "forceadd" == split[1]:
                        slots["used"] += 1
                        await message.channel.send(f"""<:bfyYes:613851579266760733> Forcefully used a slot. Used slots now {slots["used"]}.""")
                else:
                    await message.channel.send("<:bfyNo:613851611600781342> You do not have the required permissions to use this command.")
            elif lower == "w.emojiupdate":
                admin = guild.get_role(471024426356310028)
                if admin in message.author.roles:
                    channel = client.get_channel(578237505770618891)
                    async for message1 in channel.history():
                        await message1.delete()
                    for emoji in guild.emojis:
                        await channel.send(f"""{emoji} ~ `{emoji.name}`""")
                else:
                    await message.channel.send("<:bfyNo:613851611600781342> You do not have the required permissions to use this command.")
            elif "w.request" == split[0]:
                if "delete" == split[1]:
                    if status[str(message.author.id)] > 0:
                        await message.channel.send("Are you sure you would like to delete your request? Your <:blobpoint:577932728033476611> will be refunded. Please `confirm` or `cancel`.")
                        typ[message.author.id] = 5
                    else:
                        await message.channel.send("<:bfyNo:613851611600781342> You currently have no active requests to delete.")
                elif "claim" == split[1]:
                    print()
                elif "submit" == split[1]:
                    print()
                elif "check" == split[1]:
                    stat = status[str(message.author.id)]
                    if stat > 0:
                        embed = discord.Embed(title=f"""Your Request""", color=0x0080c0)
                        embed.add_field(name="Blob Type", value=rqtype[str(message.author.id)])
                        embed.add_field(name="Blob Description", value=rqdesc[str(message.author.id)])
                        embed.add_field(name="Server Blob?", value=rqserv[str(message.author.id)])
                        embed.set_thumbnail(
                            url="https://cdn.discordapp.com/attachments/470304317748805652/581650589423763463/wiz.png")
                        embed.set_footer(text=f"""Created by Tri#4823 ~ W1Z4RD {version}""")
                        if stat == 1:
                            await message.channel.send(content="Your request is **unclaimed**. You can edit it with the `edit` subommand.", embed=embed)
                        elif stat == 2:
                            await message.channel.send(content="Your request was claimed by artist [ARTIST]. The request is no longer able to be edited")
                    else:
                        await message.channel.send("<:bfyNo:613851611600781342> You do not have a request in the queue. Use the `w.request` command to create one.")
                elif "forcedelete" == split[1]:
                    admin = guild.get_role(471024426356310028)
                    if admin in message.author.roles:
                        user = client.get_user(int(split[2]))
                        if status[str(user.id)] > 0:
                            status[str(user.id)] = 0
                            slots["used"] -= 1
                            if rqtype[str(user.id)] == "Animated Blob":
                                bal[str(user.id)] += 6
                            if rqtype[str(user.id)] == "Normal Blob":
                                bal[str(user.id)] += 1
                            elif rqtype[str(user.id)] == "Bongo Cat":
                                bal[str(user.id)] += 7
                            elif rqtype[str(user.id)] == "Peep":
                                bal[str(user.id)] += 3
                            elif rqtype[str(user.id)] == "Animated Peep":
                                bal[str(user.id)] += 8
                            elif rqtype[str(user.id)] == "Full Blob Pack":
                                bal[str(user.id)] += 40
                            elif rqtype[str(user.id)] == "Custom Emoji":
                                bal[str(user.id)] += 10
                            elif rqtype[str(user.id)] == "Custom Emoji Pack":
                                bal[str(user.id)] += 80
                            await message.channel.send(f"""<:bfyYes:613851579266760733> You have forcefully deleted {str(user)}'s request. You may proceed to delete the message in the queue.""")
                            channel = client.get_channel(470347448066375681)
                            await channel.send(f"""**Bank Update:** Bal of {str(user)} now {bal[str(user.id)]}""")
                        else:
                            await message.channel.send("<:bfyNo:613851611600781342> That user has no request in the queue.")
                    else:
                        await message.channel.send("<:bfyNo:613851611600781342> You do not have the required permissions to use this subcommand.")
        elif typ[message.author.id] == 1:
            if "1" in message.content:
                if bal[str(message.author.id)] >= 1:
                    await message.channel.send("__Great Choice! Now, please state what you would like your blob(s) to look like, or say `cancel`.__")
                    rqtype[str(message.author.id)] = "Normal Blob"
                    typ[message.author.id] += 1
                else:
                    await message.channel.send("<:bfyNo:613851611600781342> You do not have enough <:blobpoint:577932728033476611> to request this item. Pick a different item or `cancel`.")
            elif "2" in message.content:
                if bal[str(message.author.id)] >= 6:
                    await message.channel.send("__Great Choice! Now, please state what you would like your blob(s) to look like, or say `cancel`.__")
                    rqtype[str(message.author.id)] = "Animated Blob"
                    typ[message.author.id] += 1
                else:
                    await message.channel.send("<:bfyNo:613851611600781342> You do not have enough <:blobpoint:577932728033476611> to request this item. Pick a different item or `cancel`.")
            elif "3" in message.content:
                if bal[str(message.author.id)] >= 7:
                    await message.channel.send("__Great Choice! Now, please state what you would like your blob(s) to look like, or say `cancel`.__")
                    rqtype[str(message.author.id)] = "Bongo Cat"
                    typ[message.author.id] += 1
                else:
                    await message.channel.send("<:bfyNo:613851611600781342> You do not have enough <:blobpoint:577932728033476611> to request this item. Pick a different item or `cancel`.")
            elif "4" in message.content:
                if bal[str(message.author.id)] >= 3:
                    await message.channel.send("__Great Choice! Now, please state what you would like your blob(s) to look like, or say `cancel`.__")
                    rqtype[str(message.author.id)] = "Peep"
                    typ[message.author.id] += 1
                else:
                    await message.channel.send("<:bfyNo:613851611600781342> You do not have enough <:blobpoint:577932728033476611> to request this item. Pick a different item or `cancel`.")
            elif "5" in message.content:
                if bal[str(message.author.id)] >= 8:
                    await message.channel.send("__Great Choice! Now, please state what you would like your blob(s) to look like, or say `cancel`.__")
                    rqtype[str(message.author.id)] = "Animated Peep"
                    typ[message.author.id] += 1
                else:
                    await message.channel.send("<:bfyNo:613851611600781342> You do not have enough <:blobpoint:577932728033476611> to request this item. Pick a different item or `cancel`.")
            elif "6" in message.content:
                if bal[str(message.author.id)] >= 40:
                    await message.channel.send("__Great Choice! Now, please state what you would like your blob(s) to look like, or say `cancel`.__")
                    rqtype[str(message.author.id)] = "Full Blob Pack"
                    typ[message.author.id] += 1
                else:
                    await message.channel.send("<:bfyNo:613851611600781342> You do not have enough <:blobpoint:577932728033476611> to request this item. Pick a different item or `cancel`.")
            elif "7" in message.content:
                if bal[str(message.author.id)] >= 10:
                    await message.channel.send("__Great Choice! Now, please state what you would like your blob(s) to look like, or say `cancel`.__")
                    rqtype[str(message.author.id)] = "Custom Emoji"
                    typ[message.author.id] += 1
                else:
                    await message.channel.send("<:bfyNo:613851611600781342> You do not have enough <:blobpoint:577932728033476611> to request this item. Pick a different item or `cancel`.")
            elif "8" in message.content:
                if bal[str(message.author.id)] >= 80:
                    await message.channel.send("__Great Choice! Now, please state what you would like your blob(s) to look like, or say `cancel`.__")
                    rqtype[str(message.author.id)] = "Custom Emoji Pack"
                    typ[message.author.id] += 1
                else:
                    await message.channel.send("<:bfyNo:613851611600781342> You do not have enough <:blobpoint:577932728033476611> to request this item. Pick a different item or `cancel`.")
            else:
                await message.channel.send("<:bfyNo:613851611600781342> That was not a valid response. Send a number from 1 through 8.")
        elif typ[message.author.id] == 2:
            await message.channel.send("__Great! One last thing. Would you like this to be a server blob?__")
            await message.channel.send("Server blobs represent you in the server, and are made into emojis that you can use with Nitro.")
            await message.channel.send("However, only NORMAL BLOB requests can qualify. So what do you say, or `cancel`.")
            rqdesc[str(message.author.id)] = message.content
            typ[message.author.id] += 1
        elif typ[message.author.id] == 3:
            await message.channel.send("Cool! Now please confirm the following details before making your purchase.")
            await message.channel.send("The appropriate amount of <:blobpoint:577932728033476611> will be deducted from your account as listed in <#526232642425978892>.")
            embed = discord.Embed(title="Confirm Information", description="Either `confirm` or `cancel`", color=0x0080c0)
            embed.add_field(name="Blob Type", value=rqtype[str(message.author.id)])
            embed.add_field(name="Blob Description", value=rqdesc[str(message.author.id)])
            embed.add_field(name="Server Blob?", value=message.content)
            embed.set_thumbnail(url="https://cdn.discordapp.com/attachments/470304317748805652/581650589423763463/wiz.png")
            embed.set_footer(text=f"""Created by Tri#4823 ~ W1Z4RD {version}""")
            await message.channel.send(embed=embed)
            rqserv[str(message.author.id)] = message.content
            typ[message.author.id] += 1
        elif typ[message.author.id] == 4:
            if lower == "confirm":
                await message.channel.send("<:bfyYes:613851579266760733> The blob request has been added to the queue!")
                await message.channel.send("You will receive notifications as your blob is being made.")
                await message.channel.send("Send any image references to <@266319920009183242>.")
                embed = discord.Embed(title=f"""{message.author}""", color=0x0080c0)
                embed.add_field(name="Blob Type", value=rqtype[str(message.author.id)])
                embed.add_field(name="Blob Description", value=rqdesc[str(message.author.id)])
                embed.add_field(name="Server Blob?", value=rqserv[str(message.author.id)])
                embed.set_thumbnail(url="https://cdn.discordapp.com/attachments/470304317748805652/581650589423763463/wiz.png")
                embed.set_footer(text=f"""Created by Tri#4823 ~ W1Z4RD {version}""")
                channel = client.get_channel(611768294315130891)
                await channel.send(content=f"""**Incoming Blob Request!** From {message.author.mention}""", embed=embed)
                typ[message.author.id] = 0
                status[str(message.author.id)] = 1
                slots["used"] += 1
                if rqtype[str(message.author.id)] == "Animated Blob":
                    bal[str(message.author.id)] -= 6
                elif rqtype[str(message.author.id)] == "Normal Blob":
                    bal[str(message.author.id)] -= 1
                elif rqtype[str(message.author.id)] == "Bongo Cat":
                    bal[str(message.author.id)] -= 7
                elif rqtype[str(message.author.id)] == "Peep":
                    bal[str(message.author.id)] -= 3
                elif rqtype[str(message.author.id)] == "Animated Peep":
                    bal[str(message.author.id)] -= 8
                elif rqtype[str(message.author.id)] == "Full Blob Pack":
                    bal[str(message.author.id)] -= 40
                elif rqtype[str(message.author.id)] == "Custom Emoji":
                    bal[str(message.author.id)] -= 10
                elif rqtype[str(message.author.id)] == "Custom Emoji Pack":
                    bal[str(message.author.id)] -= 80
                channel = client.get_channel(470347448066375681)
                await channel.send(f"""**Bank Update:** Bal of {str(message.author)} now {bal[str(message.author.id)]}""")
            else:
                await message.channel.send("<:bfyNo:613851611600781342> That was not a valid response. Please `confirm` or `cancel`.")
        elif typ[message.author.id] == 5:
            if lower == "confirm":
                await message.channel.send("<:bfyYes:613851579266760733> <@266319920009183242> will proceed to delete your request and refund your <:blobpoint:577932728033476611>. At this point you may also start a new request.")
                status[str(message.author.id)] = 0
                typ[message.author.id] = 0
                slots["used"] -= 1
                if rqtype[str(message.author.id)] == "Animated Blob":
                    bal[str(message.author.id)] += 6
                elif rqtype[str(message.author.id)] == "Normal Blob":
                    bal[str(message.author.id)] += 1
                elif rqtype[str(message.author.id)] == "Bongo Cat":
                    bal[str(message.author.id)] += 7
                elif rqtype[str(message.author.id)] == "Peep":
                    bal[str(message.author.id)] += 3
                elif rqtype[str(message.author.id)] == "Animated Peep":
                    bal[str(message.author.id)] += 8
                elif rqtype[str(message.author.id)] == "Full Blob Pack":
                    bal[str(message.author.id)] += 40
                elif rqtype[str(message.author.id)] == "Custom Emoji":
                    bal[str(message.author.id)] += 10
                elif rqtype[str(message.author.id)] == "Custom Emoji Pack":
                    bal[str(message.author.id)] += 80
                channel = client.get_channel(471878672677208084)
                await channel.send(f"""{str(message.author)} has deleted their request.""")
                channel = client.get_channel(470347448066375681)
                await channel.send(f"""**Bank Update:** Bal of {str(message.author)} now {bal[str(message.author.id)]}""")
            else:
                await message.channel.send("<:bfyNo:613851611600781342> That was not a valid response. Please `confirm` or `cancel`.")

    dicts = [bal, status, rqtype, rqdesc, rqserv, mess, slots]
    for d in dicts:
        db.doc.replace_one({'_id': d['_id']}, d, True)

@client.event
async def on_guild_emojis_update(guild0, before, after):
    channel = 0
    if guild0.id == 469591475999604746:
        channel = client.get_channel(570397486141669406)
    emoadd, emoaddname, emoremove, emoremovename, lis, lis2 = "", "", "", "", [], []
    for emoji in before:
        for emoji2 in after:
            lis.append(emoji2.name)
        if emoji.name not in lis:
            emoremove = emoji
            emoremovename = emoji.name
    for emoji in after:
        for emoji2 in before:
            lis2.append(emoji2.name)
        if emoji.name not in lis2:
            emoadd = emoji
            emoaddname = emoji.name
    if emoremove == "":  # If an emoji was added
        await channel.send(f"""<:w1:579473596041265152> **Added** {emoadd} `{emoaddname}`""")
    else:  # If an emoji was removed
        if emoadd == "":  # If an emoji was ONLY removed
            await channel.send(f"""<:w2:579473617134288898> **Removed** `{emoremovename}`""")
        else:  # If an emoji was renamed
            await channel.send(f"""<:w3:579473645706018827> {emoadd} **Renamed** `{emoremovename}` to `{emoaddname}`""")

client.run(os.getenv('TOKEN'))


#! /usr/bin/python3
# -*- coding:utf-8 -*-

class color:
   PURPLE = '\033[95m'
   CYAN = '\033[96m'
   DARKCYAN = '\033[36m'
   BLUE = '\033[94m'
   GREEN = '\033[92m'
   YELLOW = '\033[93m'
   RED = '\033[91m'
   BOLD = '\033[1m'
   ITALIC = '\033[3m'
   UNDERLINE = '\033[4m'
   END = '\033[0m'

if __name__ == '__main__':
    print(color.BOLD + "Hello" + color.BLUE + " world" + color.END
            + color.BOLD + "!" + color.END)


import boto3
from threading import Lock
from botocore.endpoint import MAX_POOL_CONNECTIONS
import botocore.client

def get_caller_identity(client_provider):
    resp = client_provider.get_client("sts").get_caller_identity()
    return resp["UserId"], resp["Account"], resp["Arn"]

class ClientProvider:

    def __init__(
            self,
            account,
            verify=True,
            connect_timeout=5,
            read_timeout=60,
            max_retries=2,
    ):
        self.account = account
        self.verify = verify

        # there is a problem with the read_timeout for big requests
        # the read timeout is reached, and the client retries after sleeping
        # for a while, bad thing is that sleeping increases exponentially, so
        # first is 2s, then 4s, then 8s, then 16s,
        self.client_config = botocore.client.Config(
            connect_timeout=connect_timeout,
            read_timeout=read_timeout,
            retries={'max_attempts': max_retries},
            max_pool_connections=MAX_POOL_CONNECTIONS * 2
        )
        self.client_lock = Lock()
        self.clients = {}

    def get_client(self, service):
        with self.client_lock:
            return self._get_client(service)

    def _get_client(self, service):
        try:
            return self.clients[service]
        except KeyError:
            self.clients[service] = boto3.client(
                service,
                aws_access_key_id=self.account.access_key,
                aws_secret_access_key=self.account.secret_key,
                aws_session_token=self.account.session_token,
                region_name=self.account.region,
                verify=self.verify,
                config=self.client_config,
            )

        return self.clients[service]


def f(x):
    if x==1:
        return False
    for i in range(2,x):
        if x%i==0:
            return False
    return True

list1=[2, 3, 5, 16, 100]
list2=list(filter(f,list1))

print(list2)

#[2, 3, 5]


N, Y = map(int, input().split())
out_x = out_y = out_z = -1
for x in range(N+1):
    for y in range(N+1):
        price = x * 10000 + y * 5000
        if price > Y:
            break
        price = price + (N-x-y) * 1000
        if price == Y:
            out_x = x
            out_y = y
            out_z = N-x-y
            break
    if out_x != -1:
        break
print("{0} {1} {2}".format(out_x, out_y, out_z))


def is_adjacency_matrix(matrix, digraph=False, flow_network=False):
    """Checks if the passed matrix is a valid Adjacency Matrix.
        matrix - matrix which will be examined for being an adjacency matrix
        digraph - boolean whether to check the matrix in case of Digraph object or not
        flow_network - boolean whether to check the matrix in case of FlowNetwork object or not"""

    n = len(matrix)
    for i in range(n):
        if len(matrix[i]) != n:
            return False

    if not flow_network:
        if matrix[0][0] is not None:
            return False
        for i in range(1, n):
            for j in range(0, i):
                if not (digraph or flow_network):
                    if matrix[i][j] != matrix[j][i]:
                        return False
            if matrix[i][i] is not None:
                return False
    else:
        for i in range(n):
            if matrix[i][0][1] or matrix[n-1][i][1] or matrix[i][i][1]:
                return False
            for j in range(n):
                if matrix[i][j][1] and matrix[j][i][1]:
                    return False
    return True

def is_incidence_matrix(matrix):
    """Checks if the passed matrix is a valid Incidence Matrix.
        matrix - matrix which will be examined for being an incidence matrix"""

    n = len(matrix)
    m = len(matrix[0])
    for i in range(n):
        if len(matrix[i]) != m:
            return False
    if m > (n * (n-1) / 2):
        return False
    for j in range(m):
        vertices_in_edge = 0
        first_index = second_index = None
        for i in range(n):
            if matrix[i][j] is not None:
                vertices_in_edge += 1
                if first_index is None:
                    first_index = i
                else:
                    second_index = i
        if vertices_in_edge != 2:
            return False
        for j2 in range(j+1, m):
            if matrix[first_index][j] == matrix[first_index][j2] and matrix[second_index][j] == matrix[second_index][j2]:
                return False

    return True

def is_adjacency_list(adjacency_list):
    """Checks if the passed list/matrix is a valid Adjacency List.
        adjacency_list - list which will be examined for being an adjacency list"""

    n = len(adjacency_list)
    print(adjacency_list)
    for i in range(n):
        if len(adjacency_list[i]) > n-1:
            return False
        copies_checker = []
        for neighbour in adjacency_list[i]:
            if neighbour in copies_checker:
                return False
            if neighbour-1 == i:
                return False
            if i+1 not in adjacency_list[neighbour-1]:
                return False
            copies_checker.append(neighbour)
    return True

"""Dictionary object which maps the representations to their proper validation functions."""
conversion_check_map = {"AM": is_adjacency_matrix,
                        "IM": is_incidence_matrix,
                        "AL": is_adjacency_list}


# -*- coding: utf-8 -*-
# date: 2022-11-21
import requests
import os
from pypinyin import lazy_pinyin
import csv

def name2py(name: str):
    """
    汉字转拼音首字母
    :param name: 汉字
    :return: 首字母（包含数字）
    """
    result = ''
    for i in lazy_pinyin(name):
        result += i[0]
    return result

def download(name, pyname):
    """
    下载m4a音频
    :param name: 需要保存为的文件名
    :param pyname: 拼音首字母，用于下载。
    :return:
    """
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36'}
    m4file = requests.get(
        f'https://jxgc-file.oss-accelerate.aliyuncs.com/yyjs/20200102/{pyname}.m4a', headers=headers)

    with open(f'{name}.m4a', 'wb') as f:
        f.write(m4file.content)

os.chdir(r"C:\Users\Administrator\Downloads\乱世三百年-闲话南北朝之天下归一")
with open('name.csv') as f:
    lines = csv.reader(f)
    for fullname, name in lines:
        pyname = name2py(name)
        download(fullname, pyname)
        print(fullname)

下载一元检史h5音频.py


from rest_framework import serializers
from .models import Payment

class PaymentSerializer(serializers.ModelSerializer):
    amount = serializers.FloatField(default=2000)
    class Meta:
        model = Payment
        fields = ['id', 'xendit_id', 'reference_id', 'amount', 'description',
                  'user', 'status', 'paid_at', 'payment_method', 'expiry_date',
                  'created', 'updated']
        read_only_fields = ['user', 'description', 'status', 'xendit_id',
                            'reference_id', 'payment_method', 'expiry_date', 'paid_at',
                            'created', 'updated']
        extra_kwargs = {
            'amount': {'min_value': 0, 'max_value': None}
        }


fname = input("enter file name: ")
fhandle = open(fname)

dic = dict()
for line in fhandle:
    l = line.rstrip()
    if not line.startswith("From"):
        continue
    else:
        l = l.split()
        address = l[1]
        dic[address] = dic.get(address, 0) + 1
lis = list()
for (k, v) in dic.items():
    lis.append((v, k))
lis = sorted(lis, reverse=True)
print(lis[0][1], lis[0][0])


import matplotlib.pyplot as plt
from scipy.fftpack import fft
from scipy.io import wavfile
from sys import argv
import numpy as np

DTYPES = {
      "float32" : 0
      , "int32" : 32
      , "int16" : 16
      , "uint8" : 8
}

def plotter(fft_func, wavename: str):
    ### read the wav data
    sample_rate, data = wavfile.read(wavename)
    bit = DTYPES[str(data.dtype)] # get the data type
    data = data / (2. ** bit) # normalize the data
    data_len = data.shape[0] # get the total data points and number of channels

    ### plot the time domain
    time_axis = np.arange(0, data_len, 1) / sample_rate  # scale time pointsto seconds
    plt.subplot(2, 1, 1)
    plt.plot(time_axis, data, color='b')
    plt.xlabel("Time (sec)")
    plt.ylabel("Amplitude")

    ### plot the frequency domain (fourier transform)
    N = data_len
    FFT = fft_func(data) # calculate the fft with the specified function
    num_unique_points = int(np.ceil((N+1)/2.0))
    FFT = np.abs(FFT[0:num_unique_points]) # truncate the FFT to the region of the data points
    FFT = (FFT/float(N)) ** 2 # normalize the FFT

    # nyquist fix, see https://web.archive.org/web/20120615002031/http://www.mathworks.com/support/tech-notes/1700/1702.html
    if N % 2 != 0: # odd amount of FFT points
        FFT[1:len(FFT)] = FFT[1:len(FFT)] * 2
    else: # even amount of FFT points
        FFT[1:len(FFT) - 1] = FFT[1:len(FFT) - 1] * 2

    plt.subplot(2, 1, 2)
    frequency_axis = np.arange(0, num_unique_points, 1.0) * (sample_rate / N)
    plt.plot(frequency_axis, 10*np.log10(FFT), color='r')

    plt.xlabel("Frequency (Hz)")
    plt.semilogx(base=10, subsx=[440])
    plt.xlim(xmin=1, xmax=35000)

    plt.ylabel("Energy (dB)")
    plt.ylim(ymin=-60, ymax=0)

    plt.show()

if __name__ == "__main__":
    plotter(fft_func=np.fft.fft, wavename=argv[1])


# encoding:utf-8
import copy
import numpy as np
import random
import bisect #bisect_left　これで二部探索の大小検索が行える
import math

T = int(input())
N = []
W = []

for t in range(T):
    n = int(input())
    w = []
    for i in range(n):
        w = w+[str(input())]
    W.append(w)

def solve(words):
    n = len(words)
    table = [[0 for i in range(n)] for j in range(n)]
    accents = {}
    for i in range(len(words)):
        for j in range(len(words)):
            if i >= j:
                pass
            else:
                count = 0
                for num in range(1,min(len(words[i]),len(words[j]))+1):
                    if words[i][-num] == words[j][-num]:
                        count += 1
                        if count==min(len(words[i]),len(words[j])):
                            accent = words[i][-num:-1]+words[i][-1]
                            accents[accent] = count
                            # print("hoge")
                    else:
                        if count > 0:
                            accent = words[i][1-num:-1]+words[i][-1]
                            accents[accent] = count
                            # print("huge")
                            break
                        else:
                            break
                table[i][j] = count

    ans_1 = 0
    # print(table)
    # print(accents)
    for i in range(n):
        # print(table)
        if max(table[i])>0:
            del_j = table[i].index(max(table[i]))
            for k in range(n):
                table[k][del_j] = 0
                table[del_j][k] = 0
            ans_1 += 1

    ans = len(accents.keys())
    # print(accents)
    # print(ans,ans_1)
    ans = min(ans,ans_1)*2

    return ans

for i in range(T):
    print("Case #"+str(i+1)+": {0}".format(solve(W[i])))


valid_name_1 = 'Иван'
valid_name_2 = 'Ivan'
valid_name_3 = 'иван'
valid_name_4 = 'ivan'
valid_email = 'ivanov@yandex.ru'
valid_phone = '93155555555'
valid_company = 'Only.digital'
invalid_name_1 = ' '
invalid_name_2 = ''
invalid_name_3 = '@#$$%^'
about_project = 'Only.digital прекрасная компания,\n в которой работают над крутыми проектами и решают интересные задачи.\n Я хочу в ней работать!!!'


from pyspark.sql import SparkSession
spark = SparkSession \
    .builder \
    .getOrCreate()
context = spark.sparkContext

# Data Loading into dataframe
data = "ShartankIndiaAllPitches.csv"
df1 = spark.read.format("csv").option("header", "true").load(data)

# Making a table using dataset for querying on that table
df1.createOrReplaceTempView("sharksdetails")
column_names = spark.sql("DESCRIBE sharksdetails")
column_names.show()

# column counts
print("Total columns = ", column_names.count())

# printing all values in particular column
for col in column_names.collect():
    col_names = col['col_name']
    h = spark.sql(f"Select {col_names} from sharksdetails")
    h.show()


from django.urls import path
from blog.views import contact, anasayfa, kategori, yazilarim, detay, yaziEkle, yaziGuncelle, yaziSil, yorumSil

urlpatterns = [
    path("", anasayfa, name="Anasayfa"),
    path("contact", contact, name="iletisim"),
    path("kategori/<slug:kategoriSlug>", kategori, name="kategori"),
    path("yazilarim", yazilarim, name="yazilarim"),
    path("detay/<slug:slug>", detay, name="detay"),
    path("yazi-ekle", yaziEkle, name="yazi-ekle"),
    path("yazi-guncelle/<slug:slug>", yaziGuncelle, name="yazi-guncelle"),
    path("yazi-sil/<slug:slug>", yaziSil, name="yazi-sil"),
    path("yorum-sil/<int:id>", yorumSil, name="yorum-sil"),
]


from sklearn.base import clone
from itertools import  combinations
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score

'''
序列后向选择算法（Sequence Backward Selection)
    用作特征选择
'''
class SBS():
    def __init__(self,estimator,k_features,
                 scoring=accuracy_score,
                 test_size=0.25,
                 random_state=1):
        self.scoring = scoring
        self.estimator = clone(estimator)
        self.k_features = k_features
        self.test_size = test_size
        self.random_state = random_state

    def fit(self,X,y):
        X_train,X_test,y_train,y_test=\
                train_test_split(X,y,test_size=self.test_size,random_state=self.random_state)
        dim = X_train.shape[1]#当前特征数
        self.indices_ = tuple(range(dim))
        self.subsets_ = [self.indices_]#子特征数
        score = self._calc_score(X_train,y_train,X_test,y_test,self.indices_)
        self.scores_ = [score]#获取初始分值
        while dim>self.k_features:
            scores = []
            subsets = []
            for p in combinations(self.indices_,r=dim-1):#对当前特征数进行特征数-1的排列组合，获取到子序列
                score = self._calc_score(X_train,y_train,
                                         X_test,y_test,p)
                scores.append(score)
                subsets.append(p)
            best = np.argmax(scores)
            self.indices_ = subsets[best] #获取到当前子序列中分值最高的特征值子序列
            self.subsets_.append(self.indices_)#获取当前数量分值最高的子序列
            dim -= 1
            self.scores_.append(scores[best])#获取当前最好的分值

        self.k_score_ = self.scores_[-1]#获取分值最高的分数
        return self

    def transform(self,X):
        return X[:,self.indices_]

    def _calc_score(self,X_train,y_train,X_test,y_test,indices):
        self.estimator.fit(X_train[:,indices],y_train)#通过给定的机器学习算法，训练模型
        y_pred = self.estimator.predict(X_test[:,indices])#通过测试集得到预测结果
        score = self.scoring(y_test,y_pred)#获取到预测分值
        return score


class Solution:
    def removeSpace(self, s):
        new_s = ''
        for i in s:
            if i.isalpha():
                new_s += i.lower()
            elif i.isnumeric():
                new_s += i

        return new_s

    def isPalindrome(self, s: str) -> bool:
        """同时check是否是字符或者数字，如果不是就跳过，是则"""
        left, right = 0, len(s) - 1
        while left < right:
            if not s[left].isalnum():
                left += 1
                continue
            if not s[right].isalnum():
                right -= 1
                continue
            if s[left].lower() == s[right].lower():
                left += 1
                right -= 1
            else:
                return False
        return True


import sys
import table
l_eax=[]
l_ebx=[]
l_ecx=[]
l_edx=[]
sys_cal=[]
sym_addr=[]
sym_val=[]
with open("test.asm","r") as f:
    for line in f:
        if " db " in line:
            l1=line.split('"')
            sym_val.append(l1[1])
            sym_addr.append('0')
        if " equ " in line:
            sym_val.append(len(sym_val[0])+2)

#print(sym_val)
with open("test.o","r") as file:
    for line in file:
        line=line.replace("\n","")
        l=list(line)
        if l[0]=='B' and l[1]=='8':
            val=''.join(l[2:])
            opc=''.join(l[:2])
            if val=="01":
                l_eax.append(val)
            elif val=='04':
                l_ebx.append(val)
   #         print(opc,val)
        elif l[0]=='B' and l[1]=='9':
            val=''.join(l[2:])
            opc=''.join(l[:2])
            if '[' in val:
                l_ecx.append(val)
  #          print(opc,val)
        elif l[0]=='B' and l[1]=='A':
            val=''.join(l[2:])
            opc=''.join(l[:2])
            l_edx.append(val)
 #           print(opc,val)
        elif l[0]=='C' and l[1]=='D':
            val=''.join(l[2:])
            opc=''.join(l[:2])
            if val=='80':
                if l_ebx[0]=='04':
                    for i in range(len(sym_addr)):
                        if sym_addr[i] in l_ecx[0]:
                            print(sym_val[0])
                if l_eax[0]=='01':
                    sys.exit(0)
               # print(opc,val)

#print(l_eax,l_ebx,l_ecx,l_edx)


#!/usr/bin/env python
import os
import sys
import gc
from math import *
import time
import random
import pysam

# Get position of read based on chr with sam or bam file
def get_read_pos_with_sam_bam_file(sam_bam_file, chr_len_db, bin_size, out_list):
	long_bin_size = bin_size.upper()
	long_bin_size = long_bin_size.replace('K', '000')
	long_bin_size = long_bin_size.replace('M', '000000')
	long_bin_size = long_bin_size.replace('G', '000000000')
	long_bin_size = int(long_bin_size)

	random.seed()
	read_on_chr = {}
	with pysam.AlignmentFile(sam_bam_file, 'rb') as fin:
		with open(bin_size.upper()+"_"+out_list, 'w') as fout:
			for line in fin:
				if 'WGS' in line.query_name:
					fout.write(line.strip().split()[0]+"\n")
					continue
				read_id = line.query_name

				if line.is_unmapped or line.mate_is_unmapped:
					continue

				read_pos1 = line.reference_start+1
				chr1 = line.reference_name
				chr2 = line.next_reference_name
				read_pos2 = line.next_reference_start +1

				if chr1 == chr2 and chr1 in chr_len_db:
					bin_count_of_chr = int(round((chr_len_db[chr1]*1.0/long_bin_size+0.5)))
					pos1_index = int(read_pos1/long_bin_size)
					pos2_index = int(read_pos2/long_bin_size)
					if (pos1_index+pos2_index) in range(bin_count_of_chr-11, bin_count_of_chr+10):
						border = abs(bin_count_of_chr-1-(pos1_index+pos2_index))

						if abs(pos1_index-pos2_index) < 4:
							border = 0
						elif abs(pos1_index-pos2_index) < 7:
							border = 1
						else:
							border = 4.0-int((border+1)/2)
						if random.random() > 1.0/(2**border):
							fout.write(read_id+'\n')
							if read_id in read_on_chr:
								read_on_chr.pop(read_id)
							continue
				read_on_chr[read_id] = [chr1, read_pos1, chr2, read_pos2]
	return read_on_chr

# Get chromosome length
def get_chr_len(chr_list):
	chr_len_db = {}
	chr_order = []
	with open(chr_list, 'r') as f_in:
		for line in f_in:
			if line.strip() == '':
				continue
			data = line.strip().split()
			chr_order.append(data[0])
			chr_len_db[data[0]] = int(data[1])
	return chr_len_db, chr_order

# Calc read counts on each bin
def calc_read_count_per_bin(chr_len_db, chr_order, read_on_chr, bin_size):
	long_bin_size = bin_size.upper()
	long_bin_size = long_bin_size.replace('K', '000')
	long_bin_size = long_bin_size.replace('M', '000000')
	long_bin_size = long_bin_size.replace('G', '000000000')
	long_bin_size = int(long_bin_size)

	read_count_per_chr = {}
	read_count_whole_genome = {}

	bin_offset = [0 for i in range(0, len(chr_order)+1)]
	bin_count = [0 for i in range(0, len(chr_order)+1)]
	total_bin_count = 0

	for chrn in chr_len_db:
		bin_count_of_chr = int(round((chr_len_db[chrn]*1.0/long_bin_size+0.5)))
		total_bin_count += bin_count_of_chr
		bin_count[chr_order.index(chrn)+1] = bin_count_of_chr
		read_count_per_chr[chrn] = [[0 for i in range(0, bin_count_of_chr)] for j in range(0, bin_count_of_chr)]

	for i in range(0, len(bin_count)):
		for j in range(0, i+1):
			bin_offset[i] += bin_count[j]

	read_count_whole_genome = [[0 for i in range(0, total_bin_count)] for j in range(0, total_bin_count)]

	for read in read_on_chr:
		chr1, pos1, chr2, pos2 = read_on_chr[read]
		if chr1 not in chr_len_db or chr2 not in chr_len_db:
			continue
		pos1_index = int(pos1/long_bin_size)
		pos2_index = int(pos2/long_bin_size)
		if chr1 == chr2 and chr1 in read_count_per_chr:
			read_count_per_chr[chr1][pos1_index][pos2_index] += 1
			read_count_per_chr[chr1][pos2_index][pos1_index] += 1

		chr1_index = chr_order.index(chr1)
		chr2_index = chr_order.index(chr2)

		whole_pos1 = bin_offset[chr1_index] + pos1_index
		whole_pos2 = bin_offset[chr2_index] + pos2_index
		read_count_whole_genome[whole_pos1][whole_pos2] += 1
		read_count_whole_genome[whole_pos2][whole_pos1] += 1

	for chrn in read_count_per_chr:
		for i in range(0, len(read_count_per_chr[chrn])):
			for j in range(0, len(read_count_per_chr[chrn][i])):
				if read_count_per_chr[chrn][i][j] != 0:
					read_count_per_chr[chrn][i][j] = log(read_count_per_chr[chrn][i][j], 2)
				else:
					read_count_per_chr[chrn][i][j] = -float('inf')

	for i in range(0, len(read_count_whole_genome)):
		for j in range(0, len(read_count_whole_genome[i])):
			if read_count_whole_genome[i][j] != 0:
				read_count_whole_genome[i][j] = log(read_count_whole_genome[i][j], 2)
			else:
				read_count_whole_genome[i][j] = -float('inf')

	return read_count_per_chr, read_count_whole_genome

# Draw heatmap of allhic result with matplotlib
def draw_heatmap(data, chrn, bin_size, ext):

	import matplotlib as mpl
	mpl.use('Agg')
	import matplotlib.pyplot as plt

	short_bin_size = bin_size.upper()
	if bin_size[-9:] == '000000000':
		short_bin_size = bin_size[:-9]+'G'
	elif bin_size[-6:] == '000000':
		short_bin_size = bin_size[:-6]+'M'
	elif bin_size[-3:] == '000':
		short_bin_size = bin_size[:-3]+'K'

	ax = plt.gca()

	if chrn != 'all':
		file_prefix = short_bin_size + "_" + chrn
	else:
		file_prefix = short_bin_size + '_Whole_genome'

	print(time.strftime('[%H:%M:%S]',time.localtime(time.time()))+' Draw '+file_prefix)
	with open('log.csv', 'w') as flog:
		for i in range(0, len(data)):
			for j in range(0, len(data[i])):
				flog.write("%s,"%(str(data[i][j])))
			flog.write('\n')
	# mpl.cm.YlOrRd
	cmap = plt.get_cmap('YlOrRd')
	cmap.set_over('black')
	if chrn != 'all':
		hmap = ax.imshow(data, interpolation='nearest', origin='lower', cmap=cmap, aspect='auto')
	else:
		hmap = ax.imshow(data, interpolation='nearest', cmap=cmap, aspect='auto')

	plt.colorbar(mappable=hmap,cax=None, ax=None, shrink=0.5)
	plt.tick_params(labelsize=6)
	for ticks in ax.get_xticklabels():
		ticks.set_rotation(90)
	for ticks in ax.get_yticklabels():
		ticks.set_rotation(0)

	if chrn != 'all':
		title = chrn+'_'+short_bin_size
	else:
		title = 'Whole_genome_'+short_bin_size

	plt.xlabel("Bins ("+short_bin_size.lower()+"b per bin)", fontsize=8)
	if chrn == 'all':
		plt.xticks([])
		plt.yticks([])
		plt.title(title, y=1.01, fontsize=12)
	else:
		plt.title(title, y=1.1, fontsize=12)

	plt.savefig(file_prefix+'.'+ext, bbox_inches='tight', dpi=200)
	plt.close('all')

if __name__ == "__main__":
	if len(sys.argv) < 5:
		print("Notice: This script is using for drawing heatmap of the all-hic reasult")
		print("Usage: python "+sys.argv[0]+" <sam/bam file> <chr_list> <pic_ext> <out_filter_list>")
		print("\t<sam/bam_file> is the sam or bam file filtered by allhic")
		print("\t<chr_list> is the file contain ordered chrs and length")
		print("\t<pic_ext> is the file type of picture")
		print("\t<out_filter_list> is the list of reads to be filtered")

	else:
		sam_bam_file = sys.argv[1]
		chr_list = sys.argv[2]
		ext = sys.argv[3]
		out_list = sys.argv[4]

		print(time.strftime('[%H:%M:%S]',time.localtime(time.time()))+" Step 1: Get chromosome length")
		chr_len_db, chr_order = get_chr_len(chr_list)

		print(time.strftime('[%H:%M:%S]',time.localtime(time.time()))+" Step 2: Calculating and Drawing heatmap")

		bin_size = "150k"
		print(time.strftime('[%H:%M:%S]',time.localtime(time.time()))+" Get read position based on chromosome")
		read_on_chr = get_read_pos_with_sam_bam_file(sam_bam_file, chr_len_db, bin_size, out_list)
		print(time.strftime('[%H:%M:%S]',time.localtime(time.time()))+" Calculating")
		read_count_per_chr, read_count_whole_genome = calc_read_count_per_bin(chr_len_db, chr_order, read_on_chr, bin_size)

		print(time.strftime('[%H:%M:%S]',time.localtime(time.time()))+" Drawing heatmap")

		print(time.strftime('[%H:%M:%S]',time.localtime(time.time()))+" Drawing with bin size "+str(bin_size))
		for chrn in read_count_per_chr:
			draw_heatmap(read_count_per_chr[chrn], chrn, bin_size, ext)

		draw_heatmap(read_count_whole_genome, 'all', bin_size, ext)
		del read_count_per_chr, read_count_whole_genome
		gc.collect()

		del read_on_chr
		gc.collect()
		print(time.strftime('[%H:%M:%S]',time.localtime(time.time()))+" Success")


"""
MIT License

Copyright (c) 2018-Present NeuroAssassin

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
"""

import asyncio
import time
from collections import defaultdict
from copy import deepcopy as dc

import discord
from redbot.core import Config, commands
from redbot.core.utils import AsyncIter
from redbot.core.utils.chat_formatting import humanize_list

class Deleter(commands.Cog):
    """Set channels for their messages to be auto-deleted after a specified amount of time.

    WARNING: This cog has potential API abuse AND SHOULD BE USED CAREFULLY!  If you see any issues arise due to this, please report to Neuro Assassin or bot owner ASAP!
    """

    def __init__(self, bot):
        self.bot = bot
        self.lock = asyncio.Lock()
        self.conf = Config.get_conf(self, identifier=473541068378341376)
        default_channel = {"wait": 0, "messages": {}}
        self.conf.register_channel(**default_channel)
        self.task = self.bot.loop.create_task(self.background_task())

    def cog_unload(self):
        self.task.cancel()

    async def red_delete_data_for_user(self, **kwargs):
        """This cog does not store user data"""
        return

    async def background_task(self):
        await self.bot.wait_until_ready()
        while True:
            async with self.lock:
                cs = await self.conf.all_channels()
                async for channel, data in AsyncIter(cs.items()):
                    if int(data["wait"]) == 0:
                        continue
                    c = self.bot.get_channel(int(channel))
                    if not c:
                        continue
                    old = dc(data)
                    ms = dc(data["messages"])
                    async for message, wait in AsyncIter(ms.items()):
                        if int(wait) <= time.time():
                            dontdelete = False
                            try:
                                m = await c.fetch_message(int(message))
                                if not m.pinned:
                                    await m.delete()
                            except (discord.NotFound, discord.Forbidden):
                                pass
                            except discord.HTTPException:
                                dontdelete = True
                            if not dontdelete:
                                del data["messages"][str(message)]
                    if old != data:
                        await self.conf.channel(c).messages.set(data["messages"])
            await asyncio.sleep(10)

    @commands.Cog.listener()
    async def on_message(self, message):
        async with self.lock:
            c = await self.conf.channel(message.channel).all()
            if int(c["wait"]) == 0:
                return
            c["messages"][str(message.id)] = time.time() + int(c["wait"])
            await self.conf.channel(message.channel).messages.set(c["messages"])

    @commands.group(invoke_without_command=True)
    @commands.guild_only()
    @commands.mod_or_permissions(manage_messages=True)
    async def deleter(self, ctx):
        """Group command for commands dealing with auto-timed deletion.

        To see what channels are currently being tracked, use this command with no subcommands passed.
        """
        async with self.lock:
            channels = await self.conf.all_channels()
        sending = ""
        for c, data in channels.items():
            c = self.bot.get_channel(int(c))
            if c is None:
                continue
            if c.guild.id == ctx.guild.id and int(data["wait"]) != 0:
                sending += f"{c.mention}: {data['wait']} seconds\n"
        if sending:
            await ctx.send(sending)
        else:
            await ctx.send(
                f"No channels are currently being tracked.  Add one by using `{ctx.prefix}deleter channel`."
            )

    @deleter.command()
    async def channel(self, ctx, channel: discord.TextChannel, wait):
        """Set the amount of time after a message sent in the specified channel is supposed to be deleted.

        There may be about an approximate 10 second difference between the wait and the actual time the message is deleted, due to rate limiting and cooldowns.

        Wait times must be greater than or equal to 5 seconds, or 0 to disable auto-timed deletion.  If you would like to use time specifications other than seconds, suffix the wait argument with one below:

        s => seconds (ex. 5s => 5 seconds)
        m => minutes (ex. 5m => 5 minutes)
        h => hours   (ex. 5h => 5 hours)
        d => days    (ex. 5d => 5 days)
        w => weeks   (ex. 5w => 5 weeks"""
        if wait != "0":
            ttype = None
            wait = wait.lower()
            wt = wait[:-1]
            og = wait[:-1]
            if not wt.isdigit():
                return await ctx.send(
                    "Invalid amount of time.  There is a non-number in your `wait` argument, not including the time type."
                )
            wt = int(wt)
            if wait.endswith("s"):
                ttype = "second"
            elif wait.endswith("m"):
                ttype = "minute"
                wt *= 60
            elif wait.endswith("h"):
                ttype = "hour"
                wt *= 3600
            elif wait.endswith("d"):
                ttype = "day"
                wt *= 86400
            elif wait.endswith("w"):
                ttype = "week"
                wt *= 604800
            if not ttype:
                return await ctx.send("Invalid time unit.  Please use S, M, H, D or W.")
        else:
            wt = 0
        if wt < 5 and wt != 0:
            return await ctx.send("Wait times must be greater than or equal to 5 seconds.")
        if not channel.permissions_for(ctx.guild.me).manage_messages:
            return await ctx.send("I do not have permission to delete messages in that channel.")
        if not channel.permissions_for(ctx.author).manage_messages:
            return await ctx.send("You do not have permission to delete messages in that channel.")
        await self.conf.channel(channel).wait.set(str(wt))
        if wt:
            await ctx.send(
                f"Messages in {channel.mention} will now be deleted after {og} {ttype}{'s' if og != '1' else ''}."
            )
        else:
            await ctx.send("Messages will not be auto-deleted after a specific amount of time.")

    @deleter.command()
    async def remove(self, ctx, channel: discord.TextChannel, *messages: str):
        """Remove messages in the specified channel from the auto-timed deletion.

        Helpful for announcements that you want to stay in the channel.
        The messages to be removed must be the IDs of the messages you wish to remove."""
        failed = []
        success = []
        msgs = await self.conf.channel(channel).messages()
        for m in messages:
            if not m in msgs:
                failed.append(m)
                continue
            del msgs[m]
            success.append(m)
        if not failed:
            failed = [None]
        if not success:
            success = [None]
        await self.conf.channel(channel).messages.set(msgs)
        await ctx.send(
            f"Messages successfully removed: {humanize_list(success)}\nMessages that failed to be removed: {humanize_list(failed)}"
        )

    @deleter.command()
    async def wipe(self, ctx, channel: discord.TextChannel = None):
        """Removes all messages in the specified channel from the auto-timed deleter.

        Leave blank to do it for the current channel."""
        if not channel:
            channel = ctx.channel
        await self.conf.channel(channel).messages.set({})
        await ctx.tick()


'''
  File name: rmHorSeam.py
  Author:
  Date created:
'''

'''
  File clarification:
    Removes horizontal seams. You should identify the pixel from My from which
    you should begin backtracking in order to identify pixels for removal, and
    remove those pixels from the input image.

    - INPUT I: n × m × 3 matrix representing the input image.
    - INPUT My: n × m matrix representing the cumulative minimum energy map along horizontal direction.
    - INPUT Tby: n × m matrix representing the backtrack table along horizontal direction.
    - OUTPUT Iy: (n − 1) × m × 3 matrix representing the image with the row removed.
    - OUTPUT E: the cost of seam removal.
'''
from constants import *
from rmVerSeam import *

def rmHorSeam(I, My, Tby):
  # Your Code Here

  Mx = np.transpose(My)

  Tbx = np.transpose(Tby)

  IUpdate = np.transpose(I, (1, 0, 2))

  Ix,E = rmVerSeam(IUpdate, Mx, Tbx)

  Iy = np.transpose(Ix, (1, 0, 2))

  return Iy, E


""" This is the script responsible for stacking images"""
import os
from PIL import Image

print("\nStart stacking images...")

os.chdir('cropped')
images = os.listdir()

red_data = []
green_data = []
blue_data = []
for image in images:
    with Image.open(image) as img:
        if image == images[0]:  # gets size of 1st cropped image
            img_size = img.size
        red_data.append(list(img.getdata(0)))
        green_data.append(list(img.getdata(1)))
        blue_data.append(list(img.getdata(2)))

ave_red = [round(sum(x)/len(red_data)) for x in zip(*red_data)]
ave_green = [round(sum(x)/len(green_data)) for x in zip(*green_data)]
ave_blue = [round(sum(x)/len(blue_data)) for x in zip(*blue_data)]

merged_data = list(zip(ave_red,ave_green,ave_blue))
stacked = Image.new('RGB', (img_size))
stacked.putdata(merged_data)
stacked.show()

os.chdir('..')
stacked.save('jupiter_stacked.tif','TIFF')
print('done')


"""

Explanation
Example case 1. The first person only knows the Indian head-bob, but that's not enough to prove that he is Indian.
Example case 2. The second person uses the Indian head-bob, and also the normal "Yes" gesture. Hence, he is Indian.
Example case 3. The third person only uses the "No" gesture. This is sufficient to prove that he is not Indian.

"""

import sys

def isIndian(gestures):
    if gestures.count('Y') > 0:
        return 'NOT INDIAN'
    elif gestures.count('I') > 0:
        return 'INDIAN'
    else:
        return 'NOT SURE'

if __name__ == "__main__":
    T = int(sys.stdin.readline())
    for i in range(T):
        N = int(sys.stdin.readline())
        gestures = sys.stdin.readline().strip()
        print(isIndian(gestures))


__author__ = 'Esmidth'

import time

b = [5, 2, 4, 6, 1, 3, 9, 7, 8, 11, 10]
a = b
i = 0

time_start = time.time()

while i < len(a) - 1:
    if a[i] > a[i + 1]:
        temp = a[i]
        a[i] = a[i + 1]
        a[i + 1] = temp
        i = 0
    i += 1
print(a)
time_end = time.time()

print("Insertion-sort(A): ", time_end - time_start)

a = b
j = 1
time_start = time.time()

while j < len(a):
    i = j - 1
    temp = a[j]
    while i >= 0 and temp < a[i]:
        a[i + 1] = a[i]
        i -= 1
    a[i + 1] = temp
    j += 1
time_end = time.time()
print("B: ", time_end - time_start)


import cv2 as cv
from kivy.graphics.texture import Texture

def cv_to_kivy_texture(src_cv):
    if len(src_cv.shape) == 2:
        out_cv = cv.cvtColor(src_cv, cv.COLOR_GRAY2BGR)
    else:
        out_cv = src_cv

    frame = (out_cv.shape[1], out_cv.shape[0])
    buf = out_cv.tostring()
    texture = Texture.create(size=(frame[0], frame[1]), colorfmt='bgr')
    texture.flip_vertical()
    texture.blit_buffer(buf, colorfmt='bgr', bufferfmt='ubyte')
    return texture


import numpy as np

def my_func(param1):
  print(param1)

# my_func('Aralya')
names = ['Aralya', 'Rosa', 'Tubesock']

# print(list(map(my_func, names)))

# list(map(my_func, names))

# list(map(lambda name: print(name), names))

numbers = [1, 2, 3, 4, 5, 6]

result = list(filter(lambda num: num%2 == 0, numbers))
# print(result)

print(np)
my_list = [1, 2, 3, 4]

print('this is before using np: ', my_list)
print(np.array(my_list))