# coding=utf-8
# Copyright 2022 The Google Research Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""Different datasets implementation plus a general port for all the datasets."""
INTERNAL = False  # pylint: disable=g-statement-before-imports
import json
import os
from os import path
import queue
import threading
if not INTERNAL:
  import cv2  # pylint: disable=g-import-not-at-top
import jax
import numpy as np
from PIL import Image
from snerg.nerf import utils

def get_dataset(split, args):
  return dataset_dict[args.dataset](split, args)

def convert_to_ndc(origins, directions, focal, w, h, near=1.):
  """Convert a set of rays to NDC coordinates."""
  # Shift ray origins to near plane
  t = -(near + origins[Ellipsis, 2]) / directions[Ellipsis, 2]
  origins = origins + t[Ellipsis, None] * directions

  dx, dy, dz = tuple(np.moveaxis(directions, -1, 0))
  ox, oy, oz = tuple(np.moveaxis(origins, -1, 0))

  # Projection
  o0 = -((2 * focal) / w) * (ox / oz)
  o1 = -((2 * focal) / h) * (oy / oz)
  o2 = 1 + 2 * near / oz

  d0 = -((2 * focal) / w) * (dx / dz - ox / oz)
  d1 = -((2 * focal) / h) * (dy / dz - oy / oz)
  d2 = -2 * near / oz

  origins = np.stack([o0, o1, o2], -1)
  directions = np.stack([d0, d1, d2], -1)
  return origins, directions

# TODO(bydeng): Swap this function with a more flexible camera model.
def rays_from_camera(use_pixel_centers, h, w, focal, camtoworlds):
  """Create rays for each pixel in a collection of images."""
  pixel_center = 0.5 if use_pixel_centers else 0.0
  x, y = np.meshgrid(  # pylint: disable=unbalanced-tuple-unpacking
      np.arange(w, dtype=np.float32) + pixel_center,  # X-Axis (columns)
      np.arange(h, dtype=np.float32) + pixel_center,  # Y-Axis (rows)
      indexing="xy")
  camera_dirs = np.stack([(x - w * 0.5) / focal,
                          -(y - h * 0.5) / focal, -np.ones_like(x)],
                         axis=-1)
  directions = ((camera_dirs[None, Ellipsis, None, :] *
                 camtoworlds[:, None, None, :3, :3]).sum(axis=-1))
  origins = np.broadcast_to(camtoworlds[:, None, None, :3, -1],
                            directions.shape)
  viewdirs = directions / np.linalg.norm(directions, axis=-1, keepdims=True)
  return origins, directions, viewdirs

class Dataset(threading.Thread):
  """Dataset Base Class."""

  def __init__(self, split, args):
    super(Dataset, self).__init__()
    self.queue = queue.Queue(3)  # Set prefetch buffer to 3 batches.
    self.daemon = True
    self.use_pixel_centers = args.use_pixel_centers
    self.split = split
    if split == "train":
      self._train_init(args)
    elif split == "test":
      self._test_init(args)
    else:
      raise ValueError(
          "the split argument should be either \"train\" or \"test\", set"
          "to {} here.".format(split))
    self.batch_size = args.batch_size // jax.host_count()
    self.batching = args.batching
    self.render_path = args.render_path
    self.start()

  def __iter__(self):
    return self

  def __next__(self):
    """Get the next training batch or test example.

    Returns:
      batch: dict, has "pixels" and "rays".
    """
    x = self.queue.get()
    if self.split == "train":
      return utils.shard(x)
    else:
      return utils.to_device(x)

  def peek(self):
    """Peek at the next training batch or test example without dequeuing it.

    Returns:
      batch: dict, has "pixels" and "rays".
    """
    x = self.queue.queue[0].copy()  # Make a copy of the front of the queue.
    if self.split == "train":
      return utils.shard(x)
    else:
      return utils.to_device(x)

  def run(self):
    if self.split == "train":
      next_func = self._next_train
    else:
      next_func = self._next_test
    while True:
      self.queue.put(next_func())

  @property
  def size(self):
    return self.n_examples

  def _train_init(self, args):
    """Initialize training."""
    self._load_renderings(args)
    self._generate_rays()

    if args.batching == "all_images":
      # flatten the ray and image dimension together.
      self.images = self.images.reshape([-1, 3])
      self.rays = utils.namedtuple_map(lambda r: r.reshape([-1, r.shape[-1]]),
                                       self.rays)
    elif args.batching == "single_image":
      self.images = self.images.reshape([-1, self.resolution, 3])
      self.rays = utils.namedtuple_map(
          lambda r: r.reshape([-1, self.resolution, r.shape[-1]]), self.rays)
    else:
      raise NotImplementedError(
          f"{args.batching} batching strategy is not implemented.")

  def _test_init(self, args):
    self._load_renderings(args)
    self._generate_rays()
    self.it = 0

  def _next_train(self):
    """Sample next training batch."""

    if self.batching == "all_images":
      ray_indices = np.random.randint(0, self.rays[0].shape[0],
                                      (self.batch_size,))
      batch_pixels = self.images[ray_indices]
      batch_rays = utils.namedtuple_map(lambda r: r[ray_indices], self.rays)
    elif self.batching == "single_image":
      image_index = np.random.randint(0, self.n_examples, ())
      ray_indices = np.random.randint(0, self.rays[0][0].shape[0],
                                      (self.batch_size,))
      batch_pixels = self.images[image_index][ray_indices]
      batch_rays = utils.namedtuple_map(lambda r: r[image_index][ray_indices],
                                        self.rays)
    else:
      raise NotImplementedError(
          f"{self.batching} batching strategy is not implemented.")
    return {"pixels": batch_pixels, "rays": batch_rays}

  def _next_test(self):
    """Sample next test example."""
    idx = self.it
    self.it = (self.it + 1) % self.n_examples

    if self.render_path:
      return {"rays": utils.namedtuple_map(lambda r: r[idx], self.render_rays)}
    else:
      return {
          "pixels": self.images[idx],
          "rays": utils.namedtuple_map(lambda r: r[idx], self.rays)
      }

  def _generate_rays(self):
    """Generating rays for all images."""
    origins, directions, viewdirs = rays_from_camera(self.use_pixel_centers,
                                                     self.h, self.w, self.focal,
                                                     self.camtoworlds)
    self.rays = utils.Rays(
        origins=origins, directions=directions, viewdirs=viewdirs)

class Blender(Dataset):
  """Blender Dataset."""

  def _load_renderings(self, args):
    """Load images from disk."""
    if args.render_path:
      raise ValueError("render_path cannot be used for the blender dataset.")
    with utils.open_file(
        path.join(args.data_dir, "transforms_{}.json".format(self.split)),
        "r") as fp:
      meta = json.load(fp)
    images = []
    cams = []
    for i in range(len(meta["frames"])):
      frame = meta["frames"][i]
      fname = os.path.join(args.data_dir, frame["file_path"] + ".png")
      with utils.open_file(fname, "rb") as imgin:
        image = np.array(Image.open(imgin), dtype=np.float32) / 255.
        if args.factor == 2:
          [halfres_h, halfres_w] = [hw // 2 for hw in image.shape[:2]]
          image = cv2.resize(
              image, (halfres_w, halfres_h), interpolation=cv2.INTER_AREA)
        elif args.factor > 0:
          raise ValueError("Blender dataset only supports factor=0 or 2, {} "
                           "set.".format(args.factor))
      cams.append(np.array(frame["transform_matrix"], dtype=np.float32))
      images.append(image)
    self.images = np.stack(images, axis=0)
    if args.white_bkgd:
      self.images = (
          self.images[Ellipsis, :3] * self.images[Ellipsis, -1:] +
          (1. - self.images[Ellipsis, -1:]))
    else:
      self.images = self.images[Ellipsis, :3]
    self.h, self.w = self.images.shape[1:3]
    self.resolution = self.h * self.w
    self.camtoworlds = np.stack(cams, axis=0)
    camera_angle_x = float(meta["camera_angle_x"])
    self.focal = .5 * self.w / np.tan(.5 * camera_angle_x)
    self.n_examples = self.images.shape[0]

class LLFF(Dataset):
  """LLFF Dataset."""

  def _load_renderings(self, args):
    """Load images from disk."""
    # Load images.
    imgdir_suffix = ""
    if args.factor > 0:
      imgdir_suffix = "_{}".format(args.factor)
      factor = args.factor
    else:
      factor = 1
    imgdir = path.join(args.data_dir, "images" + imgdir_suffix)
    if not utils.file_exists(imgdir):
      raise ValueError("Image folder {} doesn't exist.".format(imgdir))
    imgfiles = [
        path.join(imgdir, f)
        for f in sorted(utils.listdir(imgdir))
        if f.endswith("JPG") or f.endswith("jpg") or f.endswith("png")
    ]
    images = []
    for imgfile in imgfiles:
      with utils.open_file(imgfile, "rb") as imgin:
        image = np.array(Image.open(imgin), dtype=np.float32) / 255.
        images.append(image)
    images = np.stack(images, axis=-1)

    # Load poses and bds.
    with utils.open_file(path.join(args.data_dir, "poses_bounds.npy"),
                         "rb") as fp:
      poses_arr = np.load(fp)
    poses = poses_arr[:, :-2].reshape([-1, 3, 5]).transpose([1, 2, 0])
    bds = poses_arr[:, -2:].transpose([1, 0])
    if poses.shape[-1] != images.shape[-1]:
      raise RuntimeError("Mismatch between imgs {} and poses {}".format(
          images.shape[-1], poses.shape[-1]))

    # Update poses according to downsampling.
    poses[:2, 4, :] = np.array(images.shape[:2]).reshape([2, 1])
    poses[2, 4, :] = poses[2, 4, :] * 1. / factor

    # Correct rotation matrix ordering and move variable dim to axis 0.
    poses = np.concatenate(
        [poses[:, 1:2, :], -poses[:, 0:1, :], poses[:, 2:, :]], 1)
    poses = np.moveaxis(poses, -1, 0).astype(np.float32)
    images = np.moveaxis(images, -1, 0)
    bds = np.moveaxis(bds, -1, 0).astype(np.float32)

    # Rescale according to a default bd factor.
    scale = 1. / (bds.min() * .75)
    poses[:, :3, 3] *= scale
    bds *= scale

    # Recenter poses.
    poses = self._recenter_poses(poses)

    # Generate a spiral/spherical ray path for rendering videos.
    if args.spherify:
      poses = self._generate_spherical_poses(poses, bds)
      self.spherify = True
    else:
      self.spherify = False
    if not args.spherify and self.split == "test":
      self._generate_spiral_poses(poses, bds)

    # Select the split.
    i_test = np.arange(images.shape[0])[::args.llffhold]
    i_train = np.array(
        [i for i in np.arange(int(images.shape[0])) if i not in i_test])
    if self.split == "train":
      indices = i_train
    else:
      indices = i_test
    images = images[indices]
    poses = poses[indices]

    self.images = images
    self.camtoworlds = poses[:, :3, :4]
    self.focal = poses[0, -1, -1]
    self.h, self.w = images.shape[1:3]
    self.resolution = self.h * self.w
    if args.render_path:
      self.n_examples = self.render_poses.shape[0]
    else:
      self.n_examples = images.shape[0]

  def _generate_rays(self):
    """Generate normalized device coordinate rays for llff."""
    if self.split == "test":
      n_render_poses = self.render_poses.shape[0]
      self.camtoworlds = np.concatenate([self.render_poses, self.camtoworlds],
                                        axis=0)

    super()._generate_rays()

    if not self.spherify:
      ndc_origins, ndc_directions = convert_to_ndc(self.rays.origins,
                                                   self.rays.directions,
                                                   self.focal, self.w, self.h)
      self.rays = utils.Rays(
          origins=ndc_origins,
          directions=ndc_directions,
          viewdirs=self.rays.viewdirs)

    # Split poses from the dataset and generated poses
    if self.split == "test":
      self.camtoworlds = self.camtoworlds[n_render_poses:]
      split = [np.split(r, [n_render_poses], 0) for r in self.rays]
      split0, split1 = zip(*split)
      self.render_rays = utils.Rays(*split0)
      self.rays = utils.Rays(*split1)

  def _recenter_poses(self, poses):
    """Recenter poses according to the original NeRF code."""
    poses_ = poses.copy()
    bottom = np.reshape([0, 0, 0, 1.], [1, 4])
    c2w = self._poses_avg(poses)
    c2w = np.concatenate([c2w[:3, :4], bottom], -2)
    bottom = np.tile(np.reshape(bottom, [1, 1, 4]), [poses.shape[0], 1, 1])
    poses = np.concatenate([poses[:, :3, :4], bottom], -2)
    poses = np.linalg.inv(c2w) @ poses
    poses_[:, :3, :4] = poses[:, :3, :4]
    poses = poses_
    return poses

  def _poses_avg(self, poses):
    """Average poses according to the original NeRF code."""
    hwf = poses[0, :3, -1:]
    center = poses[:, :3, 3].mean(0)
    vec2 = self._normalize(poses[:, :3, 2].sum(0))
    up = poses[:, :3, 1].sum(0)
    c2w = np.concatenate([self._viewmatrix(vec2, up, center), hwf], 1)
    return c2w

  def _viewmatrix(self, z, up, pos):
    """Construct lookat view matrix."""
    vec2 = self._normalize(z)
    vec1_avg = up
    vec0 = self._normalize(np.cross(vec1_avg, vec2))
    vec1 = self._normalize(np.cross(vec2, vec0))
    m = np.stack([vec0, vec1, vec2, pos], 1)
    return m

  def _normalize(self, x):
    """Normalization helper function."""
    return x / np.linalg.norm(x)

  def _generate_spiral_poses(self, poses, bds):
    """Generate a spiral path for rendering."""
    c2w = self._poses_avg(poses)
    # Get average pose.
    up = self._normalize(poses[:, :3, 1].sum(0))
    # Find a reasonable "focus depth" for this dataset.
    close_depth, inf_depth = bds.min() * .9, bds.max() * 5.
    dt = .75
    mean_dz = 1. / (((1. - dt) / close_depth + dt / inf_depth))
    focal = mean_dz
    # Get radii for spiral path.
    tt = poses[:, :3, 3]
    rads = np.percentile(np.abs(tt), 90, 0)
    c2w_path = c2w
    n_views = 120
    n_rots = 2
    # Generate poses for spiral path.
    render_poses = []
    rads = np.array(list(rads) + [1.])
    hwf = c2w_path[:, 4:5]
    zrate = .5
    for theta in np.linspace(0., 2. * np.pi * n_rots, n_views + 1)[:-1]:
      c = np.dot(c2w[:3, :4], (np.array(
          [np.cos(theta), -np.sin(theta), -np.sin(theta * zrate), 1.]) * rads))
      z = self._normalize(c - np.dot(c2w[:3, :4], np.array([0, 0, -focal, 1.])))
      render_poses.append(np.concatenate([self._viewmatrix(z, up, c), hwf], 1))
    self.render_poses = np.array(render_poses).astype(np.float32)[:, :3, :4]

  def _generate_spherical_poses(self, poses, bds):
    """Generate a 360 degree spherical path for rendering."""
    # pylint: disable=g-long-lambda
    p34_to_44 = lambda p: np.concatenate([
        p,
        np.tile(np.reshape(np.eye(4)[-1, :], [1, 1, 4]), [p.shape[0], 1, 1])
    ], 1)
    rays_d = poses[:, :3, 2:3]
    rays_o = poses[:, :3, 3:4]

    def min_line_dist(rays_o, rays_d):
      a_i = np.eye(3) - rays_d * np.transpose(rays_d, [0, 2, 1])
      b_i = -a_i @ rays_o
      pt_mindist = np.squeeze(-np.linalg.inv(
          (np.transpose(a_i, [0, 2, 1]) @ a_i).mean(0)) @ (b_i).mean(0))
      return pt_mindist

    pt_mindist = min_line_dist(rays_o, rays_d)
    center = pt_mindist
    up = (poses[:, :3, 3] - center).mean(0)
    vec0 = self._normalize(up)
    vec1 = self._normalize(np.cross([.1, .2, .3], vec0))
    vec2 = self._normalize(np.cross(vec0, vec1))
    pos = center
    c2w = np.stack([vec1, vec2, vec0, pos], 1)
    poses_reset = (
        np.linalg.inv(p34_to_44(c2w[None])) @ p34_to_44(poses[:, :3, :4]))
    rad = np.sqrt(np.mean(np.sum(np.square(poses_reset[:, :3, 3]), -1)))
    sc = 1. / rad
    poses_reset[:, :3, 3] *= sc
    bds *= sc
    rad *= sc
    centroid = np.mean(poses_reset[:, :3, 3], 0)
    zh = centroid[2]
    radcircle = np.sqrt(rad**2 - zh**2)
    new_poses = []

    for th in np.linspace(0., 2. * np.pi, 120):
      camorigin = np.array([radcircle * np.cos(th), radcircle * np.sin(th), zh])
      up = np.array([0, 0, -1.])
      vec2 = self._normalize(camorigin)
      vec0 = self._normalize(np.cross(vec2, up))
      vec1 = self._normalize(np.cross(vec2, vec0))
      pos = camorigin
      p = np.stack([vec0, vec1, vec2, pos], 1)
      new_poses.append(p)

    new_poses = np.stack(new_poses, 0)
    new_poses = np.concatenate([
        new_poses,
        np.broadcast_to(poses[0, :3, -1:], new_poses[:, :3, -1:].shape)
    ], -1)
    poses_reset = np.concatenate([
        poses_reset[:, :3, :4],
        np.broadcast_to(poses[0, :3, -1:], poses_reset[:, :3, -1:].shape)
    ], -1)
    if self.split == "test":
      self.render_poses = new_poses[:, :3, :4]
    return poses_reset

dataset_dict = {
    "blender": Blender,
    "llff": LLFF,
}


class array_element:
    def __init__(self, index, val):
        self._index = index
        self._value = val

    def getIndex(self):
        return self._index

    def getValue(self):
        return self._value

class Solution(object):
    def twoSum(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: List[int]
        """

        new_nums = []

        # Convert the values to objects, so we can store their indices, also filter out any invalid values
        for old_idx, val in enumerate(nums):
                new_nums.append(array_element(old_idx, val))

        # Sort the numbers
        new_nums = sorted(new_nums, key=lambda ele: ele.getValue())

        # Optimization
        list_len = len(new_nums)
        if(list_len == 2):
            lower_idx = new_nums[0].getIndex()
            upper_idx = new_nums[1].getIndex()
            return [lower_idx, upper_idx]

        # Bad stuff happened
        assert(list_len >= 2)

        upper_idx = list_len - 1
        lower_idx = 0

        found = False

        while not found:
            sum = new_nums[lower_idx].getValue() + new_nums[upper_idx].getValue()

            # Lower index is too low, slide it right
            if sum < target:
                lower_idx += 1
            # Upper index is too high, slide it left
            elif sum > target:
                upper_idx -= 1
            else:
                lower_idx = new_nums[lower_idx].getIndex()
                upper_idx = new_nums[upper_idx].getIndex()
                return [lower_idx, upper_idx]


import os.path
import json
import matplotlib.pyplot as plt
from matplotlib.ticker import (MultipleLocator, FormatStrFormatter,AutoMinorLocator)
import numpy as np

def upload_model_results(file, params, train_scores, val_scores):
    """
    args:
    file = a json file name in the current directory
    params: a list of hyperparams of a model
    train_scores: a list of performance values over the train dataset
    val_scores: a list of performance values over the train dataset
    """
    item = [params, train_scores, val_scores]

    if os.path.isfile(file):

        # load data from file
        with open(file) as f:
            data = json.load(f)
        data.append(item)

        # overwrite the file
        with open(file, mode='w') as f:
            json.dump(data, f)

    else:
        with open(file, mode='w') as f:
            json.dump([item], f)

def plot_model_results(file, score_label='loss', index=-1):
    """
    args
    file = output of upload_model_results function. file must be in the current directory
    index = list index of the output of upload_mode_results.
    score_label (string): name of the score e.g. 'accuracy', 'loss'
    """
    with open(file) as f:
        data = json.load(f)

    train_scores = data[index][1]
    val_scores = data[index][2]
    epochs = len(data[index][1])
    title = data[index][0]

    fig, ax = plt.subplots()
    ax.plot(range(epochs), train_scores, marker='.', label='train')
    ax.plot(range(epochs), val_scores, marker='.', label='val')
    ax.xaxis.set_major_locator(MultipleLocator(5))
    ax.xaxis.set_major_formatter(FormatStrFormatter('%d'))
    ax.xaxis.set_minor_locator(MultipleLocator(1))
    if score_label == 'accuracy':
        ax.set_yticks(np.arange(0, 1.2, 0.2))
    ax.set_xlabel('epochs')
    ax.set_ylabel(score_label)
    ax.grid()
    ax.set_title(title)
    ax.legend(loc='upper right')


import torch
import torch.nn as nn
import numpy as np
from torch.nn.utils.rnn import pad_sequence, pad_packed_sequence, pack_padded_sequence
import torch.nn.functional as F
import global_var

class LstmDecoder(nn.Module):
    def __init__(self, num_embeddings, embedding_dim, hidden_size, word_mat_path=None):
        '''
        num_emgbeddings also means the output size of softmax
        '''
        super().__init__()
        if word_mat_path != None:
            self.embedding = nn.Embedding.from_pretrained(torch.tensor(np.load(word_mat_path), dtype=torch.float32), freeze=False)
        else:
            self.embedding = nn.Embedding(num_embeddings, embedding_dim)
        self.lstm_cell = nn.LSTMCell(embedding_dim, hidden_size)
        self.linear = nn.Linear(hidden_size, num_embeddings + 1)   # +1: '[EOS]'
        self.sos_input = nn.Parameter(torch.tensor(np.random.randn(1, embedding_dim), dtype=torch.float32), )

    def forward(self, h, c, max_length, is_teacher_force=False, teacher_input=None):
        '''
        这个是给定label长度，用于训练，predict需要可变长度
        h: (b, h)
        c: (b, h)
        max_length (int): max length of the label text, include [EOS]
        teacher_input : padded tensor(b, max_l)
        '''
        # clip the eos
        teacher_input = torch.clamp(teacher_input, 0, self.embedding.weight.size(0)-1)

        output = []
        input_x = torch.cat([self.sos_input]*(h.size(0)), 0)   # (b, embedding_dim)
        # input_x = c
        for i in range(max_length):
            h, c = self.lstm_cell(input_x, (h, c))
            output.append(self.linear(h))
            if (not is_teacher_force):
                # input_x = c
                _, input_x = output[-1][:, :-1].topk(1, dim=-1)   # remove the eos dim, (b, 1)
                input_x = input_x.squeeze(-1)  # (b)
                input_x = self.embedding(input_x)  # b, embedding_dim
                input_x = F.relu(input_x)
            else:
                input_x = teacher_input[:, i]  # (b)
                input_x = self.embedding(input_x)

        output = torch.stack(output, 1)   # (b, max_l, num_embeddings + 1)
        return output


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

"""
The MIT License (MIT)

Copyright (c) 2020 James

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 inspect
import sys
import traceback
from types import ModuleType
from typing import TYPE_CHECKING, Any, Awaitable, Dict, List, Optional

from .commands import Command, GroupCommand

if TYPE_CHECKING:
    from steam.ext import commands

    from ...client import EventType
    from .bot import Bot
    from .context import Context

__all__ = (
    "Cog",
    "ExtensionType",
)

class InjectedListener:
    """Injects the cog's "self" parameter into every event call auto-magically."""

    __slots__ = ("func", "cog", "_is_coroutine")

    def __init__(self, cog: "Cog", func: "EventType"):
        self.func = func
        self.cog = cog
        self._is_coroutine = asyncio.coroutines._is_coroutine  # for asyncio.iscoroutinefunction

    def __call__(self, *args, **kwargs) -> Awaitable[None]:
        return self.func(self.cog, *args, **kwargs)

# for a bit of type hinting
class ExtensionType(ModuleType):
    def setup(self, bot: "Bot") -> None:
        pass

    def teardown(self, bot: "Bot") -> None:
        pass

class Cog:
    """A class from which Cogs can be created. These are used to separate commands and listeners into separate files.

    Attributes
    ----------
    qualified_name: :class:`str`
        The name of the cog. Can be set in a subclass e.g. ::

            class MyCog(commands.Cog, name='SpecialCogName'):
                ...

        Defaults to ``Cog.__name__``.

    command_attrs: Dict[str, Any]
        Attributes to pass to every command registered in the cog.
        Can be set in subclass e.g. ::

            class MyBrokenCog(commands.Cog, command_attrs=dict(enabled=False)):
                # all the commands by default would be disabled

                @commands.command()
                async def broken(self, ctx):  # disabled
                    ...

                @commands.command(enabled=True)
                async def working(self, ctx):  # enabled
                    ...
    """

    __commands__: Dict[str, Command]
    __listeners__: Dict[str, List["InjectedListener"]]
    command_attrs: Dict[str, Any]
    qualified_name: str

    def __init_subclass__(cls, *args, **kwargs):
        cls.qualified_name = kwargs.get("name") or cls.__name__
        cls.command_attrs = kwargs.get("command_attrs", dict())

        cls.__listeners__ = dict()
        cls.__commands__ = dict()
        for name, attr in inspect.getmembers(cls):
            if isinstance(attr, Command):
                if attr.parent:  # ungrouped commands have no parent
                    continue
                cls.__commands__[name] = attr
            elif hasattr(attr, "__event_name__"):
                try:
                    cls.__listeners__[attr.__event_name__].append(attr)
                except KeyError:
                    cls.__listeners__[attr.__event_name__] = [attr]

    @property
    def description(self) -> Optional[str]:
        """Optional[:class:`str`]: The cleaned up docstring for the class."""
        help_doc = inspect.getdoc(self)
        if isinstance(help_doc, bytes):
            return help_doc.decode("utf-8")

        return help_doc

    @classmethod
    def listener(cls, name: Optional[str] = None):
        """Register a function as a listener.
        Similar to :meth:`~steam.ext.commands.Bot.listen`

        Parameters
        ----------
        name: Optional[:class:`str`]
            The name of the event to listen for. Defaults to ``func.__name__``.
        """

        def decorator(func: "EventType"):
            if not asyncio.iscoroutinefunction(func):
                raise TypeError(f"Listeners must be coroutines, {func.__name__} is {type(func).__name__}")
            func.__event_name__ = name or func.__name__
            return func

        return decorator

    async def cog_command_error(self, ctx: "commands.Context", error: Exception):
        """|coro|
        A special method that is called when an error is dispatched inside this cog. This is similar to
        :func:`~commands.Bot.on_command_error` except it only applies to the commands inside this cog.

        Parameters
        -----------
        ctx: :class:`~steam.ext.commands.Context`
            The invocation context where the error happened.
        error: :exc:`Exception`
            The error that happened.
        """
        print(f"Ignoring exception in command {ctx.command.name}:", file=sys.stderr)
        traceback.print_exception(type(error), error, error.__traceback__, file=sys.stderr)

    async def cog_check(self, ctx: "commands.Context"):
        """|coro|
        A special method that registers as a :func:`commands.check` for every command and subcommand in this cog.
        This should return a boolean result.

        Parameters
        -----------
        ctx: :class:`~commands.Context`
            The invocation context.

        Returns
        -------
        :class:`bool`
        """
        return True

    def cog_unload(self):
        """A special method that is called when the cog gets removed.

        This is called before :func:`teardown`.
        """

    def _inject(self, bot: "Bot") -> None:
        for idx, command in enumerate(self.__commands__.values()):
            command.cog = self
            command.checks.append(self.cog_check)
            old_attrs = inspect.getmembers(command)
            for name, value in self.command_attrs.items():
                if (name, value) not in old_attrs:
                    setattr(command, name, value)
            setattr(self, command.callback.__name__, command)
            if isinstance(command, GroupCommand):
                for child in command.children:
                    child.cog = self
            try:
                bot.add_command(command)
            except Exception:
                # undo our additions
                for to_undo in tuple(self.__commands__)[:idx]:
                    bot.remove_command(to_undo)
                raise

        for name, listeners in self.__listeners__.items():
            for idx, listener in enumerate(listeners):
                # we need to manually inject the "self" parameter
                listener = InjectedListener(self, listener)
                self.__listeners__[name][idx] = listener  # edit the original
                bot.add_listener(listener, name)

    def _eject(self, bot: "Bot") -> None:
        for command in self.__commands__.values():
            if isinstance(command, GroupCommand):
                command.recursively_remove_all_commands()
            bot.remove_command(command.name)

        for name, listeners in self.__listeners__.items():
            for listener in listeners:
                bot.remove_listener(listener, name)

        self.cog_unload()


import torch
import torch.nn as nn

class EncoderNetwork(nn.Module):

    def __init__(self,
                 enc_hid_dim: int,
                 emb_dim: int,
                 dec_hid_dim: int,
                 emb_count: int,
                 dropout: float,
                 num_layers: int,
                 device: str = 'cpu'):
        self.device = device
        super().__init__()
        self.embeddings = nn.Embedding(
            num_embeddings=emb_count,
            embedding_dim=emb_dim,
            padding_idx=0,
        )

        self.rnn = nn.GRU(
            input_size=emb_dim,
            hidden_size=enc_hid_dim,
            dropout=dropout,
            bidirectional=True,
            batch_first=True,
            num_layers=num_layers,
        )
        self.dropout = nn.Dropout(dropout)
        self.fc = nn.Linear(2 * num_layers * enc_hid_dim, dec_hid_dim)

    def get_initial_state(self, inp):
        shape = self.rnn.get_expected_hidden_size(inp, None)
        return torch.zeros(shape).to(self.device)

    def forward(self, x):
        x = x.to(self.device)
        lens = (x != 0).sum(dim=1)
        x = self.embeddings(x)
        packed = torch.nn.utils.rnn.pack_padded_sequence(
            x,
            lengths=lens,
            batch_first=True,
            enforce_sorted=False
        )
        states, last_hidden = self.rnn(packed, self.get_initial_state(x))
        states, lens = torch.nn.utils.rnn.pad_packed_sequence(states, batch_first=True)
        last_hidden = torch.cat([*last_hidden], dim=1)

        last_hidden = self.fc(last_hidden)
        last_hidden = torch.tanh(last_hidden)
        last_hidden = self.dropout(last_hidden)

        return (states, lens), last_hidden


import os
import subprocess
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import random

def main ( app ):

    df = pd.DataFrame()

    index = pd.MultiIndex.from_arrays([['insert' for i in range(0,3)]+['find' for i in range(0,3)], ['best_case', 'average_case', 'worst_case']*2])
    df_stats = pd.DataFrame(columns = index)

    for i in range(start, stop+1, step):

        file_name = './data/test_n_'+str(i)+'.txt'
        file = open( file_name , 'r' );

        data_dict = { "insert" : [] , "find" : [] }

        for line in file:

            command = 'java -cp bin '+app+' '+stage(line)+' '+day(line)+' '+time(line)+' '+file_name+' > ./logs/logs.txt'
            #cmd = command.split()
            print(command)
            os.system(command)

            with open('./logs/logs.txt', 'r') as output:
                output_to_dict(data_dict, [line.strip() for line in output.readlines()])

        with open('./logs/insert_log.txt', 'r') as insert_log:
            for j in insert_log.readlines():
                data_dict['insert'].append( int(j) )

        index = pd.MultiIndex.from_arrays([ [i,i], ['insert', 'find'] ])

        df_n = pd.DataFrame(data=np.array([data_dict['insert'], data_dict['find']]).T , columns=index)

        #df_stats.loc[i] = [df_n[i]['insert'].min() ,df_n[i]['insert'].sum()/i , df_n[i]['insert'].max(), df_n[i]['find'].min(), df_n[i]['find'].sum()/i, df_n[i]['find'].max()]
        df_stats.loc[i] = [df_n[i]['insert'].min() ,df_n[i]['insert'].sum()/int(i) , df_n[i]['insert'].max(), df_n[i]['find'].min(), df_n[i]['find'].sum()/int(i), df_n[i]['find'].max()]
        df = pd.concat([df, df_n], axis=1, sort=False)

    with open('./logs/test_'+app+'_raw_data.csv', 'w') as out:
        df.to_csv(out)
        out.close()

    with open('./logs/test_'+app+'_statistics.csv', 'w') as stats:
        df_stats.to_csv(stats)
        stats.close()

    axes = df_stats.plot.line()
    plt.savefig('./logs/'+app+'_graphs.png')
    #plt.show()

def output_to_dict( dict, output):
    comparison = int( output[2].split('\t')[1] )
    dict['find'].append(comparison)

def stage(line):
    return line[0]

def day(line):
    return line[2 : line.rindex('_')]

def time(line):
    rindex = line.rindex('_')
    return line[ rindex + 1 : rindex+3]

def generate (start, stop, step):
    f_data = open("./data/data.txt", 'r')
    data = f_data.readlines()

    for n in range(start, stop+1, step):

        f_n = open("./data/test"+"_n_"+str(n)+".txt", 'w')
        indeces = random.sample(range(2976), n)

        for index in indeces:
            f_n.write(data[index])

        f_n.close()

    f_data.close()

if __name__ == "__main__":

    usrInput = input("Press Enter for default test \nManual testing enter {start} {stop} {step}\nThe input must be space seperated eg: 2 19 16\n input >")

    start = 297
    stop = 2976
    step = 296

    if len(usrInput) > 1:
        lst = usrInput.strip().split(" ")
        start = int(lst[0])
        stop = int(lst[1])
        step = int(lst[2])

    generate(start, stop, step)
    main('LSBSTApp')
    main('LSAVLTApp')


import webapp2
import templater
from models import BlogModel, UserModel
from cookies import getUserFromRequest
import logging
import time

class EditBlogHandler(webapp2.RequestHandler):
    def get(self, blog_id):
        user = getUserFromRequest(self.request)  # type: UserModel
        post = BlogModel.get_by_id(int(blog_id))  # type:BlogModel

        if not user:
            # redirect to sign up page in case user is not found in the db
            self.redirect("/signin")
        elif not post:
            self.response.write("blog entry not found")
        elif post.author.key().id() == user.key().id():
            self.response.write(templater.render_edit_post(post=post))
        else:
            # redirect to users blog entries to choose one
            self.redirect('/blog/all')

    def post(self, blog_id):
        title = self.request.get("title")
        content = self.request.get("content")
        post = BlogModel.get_by_id(long(blog_id))  # type:BlogModel
        user = getUserFromRequest(self.request)  # type: UserModel
        if title and content and post.author.key().id() == user.key().id():
            # user is authorised to make changes
            if self.request.get('edit'):
                # update the post contents
                post.content = content
                post.title = title
                post.put()
                self.redirect("/blog/%s" % (blog_id))
            elif self.request.get('delete'):
                # delete post is triggered and got confirmation from user
                post.delete()
            # redirect to user home. If we return user entries, it will list old posts as well
            self.redirect('/welcome')
        elif user:
            # redirect to user blog entries
            self.redirect('/blog/user')
        else:
            self.redirect("/signin")


# coding:utf-8
# author: Wang Chao
# File: FrequencyAnalyzer.py
# date: 2016.12.13

from PyQt4 import QtGui
from PyQt4 import QtCore
import sys
import time
import serial
import serial.tools.list_ports
from collections import OrderedDict
from mplCanvas import MplCanvas
from controls import MyEdit, MyLabel, MyButton, MyComboBox
from drawThread import DrawCanvasThread
from getDataThread import GetDataThread
# _fromUtf8 = QtCore.QString.fromUtf8

# ========================================== Main Window Class =========================================================

class MainWindow(QtGui.QMainWindow):

    stop_thread_signal = QtCore.pyqtSignal()

    # thread_enable_draw_signal = QtCore.pyqtSignal()

    def __init__(self, force_port_num=None, parent=None):
        super(MainWindow, self).__init__(parent)
        self.force_port_num = force_port_num
        # self.setFixedSize(800, 500)
        self.resize(800, 600)
        # self.setWindowFlags(QtCore.Qt.WindowMinimizeButtonHint)
        self.setWindowTitle('Frequency Analyzer')

        # self.freqPointLabel = MyLabel('Frequency\nPoint (MHz) :')
        # self.freqPointLabel.setAlignment(QtCore.Qt.AlignCenter)
        # self.freqPointLabel.setFont(QtGui.QFont("Calibri", 12))
        self.freqPointEdit = MyEdit('908.0')
        self.freqPointEdit.setFont(QtGui.QFont("Calibri", 16))
        self.freqPointEdit.setFixedWidth(60)
        self.connect(self.freqPointEdit, QtCore.SIGNAL('returnPressed()'), self.freq_point_change)

        self.spectrumModeButton = MyButton('Spectrum\nAnalysis')
        self.spectrumModeButton.setFont(QtGui.QFont("Aharoni", 12))
        self.spectrumModeButton.setDisabled(True)
        self.connect(self.spectrumModeButton, QtCore.SIGNAL('clicked()'), self.spectrum_mode)
        self.timeModeButton = MyButton('Freq Point\nAnalysis')
        self.timeModeButton.setFont(QtGui.QFont("Aharoni", 13))
        self.connect(self.timeModeButton, QtCore.SIGNAL('clicked()'), self.time_mode)

        self.serialPortLabel = MyLabel('Serial Port :')
        self.serialPortComboBox = MyComboBox()
        self.serialPortComboBox.pressed_signal.connect(self.press_serial_port_combobox)
        self.serialPortChangeButton = QtGui.QPushButton('Change Serial\nPort')
        self.connect(self.serialPortChangeButton, QtCore.SIGNAL('clicked()'), self.change_serial_port)

        self.show_canvas = MplCanvas()
        self.show_canvas.canvas_clicked_signal.connect(self.show_click_position)

        self.startFreqShowLabel = MyLabel('Start Freq (MHz):')
        self.startFreqShowEdit = MyEdit('850.0')
        self.startFreqShowEdit.setFixedWidth(50)
        self.connect(self.startFreqShowEdit, QtCore.SIGNAL('returnPressed()'), self.start_stop_freq_show_change)
        self.stopFreqShowLabel = MyLabel('Stop Freq (MHz):')
        self.stopFreqShowEdit = MyEdit('928.0')
        self.stopFreqShowEdit.setFixedWidth(50)
        self.connect(self.stopFreqShowEdit, QtCore.SIGNAL('returnPressed()'), self.start_stop_freq_show_change)
        self.setDefaultFreqButton = QtGui.QPushButton('Set Default')
        self.setDefaultFreqButton.setFixedWidth(100)
        self.connect(self.setDefaultFreqButton, QtCore.SIGNAL('clicked()'), self.set_default_freq_start_stop)

        self.time_mode_x_show_length = 5
        self.show_canvas.canvas_time_mode_x_show_length = self.time_mode_x_show_length
        self.timeScaleLabel = MyLabel('Time Scale (Seconds):')
        self.timeScaleEdit = MyEdit(str(self.time_mode_x_show_length))
        self.timeScaleEdit.setFixedWidth(40)
        self.timeScaleEdit.setDisabled(True)
        self.connect(self.timeScaleEdit, QtCore.SIGNAL('returnPressed()'), self.time_scale_change)

        self.mark1Button = QtGui.QPushButton('Mark1')
        self.mark1Button.setDisabled(True)
        self.mark1Button.setStyleSheet('''color:red''')
        self.connect(self.mark1Button, QtCore.SIGNAL('clicked()'), self.mark1_button_clicked)
        self.mark2Button = QtGui.QPushButton('Mark2')
        self.mark2Button.setStyleSheet('''color:green''')
        self.connect(self.mark2Button, QtCore.SIGNAL('clicked()'), self.mark2_button_clicked)
        self.mark1Label = MyLabel()
        mark1_pe = QtGui.QPalette()
        mark1_pe.setColor(QtGui.QPalette.WindowText, QtCore.Qt.red)
        self.mark1Label.setPalette(mark1_pe)
        self.mark2Label = MyLabel()
        mark2_pe = QtGui.QPalette()
        mark2_pe.setColor(QtGui.QPalette.WindowText, QtCore.Qt.darkGreen)
        self.mark2Label.setPalette(mark2_pe)
        self.deltaTitleLabel = MyLabel('Delta ')
        self.deltaContentLabel = MyLabel()
        delta_pe = QtGui.QPalette()
        delta_pe.setColor(QtGui.QPalette.WindowText, QtCore.Qt.darkGray)
        self.deltaTitleLabel.setPalette(delta_pe)
        self.deltaContentLabel.setPalette(delta_pe)

        self.realTimeButton = MyButton('RealTime', self)
        self.connect(self.realTimeButton, QtCore.SIGNAL('clicked()'), self.show_real_time)
        self.accumulateButton = MyButton('Accumulate', self)
        self.connect(self.accumulateButton, QtCore.SIGNAL('clicked()'), self.show_accumulate)
        self.maxButton = MyButton('Maximum', self)
        self.connect(self.maxButton, QtCore.SIGNAL('clicked()'), self.show_max)
        self.startButton = MyButton('Start', self)
        self.startButton.setFont(QtGui.QFont("Calibri", 15))
        self.connect(self.startButton, QtCore.SIGNAL('clicked()'), self.start_show)
        self.stopButton = MyButton('Stop', self)
        self.stopButton.setFont(QtGui.QFont("Calibri", 15))
        self.connect(self.stopButton, QtCore.SIGNAL('clicked()'), self.stop_show)

        self.frame1 = QtGui.QFrame()
        self.frame1.setFrameShape(QtGui.QFrame.StyledPanel)
        frame1_grid = QtGui.QGridLayout()
        frame1_grid.addWidget(self.spectrumModeButton, 0, 0, 1, 1, QtCore.Qt.AlignCenter)
        # frame1_grid.addWidget(self.freqPointLabel, 0, 1, 1, 1, QtCore.Qt.AlignRight)
        frame1_grid.addWidget(self.timeModeButton, 0, 1, 1, 1, QtCore.Qt.AlignCenter)
        frame1_grid.addWidget(self.freqPointEdit, 0, 2, 1, 1, QtCore.Qt.AlignLeft)
        frame1_grid.addWidget(self.serialPortLabel, 0, 4, 1, 1, QtCore.Qt.AlignRight)
        frame1_grid.addWidget(self.serialPortComboBox, 0, 5, 1, 1, QtCore.Qt.AlignLeft)
        frame1_grid.addWidget(self.serialPortChangeButton, 0, 6, 1, 1, QtCore.Qt.AlignLeft)

        frame1_grid.addWidget(self.show_canvas, 1, 0, 1, 7, QtCore.Qt.AlignCenter)

        # grid.addWidget(testEdit, 6, 0, 1, 6, QtCore.Qt.AlignCenter)
        # grid.addWidget(self.mark_frame, 2, 3, 2, 3, QtCore.Qt.AlignRight)

        frame1_grid.addWidget(self.startFreqShowLabel, 2, 0, 1, 1, QtCore.Qt.AlignRight)
        frame1_grid.addWidget(self.startFreqShowEdit, 2, 1, 1, 1, QtCore.Qt.AlignLeft)
        frame1_grid.addWidget(self.stopFreqShowLabel, 3, 0, 1, 1, QtCore.Qt.AlignRight)
        frame1_grid.addWidget(self.stopFreqShowEdit, 3, 1, 1, 1, QtCore.Qt.AlignLeft)
        frame1_grid.addWidget(self.setDefaultFreqButton, 4, 0, 1, 1, QtCore.Qt.AlignRight)

        frame1_grid.addWidget(self.timeScaleLabel, 2, 2, 1, 1, QtCore.Qt.AlignRight)
        frame1_grid.addWidget(self.timeScaleEdit, 2, 3, 1, 1, QtCore.Qt.AlignLeft)

        frame1_grid.addWidget(self.mark1Button, 2, 4, 1, 1, QtCore.Qt.AlignRight)
        frame1_grid.addWidget(self.mark1Label, 2, 5, 1, 2, QtCore.Qt.AlignLeft)
        frame1_grid.addWidget(self.mark2Button, 3, 4, 1, 1, QtCore.Qt.AlignRight)
        frame1_grid.addWidget(self.mark2Label, 3, 5, 1, 2, QtCore.Qt.AlignLeft)
        frame1_grid.addWidget(self.deltaTitleLabel, 4, 4, 1, 1, QtCore.Qt.AlignRight)
        frame1_grid.addWidget(self.deltaContentLabel, 4, 5, 1, 2, QtCore.Qt.AlignLeft)

        # self.frame1.setLayout(frame1_grid)
        #
        # self.frame2 = QtGui.QFrame()
        # self.frame2.setFrameShape(QtGui.QFrame.StyledPanel)
        # frame2_grid = QtGui.QGridLayout()

        frame1_grid.addWidget(self.realTimeButton, 5, 0, 1, 1, QtCore.Qt.AlignCenter)
        frame1_grid.addWidget(self.accumulateButton, 5, 1, 1, 1, QtCore.Qt.AlignCenter)
        frame1_grid.addWidget(self.maxButton, 5, 2, 1, 1, QtCore.Qt.AlignCenter)
        frame1_grid.addWidget(self.startButton, 5, 5, 1, 1, QtCore.Qt.AlignCenter)
        frame1_grid.addWidget(self.stopButton, 5, 6, 1, 1, QtCore.Qt.AlignCenter)

        self.frame1.setLayout(frame1_grid)

        # splitter_vertical = QtGui.QSplitter(QtCore.Qt.Vertical)
        # splitter_vertical.addWidget(self.frame1)
        # splitter_vertical.addWidget(self.frame2)

        self.setCentralWidget(self.frame1)

        self.statusBar = QtGui.QStatusBar(self)
        self.statusBar.setObjectName('statusBar')
        self.setStatusBar(self.statusBar)
        self.statusLeftLabel = QtGui.QLabel('')
        self.statusLeftLabel.setAlignment(QtCore.Qt.AlignLeft)
        # self.statusBar.addPermanentWidget(self.statusLeftLabel, 0)
        self.statusBar.addWidget(self.statusLeftLabel, 0)

        self.show_canvas.draw_enable_flag = True
        # self.show_accumulate_flag = False
        self.show_max_flag = False
        # self.stop_show_flag = False
        self.show_mode = 'spectrum'
        self.stop_get_data_flag = False
        # for starting mode match
        self.mode_changing_flag = True
        self.time_mode_frequency = 0
        self.time_mode_start_time = 0

        self.spectrum_data = OrderedDict()
        self.time_data_x = []
        self.time_data_y = []

        # thread to draw the canvas
        self.drawCanvasThread = DrawCanvasThread(self, self.show_canvas)
        # self.connect(self.drawCanvasThread, QtCore.SIGNAL('draw_canvas_signal(float)'), self.draw_canvas)
        # self.drawCanvasThread.draw_canvas_signal.connect(self.draw_canvas)
        # self.thread_enable_draw_signal.connect(self.drawCanvasThread.enable_draw)
        # thread to get the data
        self.getDataThread = GetDataThread(self)
        # self.getDataThread.set_thread_function(self.get_data)

        self.serial_port = serial.Serial()
        self.serial_port.baudrate = 115200
        self.serial_port.timeout = 0.1
        # get the serial port list
        self.port_list = list(serial.tools.list_ports.comports())
        for p in self.port_list:
            self.serialPortComboBox.addItem(p[0])

        self.stop_thread_signal.connect(self.drawCanvasThread.stop)
        self.stop_thread_signal.connect(self.getDataThread.stop)

        self.init_serial_port()
        self.start()

    # @staticmethod
    # def draw_canvas(self, x, y):
    #     # print('draw_canvas')
    #     if self.show_mode == 'spectrum':
    #         self.show_canvas.draw_data(x, y, self.show_mode)
    #     if self.show_mode == 'time':
    #         draw_title = ('%.1f' % (float(self.main_window.time_mode_frequency) / 10)) + 'MHz Signal Strength'
    #         self.show_canvas.draw_data(x, y, self.show_mode, title=draw_title)
    #     self.thread_enable_draw_signal.emit()

    @QtCore.pyqtSlot()
    def press_serial_port_combobox(self):
        print('refresh serial port list..')
        self.serialPortComboBox.clear()
        self.port_list = list(serial.tools.list_ports.comports())
        for p in self.port_list:
            self.serialPortComboBox.addItem(p[0])

    @QtCore.pyqtSlot()
    def mark1_button_clicked(self):
        self.show_canvas.mark_number = 1
        self.mark1Button.setDisabled(True)
        self.mark2Button.setDisabled(False)

    @QtCore.pyqtSlot()
    def mark2_button_clicked(self):
        self.show_canvas.mark_number = 2
        self.mark1Button.setDisabled(False)
        self.mark2Button.setDisabled(True)

    @QtCore.pyqtSlot()
    def set_default_freq_start_stop(self):
        self.show_canvas.start_freq = 850
        self.startFreqShowEdit.setText('850.0')
        self.show_canvas.stop_freq = 928
        self.stopFreqShowEdit.setText('928.0')

    @QtCore.pyqtSlot()
    def time_scale_change(self):
        try:
            time_scale_pre = float(self.timeScaleEdit.text())
        except Exception as e:
            print(e)
            return
        if time_scale_pre < 0.1:
            print('time scale too small')
            return
        if time_scale_pre > 3600:
            print('time scale too long')
            return
        self.time_mode_x_show_length = time_scale_pre
        self.show_canvas.canvas_time_mode_x_show_length = self.time_mode_x_show_length
        self.set_freq_point()
        # self.mode_changing_flag = True

    @QtCore.pyqtSlot()
    def start_stop_freq_show_change(self):
        if len(self.startFreqShowEdit.text()) < 3 or len(self.startFreqShowEdit.text()) > 5:
            print('wrong frequency length, please enter like \'XXX.X\' or \'XXX\'')
        try:
            start_freq_show_pre = float(self.startFreqShowEdit.text())
        except Exception as e:
            print(e)
            return
        if start_freq_show_pre < 850 or start_freq_show_pre > self.show_canvas.stop_freq:
            print('wrong frequency, range:850 to %d' % self.show_canvas.stop_freq)
            return

        if len(self.stopFreqShowEdit.text()) < 3 or len(self.stopFreqShowEdit.text()) > 5:
            print('wrong frequency length, please enter like \'XXX.X\' or \'XXX\'')
        try:
            stop_freq_show_pre = float(self.stopFreqShowEdit.text())
        except Exception as e:
            print(e)
            return
        if stop_freq_show_pre < self.show_canvas.start_freq or stop_freq_show_pre > 928:
            print('wrong frequency, range:%d to 928' % self.show_canvas.start_freq)
            return

        self.show_canvas.start_freq = start_freq_show_pre
        self.show_canvas.stop_freq = stop_freq_show_pre

    def set_freq_point(self):
        if len(self.freqPointEdit.text()) < 3 or len(self.freqPointEdit.text()) > 5:
            print('wrong frequency length, please enter like \'XXX.X\' or \'XXX\'')
            return False
        try:
            time_mode_frequency_pre = float(self.freqPointEdit.text())
        except Exception as e:
            print(e)
            return False
        if time_mode_frequency_pre < 850 or time_mode_frequency_pre > 928:
            print('wrong frequency, range:850 to 928')
            return False
        self.time_mode_frequency = int(time_mode_frequency_pre * 10)
        print('set frequency: %f' % (float(self.time_mode_frequency)/10))
        self.clear_mark()
        self.mode_changing_flag = True
        return True

    def clear_mark(self):
        self.show_canvas.mark_number = 1
        self.show_canvas.mark1_x = None
        self.show_canvas.mark1_y = None
        self.show_canvas.mark2_x = None
        self.show_canvas.mark2_x = None
        self.mark1Label.setText('')
        self.mark2Label.setText('')
        self.deltaContentLabel.setText('')
        self.mark1_button_clicked()

    @QtCore.pyqtSlot()
    def freq_point_change(self):
        if self.show_mode != 'time':
            self.time_mode()
        else:
            self.set_freq_point()
            # self.mode_changing_flag = True

    @QtCore.pyqtSlot()
    def time_mode(self):
        if self.set_freq_point() is False:
            return
        print('start change mode to time mode...')
        self.show_mode = 'time'
        # self.mode_changing_flag = True
        self.startFreqShowEdit.setDisabled(True)
        self.stopFreqShowEdit.setDisabled(True)
        self.setDefaultFreqButton.setDisabled(True)
        self.timeScaleEdit.setDisabled(False)
        self.realTimeButton.hide()
        self.accumulateButton.hide()
        self.maxButton.hide()
        self.spectrumModeButton.setDisabled(False)
        self.timeModeButton.setDisabled(True)

    @QtCore.pyqtSlot()
    def spectrum_mode(self):
        # if self.show_mode == 'spectrum':
        #     print('already spectrum mode')
        #     return
        print('start change mode to spectrum mode...')
        self.show_mode = 'spectrum'
        self.mode_changing_flag = True
        self.startFreqShowEdit.setDisabled(False)
        self.stopFreqShowEdit.setDisabled(False)
        self.setDefaultFreqButton.setDisabled(False)
        self.timeScaleEdit.setDisabled(True)
        self.clear_mark()
        self.realTimeButton.show()
        self.accumulateButton.show()
        self.maxButton.show()
        self.realTimeButton.setDisabled(True)
        self.accumulateButton.setDisabled(False)
        self.maxButton.setDisabled(False)
        self.spectrumModeButton.setDisabled(True)
        self.timeModeButton.setDisabled(False)

    @QtCore.pyqtSlot()
    def show_real_time(self):
        self.show_canvas.accumulate_flag = False
        self.show_max_flag = False
        self.realTimeButton.setDisabled(True)
        self.accumulateButton.setDisabled(False)
        self.maxButton.setDisabled(False)

    @QtCore.pyqtSlot()
    def show_accumulate(self):
        self.show_canvas.accumulate_flag = True
        self.show_max_flag = False
        self.realTimeButton.setDisabled(False)
        self.accumulateButton.setDisabled(True)
        self.maxButton.setDisabled(False)

    @QtCore.pyqtSlot()
    def show_max(self):
        self.show_canvas.accumulate_flag = False
        self.show_max_flag = True
        self.realTimeButton.setDisabled(False)
        self.accumulateButton.setDisabled(False)
        self.maxButton.setDisabled(True)

    @QtCore.pyqtSlot()
    def start_show(self):
        if self.show_mode == 'time':
            self.time_mode_start_time = time.time()
            self.time_data_x = []
            self.time_data_y = []
            # this equal to the up 3
            # self.mode_changing_flag = True
            # clean the serial port buffer
        self.serial_port.close()
        self.serial_port.open()
        self.stop_get_data_flag = False
        # self.show_canvas.draw_enable_flag = True
        self.startButton.setDisabled(True)
        self.stopButton.setDisabled(False)

    @QtCore.pyqtSlot()
    def stop_show(self):
        self.stop_get_data_flag = True
        # self.show_canvas.draw_enable_flag = False
        self.startButton.setDisabled(False)
        self.stopButton.setDisabled(True)

    @QtCore.pyqtSlot()
    def show_click_position(self):
        if self.show_mode == 'spectrum':
            if self.show_canvas.mark_number == 1:
                self.mark1Label.setText((':    %.2f MHz' % self.show_canvas.mark1_x) +
                                        (':    %.2f dbm' % self.show_canvas.mark1_y))
            elif self.show_canvas.mark_number == 2:
                self.mark2Label.setText((':    %.2f MHz' % self.show_canvas.mark2_x) +
                                        (':    %.2f dbm' % self.show_canvas.mark2_y))
            if self.show_canvas.mark1_x is not None and \
                    self.show_canvas.mark1_y is not None and \
                    self.show_canvas.mark2_x is not None and \
                    self.show_canvas.mark2_y is not None:
                self.deltaContentLabel.setText(
                    (':     %.2f MHz' % (self.show_canvas.mark2_x - self.show_canvas.mark1_x)) +
                    (':      %.2f dbm' % (self.show_canvas.mark2_y - self.show_canvas.mark1_y)))
        elif self.show_mode == 'time':
            if self.show_canvas.mark_number == 1:
                self.mark1Label.setText((':    %.6f second' % self.show_canvas.mark1_x) +
                                        (':    %.2f dbm' % self.show_canvas.mark1_y))
            elif self.show_canvas.mark_number == 2:
                self.mark2Label.setText((':    %.6f second' % self.show_canvas.mark2_x) +
                                        (':    %.2f dbm' % self.show_canvas.mark2_y))
            if self.show_canvas.mark1_x is not None and \
                    self.show_canvas.mark1_y is not None and \
                    self.show_canvas.mark2_x is not None and \
                    self.show_canvas.mark2_y is not None:
                self.deltaContentLabel.setText(
                    (':     %.6f second' % (self.show_canvas.mark2_x - self.show_canvas.mark1_x)) +
                    (':      %.2f dbm' % (self.show_canvas.mark2_y - self.show_canvas.mark1_y)))

    @QtCore.pyqtSlot()
    def change_serial_port(self):
        if self.serial_port.isOpen():
            print('port: %s is opening, now close' % self.serial_port.port)
            self.getDataThread.close_port_flag = True
            time.sleep(0.3)

        if self.serial_port.isOpen():
            print('port: %s still open' % self.serial_port.port)
            return
        else:
            print('port: %s closed!' % self.serial_port.port)
        self.serial_port.port = str(self.serialPortComboBox.currentText())
        self.statusLeftLabel.setText('Serial Port :  ' + self.serial_port.port)
        self.start()

    def init_serial_port(self):
        # set the serial port number
        auto_set_port = False
        for port in self.port_list:
            print(port[1].decode("GB2312"))
            # print(port[1].decode( "GBK"))
            if port[1].startswith('Prolific') or port[1].startswith('USB-SERIAL CH340'):
                self.serial_port.port = port[0]
                self.statusLeftLabel.setText('Serial Port :  ' + port[1])
                # set the ComboBox to correct port
                for index in range(self.serialPortComboBox.count()):
                    if port[0] == self.serialPortComboBox.itemText(index):
                        self.serialPortComboBox.setCurrentIndex(index)
                auto_set_port = True
        if auto_set_port is False:
            self.statusLeftLabel.setText('Serial Port :  ' + 'Not find serial port!')
            print('Did not find serial port!')

        if self.force_port_num is not None:
            self.serial_port.port = self.force_port_num
            self.statusLeftLabel.setText('Serial Port :  ' + self.force_port_num)

    def start(self):
        try:
            self.serial_port.open()
            print('open serial port %s' % self.serial_port.port)
        except Exception as e:
            self.statusLeftLabel.setText('Serial Port :  ' + e.message)
            print(e)
            return

        for f_pre in range(8500, 9280):
            self.spectrum_data[(float(f_pre)/10)] = None
        self.mode_changing_flag = True
        # print(self.getDataThread.isRunning())
        self.getDataThread.start(QtCore.QThread.HighPriority)
        time.sleep(0.1)
        self.drawCanvasThread.start(QtCore.QThread.LowPriority)
        self.realTimeButton.setDisabled(True)
        self.startButton.setDisabled(True)
        # print(self.getDataThread.isRunning())

    def closeEvent(self, *args, **kwargs):
        self.stop_thread_signal.emit()
        # self.serial_port.close()
        super(MainWindow, self).closeEvent(*args, **kwargs)

# ======================================================================================================================
# ======================================================================================================================

if __name__ == '__main__':
    app = QtGui.QApplication(sys.argv)
    ui = MainWindow(force_port_num=None)
    ui.show()
    sys.exit(app.exec_())


#!/usr/bin/env python

class Group(object):
    def __init__(self, _name):
        self.name = _name
        self.groups = []
        self.users = []

    def add_group(self, group):
        self.groups.append(group)

    def add_user(self, user):
        self.users.append(user)

    def get_groups(self):
        return self.groups

    def get_users(self):
        return self.users

    def get_name(self):
        return self.name

parent = Group("parent")
child = Group("child")
sub_child = Group("subchild")

sub_child_user = "sub_child_user"
sub_child.add_user(sub_child_user)

child.add_group(sub_child)
parent.add_group(child)

def is_user_in_group(user, group):

    """
    Return True if user is in the group, False otherwise.

    Args:
      user(str): user name/id
      group(class:Group): group to check user membership against

	parent -- child -- sub_child
	-- groups[child]
	-- users
	child
	-- groups[sub_child]
	-- users[]
	sub_child
	-- groups[]
	-- users[sub_child_user]

    """

    if user in group.get_users():
        return True
    if group.groups:
        for gr in group.get_groups():
            if is_user_in_group(user,gr):
                return True
    return False

parent.add_user("Tom")
parent.add_user("Jame")
parent.add_user("White")

child.add_user("Jane")
child.add_user("Jennifer")
child.add_user("Alice")
child.add_user("Eve")

sub_child.add_user("Cat")
sub_child.add_user("Dog")
sub_child.add_user("Horse")

is_user_in_group('Tom',parent)  # True
is_user_in_group('Jane',parent) # True
is_user_in_group('Jane',child) # True
is_user_in_group('Jane',sub_child) # False
is_user_in_group('Cat',parent) # True
is_user_in_group('Cat',child) # True
is_user_in_group('Cat',sub_child) # True


class Found_card:

    def __init__(self, headline, href, thumbnail, bidCount, price):
        self.headline = headline
        self.href = href
        self.thumbnail = thumbnail
        self.bidCount = bidCount
        self.price = price

    def print_card_cell(self,hits_writer):
        hits_writer.write('')
        hits_writer.write('
')
        hits_writer.write('' + self.headline + '
')
        hits_writer.write(self.bidCount + " " + self.price + "	")
        return


"""
给定一个整数数组和一个整数k，判断数组中是否存在两个不同的索引i和j，
使得nums [i] = nums [j]，并且 i 和 j的差的 绝对值 至多为 k。

示例1:
输入: nums = [1,2,3,1], k = 3
输出: true

示例 2:
输入: nums = [1,0,1,1], k = 1
输出: true

示例 3:
输入: nums = [1,2,3,1,2,3], k = 2
输出: false

"""

"""
双哈希表比较法
先把两个哈希表写出来
然后比较值是不是一样的
"""
#大神做法1
class Solution:
    def isIsomorphic(self, s: str, t: str) -> bool:
        if s == "" and t == "":
            return True

        if s == "" or t == "":
            return False

        hashmap_s = {}
        hashmap_t = {}

        # 对s中的字符进行录入，值为各个字符出现的下标
        for i, n in zip(s, range(len(s))):
            if i not in hashmap_s:
                hashmap_s[i] = [n]
            else:
                hashmap_s[i].append(n)

        # 对t中的字符进行录入，值为各个字符出现的下标
        for i, n in zip(t, range(len(t))):
            if i not in hashmap_t:
                hashmap_t[i] = [n]
            else:
                hashmap_t[i].append(n)

        # 对比两个哈希表值是否相同
        for value in hashmap_s.values():
            if value not in hashmap_t.values():
                return False

        return True

"""
双哈希表
互相映射
"""
#大神做法2
class Solution:
    def isIsomorphic(self, s: str, t: str) -> bool:
        a2b, b2a = {}, {}
        n = len(s)
        for i in range(n):
            a, b = s[i], t[i]
            if (a in a2b and a2b[a] != b) or (b in b2a and b2a[b] != a):#是否互相映射
                return False
            a2b[a] = b
            b2a[b] = a
        return True

205、同构字符串.py

205、同构字符串.py


from django.urls import path

from .views import RegistroAlta, ListarPacientes, GerenciarPacientes, AtualizarPaciente, DeletarRegistro, FiltrarBusca

urlpatterns = [
    path("", GerenciarPacientes, name="GerenciarPacientes"),
    path("RegistroAlta/", RegistroAlta, name="RegistroAlta"),
    path("ListarPacientes/", ListarPacientes, name="ListarPacientes"),
    path("AtualizarPaciente/<int:id>/", AtualizarPaciente, name="AtualizarPaciente"),
    path("DeletarRegistro/<int:id>/", DeletarRegistro, name="DeletarRegistro"),
    path("FiltrarBusca/<int:opcao>/<str:filtro>/", FiltrarBusca, name="FiltrarBusca"),
]


import cv2
import numpy as np

## Read
img = cv2.imread("images/anip.jpg")

## convert to hsv
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)

mask = cv2.inRange(hsv, (0, 130, 20), (20, 255,255))

## slice the green
imask = mask>0
green = np.zeros_like(img, np.uint8)
green[imask] = img[imask]

## save
cv2.imwrite("images/ball_mask.png", green)


from classifier import Classifier
import cv2
import numpy as np
from datetime import datetime

# available descriptor for Classifier
from descriptors import ORB_Descriptor, SIFT_Descriptor

# available classification models for Classifier
from sklearn.tree import DecisionTreeClassifier
from sklearn.naive_bayes import GaussianNB
from sklearn.naive_bayes import MultinomialNB
from sklearn.ensemble import AdaBoostClassifier

model = Classifier(descriptor=SIFT_Descriptor())
model.fit("with_object", "without_object")
# model.process_video("video_to_check.MOV", (640, 480), fps=30)

cap = cv2.VideoCapture(0)
cap.set(cv2.CAP_PROP_FRAME_WIDTH, 320)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 240)
cover_img = cv2.imread("img.jpg")
myVid = cv2.VideoCapture("video.mp4")

video_frame = cv2.imread("img.jpg")
height, width, _ = cover_img.shape
video_frame = cv2.resize(video_frame, (width, height))

method = model.descriptor
method.compute(cover_img)
kp1, des1 = (method.points, method.descriptors)

bf = cv2.BFMatcher()

# fourcc = cv2.VideoWriter_fourcc(*"FMP4")
# out = cv2.VideoWriter(
#     "results/augmenting_reality.avi",
#     fourcc,
#     20,
#     (640, 480)
# )

start_time_point = datetime.now()
frame_counter = 0

while True:

    if (datetime.now() - start_time_point).seconds > 1:
        start_time_point = datetime.now()
        print(frame_counter)
        frame_counter = 0
    else:
        frame_counter += 1

    sucess, imgWebcam = cap.read()
    imgAug = imgWebcam.copy()
    method.compute(imgAug)
    kp2, des2 = (method.points, method.descriptors)

    try:
        matches = bf.knnMatch(des1, des2, k=2)
        good = []
        for m, n in matches:
            if m.distance < 0.75 * n.distance:
                good.append(m)

        if model.predict(imgWebcam):
            srcPts = np.float32([kp1[m.queryIdx].pt for m in good]).reshape(-1, 1, 2)
            dstPts = np.float32([kp2[m.trainIdx].pt for m in good]).reshape(-1, 1, 2)
            matrix, mask = cv2.findHomography(srcPts, dstPts, cv2.RANSAC, 5)
            pts = np.float32(
                [[0, 0], [0, height], [width, height], [width, 0]]
            ).reshape(-1, 1, 2)
            dst = cv2.perspectiveTransform(pts, matrix)
            imgWarp = cv2.warpPerspective(
                video_frame, matrix, (imgWebcam.shape[1], imgWebcam.shape[0])
            )

            maskNew = np.zeros((imgWebcam.shape[0], imgWebcam.shape[1]), np.uint8)
            cv2.fillPoly(maskNew, [np.int32(dst)], (255, 255, 255))
            maskInv = cv2.bitwise_not(maskNew)
            imgAug = cv2.bitwise_and(imgAug, imgAug, mask=maskInv)
            imgAug = cv2.bitwise_or(imgWarp, imgAug)
    except:
        # print("Bad frame")
        pass

    # out.write(imgAug)
    cv2.imshow("AugmentedReality", imgAug)
    if cv2.waitKey(1) & 0xFF == ord("q"):
        break


import matplotlib.pyplot as plt
import numpy as np
import streamlit as st
from scipy.stats import norm

"""
<!-- md -->

# What is Statistics

sited by [Wikipedia: Statistics](https://en.wikipedia.org/wiki/Statistics)

> Statistics is the discipline that concerns the collection, organization, analysis, interpretation and presentation of data.[1][2][3] In applying statistics to a scientific, industrial, or social problem, it is conventional to begin with a statistical population or a statistical model to be studied. Populations can be diverse groups of people or objects such as "all people living in a country" or "every atom composing a crystal". Statistics deals with every aspect of data, including the planning of data collection in terms of the design of surveys and experiments.[4] See glossary of probability and statistics.

## Normal Distribution

normal distribution in TeX

$$
  f(x)={\\frac{1}{\sqrt{2\pi \sigma^{2}}}}\exp(-{\\frac {(x-\mu )^{2}}{2\sigma^{2}}})\quad (x\in \mathbb {R})
$$

normal distribution in Python

```python
def norm(mu, sigma, x_i):
    return 1 / (sigma * np.sqrt(2 * np.pi)) * np.exp((- (x_i - mu)**2) / (2 * sigma**2))
```

<!-- end-md -->
"""

@st.cache
def load_data():
    # data: N(50, 20^2)
    mean = 50
    std = 20
    x = np.arange(start=-40, stop=140, step=0.1)
    y = norm.pdf(x, loc=mean, scale=std)
    return mean, std, x, y

def plot(mean, std, x, y):
    # plot
    plt.plot(x, y, color="b")
    plt.title(f"$N(\mu, \sigma^2) = N({mean}, {std}^2)$")
    st.pyplot()

def main():
    mean, std, x, y = load_data()
    plot(mean, std, x, y)

main()


from fastapi import FastAPI, Query
from fastapi.middleware.cors import CORSMiddleware
from typing import List

from joblib import load
from pandas import read_csv

app = FastAPI()

loaded_model = load("../model/classifier.joblib")
loaded_scaler = load("../model/scaler.joblib")
reference_table = read_csv("../model/cutoff_table.csv")

app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_methods=["*"],
    allow_headers=["*"],
)

def apply_model(
    data, duration, model=loaded_model, scaler=loaded_scaler, reference=reference_table
):
    # apply scaler & model to new meeting
    data_scaled = scaler.transform([data])
    predicted_cluster = model.predict(data_scaled)[0]
    # subset reference & rank new meeting duration
    if int(duration) >= int(
        reference[reference.cluster == int(predicted_cluster)].cutoff
    ):
        show_alert = True
    else:
        show_alert = False
    return show_alert

@app.get("/")
async def read_root():
    return {"Hello": "World"}

@app.get("/predict/")
def predict(
    meeting_data: List[str] = Query([12,8,
                                     0.1774193548387097,0.45161290322580644,0.3709677419354839,0,
                                     62,17100,
                                     0,1,0,0,0,0])
):

    data = list(map(float, meeting_data[0].split(",")))
    duration = data[7]
    kwargs = {"data": data, "duration": duration}
    print(kwargs)

    pred = apply_model(data, duration)
    return pred


import cv2
import numpy as np
import time

global video

class ChrisCam(object):
    def __init__(self,camera = 'c:/fred.avi'):
        self.cap = cv2.VideoCapture(camera)
        self.image_type = 0

    def size(self,width = 320, height = 240):
        self.cap.set(cv2.CAP_PROP_FRAME_WIDTH,width)
        self.cap.set(cv2.CAP_PROP_FRAME_HEIGHT,height)
        return self.cap.isOpened()

    def snap(self,show=True, fx=0.1, fy=0.1):
        ret,frame = self.cap.read()
        if ret:
            frame = cv2.resize(frame, None, fx=fx, fy=fy)
        if show:
            cv2.imshow('image',frame)
        return ret, frame

    def rotate(self, img, rotation):
        rows,cols,depth = img.shape
        rotationMatrix = cv2.getRotationMatrix2D((cols/2,rows/2),rotation,1)
        frame = cv2.warpAffine(img,rotationMatrix,(cols,rows))
        return frame

    def toLV(self,frame,plane = 'RGB'):      # takes around 30 ms per call
        array = frame.ravel()
        mask = np.array([])
        if not plane == 'Gray':
            image_depth = 24
            colors = np.array([])
            fixedFrame = np.empty((array.size,),dtype = array.dtype)
            if 'R' in plane:
                fixedFrame[0::3] = array[2::3]   # go from BGR ro RGB
            if 'G' in plane:
                fixedFrame[1::3] = array[1::3]
            if 'B' in plane:
                fixedFrame[2::3] = array[0::3]
        else:
            fixedFrame = np.empty((int(array.size/3),),dtype = array.dtype)
            fixedFrame[0::1] = array[0::3]# int((int(array[0::3]) + int(array[1::3]) +  int(array[2::3]) ) / 3)
            image_depth = 8
            colors = np.array([ (i | i<<8 | i<<16) for i in range(256)])  # define color map
        self.rectangle = (0,0,frame.shape[1],frame.shape[0])  # this is the LabVIEW rectangle format
        reply =  (self.image_type, image_depth,fixedFrame.tolist(),mask.tolist(),colors.tolist(),self.rectangle)
        return reply

    def toCV(self,LVimage):      # takes around 30 ms per call
        rows,cols = LVimage[5][3],LVimage[5][2]
        array = np.asarray(LVimage[2],dtype='uint8')
        fixedFrame = np.empty((array.size,),dtype = array.dtype)
        fixedFrame[0::3] = array[2::3]   # go from RGB to BGR
        fixedFrame[1::3] = array[1::3]
        fixedFrame[2::3] = array[0::3]
        img = fixedFrame.reshape(rows,cols,3)
        return img

    def close(self):
        self.cap.release()
        cv2.destroyAllWindows()
        return True

def initCam(camera = 'c:/fred.avi',width = 640, height = 480):
    global video
    video = ChrisCam(camera)
    return video.size(width,height)

def snap(show=True, rotation = 90, plane = 'RGB',fx=0.1, fy=0.1):
    ret, frame = video.snap(show,fx,fy)
    if not ret:
        return
    if not rotation == 0:
        frame = video.rotate(frame,rotation)
    return video.toLV(frame,plane)

def closeCam():
    return video.close()


# uncompyle6 version 3.7.4
# Python bytecode 2.7 (62211)
# Decompiled from: Python 3.6.9 (default, Apr 18 2020, 01:56:04)
# [GCC 8.4.0]
# Embedded file name: build/bdist.linux-x86_64/egg/wenlincms/utils/sites.py
# Compiled at: 2016-05-20 23:41:38
from __future__ import unicode_literals
import os, sys
from wenlincms.conf import settings

def has_site_permission(user):
    """
    Checks if a staff user has staff-level access for the current site.
    The actual permission lookup occurs in ``SitePermissionMiddleware``
    which then marks the request with the ``has_site_permission`` flag,
    so that we only query the db once per request, so this function
    serves as the entry point for everything else to check access. We
    also fall back to an ``is_staff`` check if the middleware is not
    installed, to ease migration.
    """
    mw = b'wenlincms.core.middleware.SitePermissionMiddleware'
    if mw not in settings.MIDDLEWARE_CLASSES:
        from warnings import warn
        warn(mw + b' missing from settings.MIDDLEWARE_CLASSES - per sitepermissions not applied')
        return user.is_staff and user.is_active
    return getattr(user, b'has_site_permission', False)

def host_theme_path(request):
    """
    Returns the directory of the theme associated with the given host.
    """
    for host, theme in settings.HOST_THEMES:
        if host.lower() == request.get_host().split(b':')[0].lower():
            try:
                __import__(theme)
                module = sys.modules[theme]
            except ImportError:
                pass
            else:
                return os.path.dirname(os.path.abspath(module.__file__))

    return b''

def templates_for_host(request, templates):
    """
    Given a template name (or list of them), returns the template names
    as a list, with each name prefixed with the device directory
    inserted into the front of the list.
    """
    if not isinstance(templates, (list, tuple)):
        templates = [
         templates]
    theme_dir = host_theme_path(request)
    host_templates = []
    if theme_dir:
        for template in templates:
            host_templates.append(b'%s/templates/%s' % (theme_dir, template))
            host_templates.append(template)

        return host_templates
    return templates


"""
2 个函数
分别用递归和栈的方式从 token 列表解析为 ast
"""

def parsed_ast(token_list):
    """
    递归解析 ast
    """
    ts = token_list
    token = ts[0]
    del ts[0]
    if token == '[':
        exp = []
        while ts[0] != ']':
            t = parsed_ast(ts)
            exp.append(t)
        # 循环结束, 删除末尾的 ']'
        del ts[0]
        return exp
    else:
        # token 需要 process_token / parsed_token
        return token

def pop_list(stack):
    l = []
    while stack[-1] != '[':
        l.append(stack.pop(-1))
    stack.pop(-1)
    l.reverse()
    return l

def parsed_ast_stack(token_list):
    """
    用栈解析 ast
    """
    l = []
    i = 0
    while i < len(token_list):
        token = token_list[i]
        i += 1
        if token == ']':
            list_token = pop_list(l)
            l.append(list_token)
        else:
            l.append(token)
    return l

def main():
    tokens1 = ['[', '+', 12, '[', '-', 23, 45, ']', ']']
    tokens2 = ['[', '+', 12, '[', '-', 23, 45, ']', ']']
    print('stack parse', parsed_ast_stack(tokens1 + tokens2))

    tokens = ['[', '+', 12, '[', '-', 23, 45, ']', ']']
    expected_ast = ['+', 12, ['-', 23, 45]]
    ast = parsed_ast(tokens)
    print('recursive parse', ast)
    assert ast == expected_ast

if __name__ == '__main__':
    main()


# uncompyle6 version 3.7.4
# Python bytecode 3.8 (3413)
# Decompiled from: Python 3.6.9 (default, Apr 18 2020, 01:56:04)
# [GCC 8.4.0]
# Embedded file name: /aehostd/ldapconn.py
# Compiled at: 2020-03-29 09:57:51
# Size of source mod 2**32: 4747 bytes
"""
aehostd.ldapconn - maintain LDAP connection
"""
import time, logging, ldap0
from ldap0.lock import LDAPLock
from aedir import AEDirObject
from .__about__ import __version__
from .cfg import CFG

def _new_ldap_connection():
    """
    Open new LDAP connection by trying all servers defined in config
    """
    logging.debug('Open new LDAP connection')
    who = cred = None
    if CFG.binddn:
        if CFG.bindpwfile:
            who = CFG.binddn
            cred = CFG.bindpwfile.read()
            if not cred:
                who = ''
    uris = CFG.get_ldap_uris()
    ldap_conn = None
    try_count = 0
    while True:
        try_count += 1
        logging.debug('%d LDAP servers left to try: %s', len(uris), ', '.join(uris))
        if not uris:
            logging.error('Failed to reach any of %d LDAP servers', len(CFG.uri_pool) + len(CFG.uri_list))
            ldap_conn = None
            break
        ldap_uri = uris.pop()
        logging.debug('Try %d. connect to %r ...', try_count, ldap_uri)
        try:
            ldap_conn = AEDirObject(ldap_uri,
              trace_level=0,
              retry_max=0,
              timeout=(CFG.timelimit),
              who=who,
              cred=cred,
              cacert_filename=(CFG.tls_cacertfile),
              client_cert_filename=(CFG.tls_cert),
              client_key_filename=(CFG.tls_key),
              cache_ttl=(CFG.cache_ttl))
        except (ldap0.LDAPError, AttributeError) as ldap_error:
            try:
                ldap_conn = None
                logging.warning('Error connecting to %r: %s', ldap_uri, ldap_error)
            finally:
                ldap_error = None
                del ldap_error

        else:
            if ldap_conn.get_whoami_dn():
                logging.info('Successfully bound to %r as %r (%r)', ldap_conn.uri, ldap_conn.get_whoami_dn(), id(ldap_conn))
                break
            ldap_conn = None

    return ldap_conn

class LDAPConnection:
    __doc__ = '\n    class for LDAP connection handling\n    '

    def __init__(self):
        self._ldap_conn_lock = LDAPLock(desc=('get_ldap_conn() in %s' % repr(self.__class__)))
        self._ldap_conn = None
        self._ldap_conn_ts = 0.0

    def disable_ldap_conn(self):
        """
        Destroy local LDAPI connection and reset it to None.
        Should be invoked when catching a ldap0.SERVER_DOWN exception.
        """
        try:
            self._ldap_conn_lock.acquire()
            if self._ldap_conn:
                self._ldap_conn.unbind_s()
        finally:
            del self._ldap_conn
            self._ldap_conn = None
            self._ldap_conn_lock.release()

    @property
    def current_ldap_uri(self):
        """
        property is LDAP URI string if connected, None else
        """
        if isinstance(self._ldap_conn, AEDirObject):
            if hasattr(self._ldap_conn, '_l'):
                return self._ldap_conn.uri

    def get_ldap_conn(self):
        """
        Open a single local LDAP connection and
        bind with locally configured credentials if possible
        """
        current_time = time.time()
        try:
            self._ldap_conn_lock.acquire()
            if isinstance(self._ldap_conn, AEDirObject) and hasattr(self._ldap_conn, '_l') and self._ldap_conn_ts + CFG.conn_ttl >= current_time and self._ldap_conn.get_whoami_dn().lower().split(',')[0] == CFG.binddn.lower().split(',')[0]:
                logging.debug('Reusing LDAP connection %s to %r', id(self._ldap_conn), self._ldap_conn.uri)
            else:
                self._ldap_conn = None
                self._ldap_conn = _new_ldap_connection()
                if self._ldap_conn is None:
                    self._ldap_conn_ts = 0.0
                else:
                    self._ldap_conn_ts = current_time
        finally:
            self._ldap_conn_lock.release()

        return self._ldap_conn

LDAP_CONN = LDAPConnection()


from typing import Tuple

import matplotlib.pyplot as plt
import numpy as np
from scipy.optimize import differential_evolution
from scipy.stats import poisson, nbinom, norm, chisquare

from .plt import histogram

def is_equal(sc1, sc2):
    sc1, sc2 = [np.asarray(i, np.int32) for i in [sc1, sc2]]
    x1, y1 = histogram(sc1)
    x2, y2 = histogram(sc2)
    x1, x2, y1, y2 = [np.array(i) for i in [x1, x2, y1, y2]]
    x_all = sorted(set(list(x1) + list(x2)))
    p1, p2 = [], []
    for n in x_all:
        if not x1[x1 == n].size or not x2[x2 == n].size:
            continue
        if y1[x1 == n][0] == 0.0 or y2[x2 == n][0] == 0.0:
            continue
        p1.append(y1[x1 == n][0])
        p2.append(y2[x2 == n][0])
    chi = chisquare(p1, p2)
    return chi

def find_best_similar(scores, mu_poisson=0.0, mu_nbinom=0.0, corr_nbinom=0.5, mu_norm=0.0, corr_norm=0.0):
    mb = np.array(scores, np.int32)
    xx, yy = histogram(scores)
    xx, yy = [np.array(i) for i in [xx, yy]]
    zz = poisson.pmf(xx, mb.mean() + mu_poisson)
    chi1 = chisquare(yy, zz)[0]
    zz = nbinom.pmf(xx, mb.mean() + mu_nbinom, corr_nbinom)
    chi2 = chisquare(yy, zz)[0]
    zz = norm.pdf(xx, mb.mean() + mu_norm, mb.std() + corr_norm)
    chi3 = chisquare(yy, zz)[0]
    random = ['poisson', 'nbinom', 'norm']
    chi = [chi1, chi2, chi3]
    best = random[chi.index(min(chi))]
    print('   Best: {}'.format(best))
    print('Poisson: {:.3f}'.format(chi[0]))
    print('Nbinom : {:.3f}'.format(chi[1]))
    print('Norm   : {:.3f}'.format(chi[2]))

def visualize(scores, xrange=None, mu_poisson=0.0, mu_nbinom=0.0, corr_nbinom=0.5, mu_norm=0.0, corr_norm=0.0):
    if xrange is None:
        xrange = np.arange(30)
    else:
        xrange = np.array(list(xrange))
    scores = np.asrray(scores)

    x, y = histogram(scores)
    plt.grid(True)
    plt.plot(x, y, 'r-', label='current', linewidth=0.5)

    y = poisson.pmf(xrange, scores.mean() + mu_poisson)
    plt.plot(xrange, y, 'y-', label='poisson')

    y = nbinom.pmf(xrange, scores.mean() + mu_nbinom, corr_nbinom)
    plt.plot(xrange, y, 'g-', label='nbinom')

    y = norm.pdf(xrange, scores.mean() + mu_norm, scores.std() + corr_norm)
    plt.plot(xrange, y, 'b-', label='norm')

    plt.legend(loc='best')
    plt.show()

def best_poisson(scores, mu_lim: Tuple[float, float] = None):
    def func(x):
        if not (x[0] >= 0.5):
            return 10000
        y = poisson.pmf(xrange, x[0])
        chi = chisquare(dist, y)[0]
        if np.isnan(chi) or np.isinf(chi):
            return 10000
        return chi

    if mu_lim is None:
        muLimMin, muLimMax = -1.0, 1.0
    else:
        muLimMin, muLimMax = mu_lim

    scores = np.array(scores)
    xrange, dist = histogram(scores)
    bounds = [(scores.mean() + muLimMin, scores.mean() + muLimMax)]

    de = differential_evolution(func, bounds)
    best = [de.x[0] - scores.mean()]
    find_best_similar(scores)
    print('\nBounds: [{:.3f}]'.format(*best))
    find_best_similar(scores, mu_poisson=best[0])
    return best

def best_nbinom(scores, mu_lim: Tuple[float, float] = None, corr_lim: Tuple[float, float] = None):
    def func(x):
        if not (x[0] >= 0.5 and 0.0 < x[1] < 1.0):
            return 10000
        y = nbinom.pmf(xrange, x[0], x[1])
        chi = chisquare(dist, y)[0]
        if np.isnan(chi) or np.isinf(chi):
            return 10000
        return chi

    if mu_lim is None:
        muLimMin, muLimMax = -2.0, 2.0
    else:
        muLimMin, muLimMax = mu_lim
    if corr_lim is None:
        corrLim = (0.4, 0.6)
    else:
        corrLim = corr_lim

    scores = np.array(scores)
    xrange, dist = histogram(scores)
    bounds = [(scores.mean() + muLimMin, scores.mean() + muLimMax), corrLim]

    de = differential_evolution(func, bounds)
    best = [de.x[0] - scores.mean(), de.x[1]]
    find_best_similar(scores)
    print('\nBounds: [{:.3f}, {:.3f}]'.format(*best))
    find_best_similar(scores, mu_nbinom=best[0], corr_nbinom=best[1])
    return best

def best_norm(scores, mu_lim: Tuple[float, float] = None, corr_lim: Tuple[float, float] = None):
    def func(x):
        if not (x[0] >= 0.5 and -20 < x[1] < 20):
            return 10000
        y = norm.pdf(xrange, x[0], x[1])
        chi = chisquare(dist, y)[0]
        if np.isnan(chi) or np.isinf(chi):
            return 10000
        return chi

    if mu_lim is None:
        muLimMin, muLimMax = -5.0, 5.0
    else:
        muLimMin, muLimMax = mu_lim
    if corr_lim is None:
        corrLimMin, corrLimMax = -5.0, 5.0
    else:
        corrLimMin, corrLimMax = corr_lim

    scores = np.array(scores)
    xrange, dist = histogram(scores)
    bounds = [(scores.mean() + muLimMin, scores.mean() + muLimMax),
              (scores.std() + corrLimMin, scores.std() + corrLimMax)]

    de = differential_evolution(func, bounds)
    best = [de.x[0] - scores.mean(), de.x[1] - scores.std()]
    find_best_similar(scores)
    print('\nBounds: [{:.3f}, {:.3f}]'.format(*best))
    find_best_similar(scores, mu_norm=best[0], corr_norm=best[1])
    return best

def proba_norm(mu, std, xrange, bk):
    xrange = np.array(list(xrange))
    p = norm.pdf(xrange, mu, std)
    over = p[xrange > bk].sum()
    under = p[xrange < bk].sum()
    al = over + under
    over, under = over / al, under / al
    over, under = round(over, 3), round(under, 3)
    return over, under


import setuptools

exec(open('MarinegeoTemplateBuilder/version.py').read())

with open("README.md", "r") as fh:
    long_description = fh.read()

setuptools.setup(
    name="MarinegeoTemplateBuilder",
    version=__version__,
    author="Andy Bell",
    author_email="bellan@si.edu",
    description="Constructs MarineGEO data entry excel workbooks with built in validation",
    long_description=long_description,
    long_description_content_type="text/markdown",
    url="https://github.com/MarineGEO/MarineGEO-template-builder",
    packages=setuptools.find_packages(),
    include_package_data=True,
    install_requires=[
        'xlsxwriter',
        'pandas',
        'chardet',
        'xlrd',
    ],
    classifiers=[
        "Programming Language :: Python :: 3",
        "License :: OSI Approved :: MIT License",
        "Operating System :: OS Independent",
    ],
)


import requests
import json
from datetime import datetime
from time import sleep

from mongoengine import connect
from pymongo import MongoClient

from database.mongo_service import MongoService

class ReviewService(MongoService):
    def __init__(self):
        super().__init__()

    def get_all_reviews(self):
        reviews = self.db.review.find()
        return reviews

    def get_review_byid(self, review_id):
        review = self.db.review.find({'id': review_id})
        return review

    def get_review_by_hotel_locationid(self, hotel_locationid):
        review = self.db.review.find({'location_id': hotel_locationid})
        return review

    def update_review_byid(self, review_id, data_update):
        review = self.db.review.update_one(
            {
                'id': review_id
            }, {
                "$set": data_update
            }
        )
        return review

    def get_lessthan_datetime(self, datenow):
        reviews = self.db.review.aggregate([
            {
                '$lookup': {
                    "from": 'hotel',
                    "localField": 'hotel_locationID',
                    "foreignField": 'location_id',
                    "as": 'hotel_detail'
                }
            },
            {
                '$match': {
                    'created_at': {'$lt': datenow}
                }
            },
            {
                "$unwind": "$hotel_detail"
            }
        ])
        return reviews

    def is_review_exist(self, review_id):
        review = self.db.review.find({'id': review_id})
        if review.count() > 0:
            return True
        else:
            return False


from django.db import models
from django.core.validators import RegexValidator
from django.forms import ModelForm
from django import forms

class customer(models.Model):

	name=models.CharField(max_length=40)
	#phone_regex = RegexValidator(regex=r'^\+?1?\d{9,15}$', message="enter in the format:'+999999999'")
	phone_number = models.CharField(max_length=10, blank=True) # validators should be a list
	email=models.EmailField(max_length=80,blank=True,null=True)
	address1=models.CharField(max_length=80,blank=True)
	address2=models.CharField(max_length=80,blank=True)
	age=models.IntegerField(default=0)

	def __str__(self):
		return self.name

class movie(models.Model):
	name=models.CharField(max_length=60)
	year=models.IntegerField()
	genre_choice=(('AC','Action'),
				('TH','Thriller'),
				('CO','Comedy'),
				('RM','Romance'),
				('AD','Adventure'),
				('FC','Fiction'),
				('SF','Sci-Fi'))
	genre=models.CharField(max_length=20,choices=genre_choice)
	lang_choice=(('EN','English'),
				('SP','Spanish'),
				('FR','French'))
	lang=models.CharField(max_length=12,choices=lang_choice)
	rent_price=models.DecimalField(max_digits=10, decimal_places=2,default=00.00)
	rented=models.BooleanField()
	customer_name=models.ForeignKey(customer,on_delete=models.SET_NULL, blank=True,null=True)

	def __str__(self):
		return self.name

class modelCustomer(ModelForm):
	class Meta:
		model=customer
		fields=['name', 'phone_number', 'email','address1','address2','age']