import os
import numpy as np
from keras.optimizers import Adam, Optimizer
from keras.models import Model
from keras.layers import Input, Dense
from keras.initializers import RandomNormal
from keras.utils import plot_model
from keras.engine.network import Network
import keras.backend as K
from PIL import Image
from cv2 import cv2 as cv
import random
import time
from colorama import Fore
from collections import deque
from typing import Union
import json
from statistics import mean
import imagesize
from multiprocessing.pool import ThreadPool

from ..utils.batch_maker import BatchMaker
from ..models import discriminator_models_spreadsheet, generator_models_spreadsheet
from ..keras_extensions.custom_tensorboard import TensorBoardCustom
from ..utils.helpers import time_to_format, get_paths_of_files_from_path

class DCGAN:
  CONTROL_THRESHOLD = 100_000 # Threshold when after whitch we will be testing training process
  AGREGATE_STAT_INTERVAL = 1_000  # Interval of saving data
  GRADIENT_CHECK_INTERVAL = 10_000  # Interval of checking norm gradient value of combined model
  CHECKPOINT_SAVE_INTERVAL = 1_000  # Interval of saving checkpoint

  def __init__(self, dataset_path:str,
               gen_mod_name: str, disc_mod_name: str,
               latent_dim:int,
               training_progress_save_path:str,
               testing_dataset_path:str=None,
               generator_optimizer:Optimizer=Adam(0.0002, 0.5), discriminator_optimizer:Optimizer=Adam(0.0002, 0.5),
               discriminator_label_noise:float=None, discriminator_label_noise_decay:float=None, discriminator_label_noise_min:float=0.001,
               batch_size: int = 32, buffered_batches:int=20,
               generator_weights:Union[str, None]=None, discriminator_weights:Union[str, None]=None,
               start_episode:int=0, load_from_checkpoint:bool=False,
               check_dataset:bool=True, num_of_loading_workers:int=8):

    self.disc_mod_name = disc_mod_name
    self.gen_mod_name = gen_mod_name
    self.generator_optimizer = generator_optimizer

    self.latent_dim = latent_dim
    assert self.latent_dim > 0, Fore.RED + "Invalid latent dim" + Fore.RESET

    self.batch_size = batch_size
    assert self.batch_size > 0, Fore.RED + "Invalid batch size" + Fore.RESET

    self.discriminator_label_noise = discriminator_label_noise
    self.discriminator_label_noise_decay = discriminator_label_noise_decay
    self.discriminator_label_noise_min = discriminator_label_noise_min

    self.progress_image_dim = (16, 9)

    if start_episode < 0: start_episode = 0
    self.episode_counter = start_episode

    # Initialize training data folder and logging
    self.training_progress_save_path = training_progress_save_path
    self.training_progress_save_path = os.path.join(self.training_progress_save_path, f"{self.gen_mod_name}__{self.disc_mod_name}")
    self.tensorboard = TensorBoardCustom(log_dir=os.path.join(self.training_progress_save_path, "logs"))

    # Create array of input image paths
    self.train_data = get_paths_of_files_from_path(dataset_path, only_files=True)
    assert self.train_data, Fore.RED + "Training dataset is not loaded" + Fore.RESET

    self.testing_data = None
    if testing_dataset_path:
      self.testing_data = get_paths_of_files_from_path(testing_dataset_path)
      assert self.testing_data, Fore.RED + "Testing dataset is not loaded" + Fore.RESET

    # Load one image to get shape of it
    tmp_image = cv.imread(self.train_data[0])
    self.image_shape = tmp_image.shape
    self.image_channels = self.image_shape[2]

    # Check image size validity
    if self.image_shape[0] < 4 or self.image_shape[1] < 4: raise Exception("Images too small, min size (4, 4)")

    # Check validity of whole datasets
    if check_dataset:
      self.validate_dataset()

    # Define static vars
    if os.path.exists(f"{self.training_progress_save_path}/static_noise.npy"):
      self.static_noise = np.load(f"{self.training_progress_save_path}/static_noise.npy")
      if self.static_noise.shape[0] != (self.progress_image_dim[0] * self.progress_image_dim[1]):
        print(Fore.YELLOW + "Progress image dim changed, restarting static noise!" + Fore.RESET)
        os.remove(f"{self.training_progress_save_path}/static_noise.npy")
        self.static_noise = np.random.normal(0.0, 1.0, size=(self.progress_image_dim[0] * self.progress_image_dim[1], self.latent_dim))
    else:
      self.static_noise = np.random.normal(0.0, 1.0, size=(self.progress_image_dim[0] * self.progress_image_dim[1], self.latent_dim))
    self.kernel_initializer = RandomNormal(stddev=0.02)

    # Load checkpoint
    self.initiated = False
    loaded_gen_weights_path = None
    loaded_disc_weights_path = None
    if load_from_checkpoint:
      loaded_gen_weights_path, loaded_disc_weights_path = self.load_checkpoint()

    # Create batchmaker and start it
    self.batch_maker = BatchMaker(self.train_data, self.batch_size, buffered_batches=buffered_batches, num_of_loading_workers=num_of_loading_workers)

    self.testing_batchmaker = None
    if self.testing_data:
      self.testing_batchmaker = BatchMaker(self.testing_data, self.batch_size, buffered_batches=buffered_batches, num_of_loading_workers=num_of_loading_workers)
      self.testing_batchmaker.start()

    #################################
    ###   Create discriminator    ###
    #################################
    self.discriminator = self.build_discriminator(disc_mod_name)
    self.discriminator.compile(loss="binary_crossentropy", optimizer=discriminator_optimizer)

    #################################
    ###     Create generator      ###
    #################################
    self.generator = self.build_generator(gen_mod_name)
    if self.generator.output_shape[1:] != self.image_shape: raise Exception("Invalid image input size for this generator model")

    #################################
    ### Create combined generator ###
    #################################
    noise_input = Input(shape=(self.latent_dim,), name="noise_input")
    gen_images = self.generator(noise_input)

    # Create frozen version of discriminator
    frozen_discriminator = Network(self.discriminator.inputs, self.discriminator.outputs, name="frozen_discriminator")
    frozen_discriminator.trainable = False

    # Discriminator takes images and determinates validity
    valid = frozen_discriminator(gen_images)

    # Combine models
    # Train generator to fool discriminator
    self.combined_generator_model = Model(noise_input, valid, name="dcgan_model")
    self.combined_generator_model.compile(loss="binary_crossentropy", optimizer=self.generator_optimizer)

    # Print all summaries
    print("\nDiscriminator Summary:")
    self.discriminator.summary()
    print("\nGenerator Summary:")
    self.generator.summary()
    print("\nGAN Summary")
    self.combined_generator_model.summary()

    # Load weights from checkpoint
    try:
      if loaded_gen_weights_path: self.generator.load_weights(loaded_gen_weights_path)
    except:
      print(Fore.YELLOW + "Failed to load generator weights from checkpoint" + Fore.RESET)

    try:
      if loaded_disc_weights_path: self.discriminator.load_weights(loaded_disc_weights_path)
    except:
      print(Fore.YELLOW + "Failed to load discriminator weights from checkpoint" + Fore.RESET)

    # Load weights from param and override checkpoint weights
    if generator_weights: self.generator.load_weights(generator_weights)
    if discriminator_weights: self.discriminator.load_weights(discriminator_weights)

  # Function for creating gradient generator
  def gradient_norm_generator(self):
    grads = K.gradients(self.combined_generator_model.total_loss, self.combined_generator_model.trainable_weights)
    summed_squares = [K.sum(K.square(g)) for g in grads]
    norm = K.sqrt(sum(summed_squares))
    inputs = self.combined_generator_model._feed_inputs + self.combined_generator_model._feed_targets + self.combined_generator_model._feed_sample_weights
    func = K.function(inputs, [norm])
    return func

  # Check if datasets have consistent shapes
  def validate_dataset(self):
    def check_image(image_path):
      im_shape = imagesize.get(image_path)
      if im_shape[0] != self.image_shape[0] or im_shape[1] != self.image_shape[1]:
        return False
      return True

    print(Fore.BLUE + "Checking dataset validity" + Fore.RESET)
    with ThreadPool(processes=8) as p:
      res = p.map(check_image, self.train_data)
      if not all(res): raise Exception("Inconsistent training dataset")

      if self.testing_data:
        res = p.map(check_image, self.testing_data)
        if not all(res): raise Exception("Inconsistent testing dataset")

    print(Fore.BLUE + "Dataset valid" + Fore.RESET)

  # Create generator based on template selected by name
  def build_generator(self, model_name:str):
    noise = Input(shape=(self.latent_dim,))

    try:
      m = getattr(generator_models_spreadsheet, model_name)(noise, self.image_shape, self.image_channels, self.kernel_initializer)
    except Exception as e:
      raise Exception(f"Generator model not found!\n{e}")

    return Model(noise, m, name="generator_model")

  # Create discriminator based on teplate selected by name
  def build_discriminator(self, model_name:str, classification:bool=True):
    img = Input(shape=self.image_shape)

    try:
      m = getattr(discriminator_models_spreadsheet, model_name)(img, self.kernel_initializer)
    except Exception as e:
      raise Exception(f"Discriminator model not found!\n{e}")

    if classification:
      m = Dense(1, activation="sigmoid")(m)

    return Model(img, m, name="discriminator_model")

  def train(self, target_episode:int,
            feed_prev_gen_batch:bool=False, feed_old_perc_amount:float=0.2,
            progress_images_save_interval:int=None, save_raw_progress_images:bool=True, weights_save_interval:int=None,
            discriminator_smooth_real_labels:bool=False, discriminator_smooth_fake_labels:bool=False,
            generator_smooth_labels:bool=False):

    # Function for adding random noise to labels (flipping them)
    def noising_labels(labels: np.ndarray, noise_ammount:float=0.01):
      array = np.zeros(labels.shape)
      for idx in range(labels.shape[0]):
        if random.random() < noise_ammount:
          array[idx] = 1 - labels[idx]
          if array[idx] < 0: array[idx] = -array[idx]
        else:
          array[idx] = labels[idx]
      return labels

    # Function for replacing new generated images with old generated images
    def replace_random_images(orig_images: np.ndarray, repl_images: deque, perc_ammount:float=0.20):
      repl_images = np.array(repl_images)
      for idx in range(orig_images.shape[0]):
        if random.random() < perc_ammount:
          orig_images[idx] = repl_images[random.randint(0, repl_images.shape[0] - 1)]
      return orig_images

    # Check arguments and input data
    assert target_episode > 0, Fore.RED + "Invalid number of epochs" + Fore.RESET
    if progress_images_save_interval:
      assert progress_images_save_interval <= target_episode, Fore.RED + "Invalid progress save interval" + Fore.RESET
    if weights_save_interval:
      assert weights_save_interval <= target_episode, Fore.RED + "Invalid weights save interval" + Fore.RESET

    # Calculate epochs to go
    end_episode = target_episode
    target_episode = target_episode - self.episode_counter
    assert target_episode > 0, Fore.CYAN + "Training is already finished" + Fore.RESET

    # Save noise for progress consistency
    if progress_images_save_interval is not None:
      if not os.path.exists(self.training_progress_save_path): os.makedirs(self.training_progress_save_path)
      np.save(f"{self.training_progress_save_path}/static_noise.npy", self.static_noise)

    # Training variables
    prev_gen_images = deque(maxlen=3*self.batch_size)
    get_gradients = self.gradient_norm_generator()

    epochs_time_history = deque(maxlen=self.AGREGATE_STAT_INTERVAL * 50)

    # Save starting kernels and biases
    if not self.initiated:
      self.__save_imgs(save_raw_progress_images)
      self.tensorboard.log_kernels_and_biases(self.generator)
      self.save_checkpoint()

    print(Fore.GREEN + f"Starting training on episode {self.episode_counter} for {target_episode} episodes" + Fore.RESET)
    for _ in range(target_episode):
      ep_start = time.time()

      ### Train Discriminator ###
      # Select batch of valid images
      imgs = self.batch_maker.get_batch()

      # Sample noise and generate new images
      gen_imgs = self.generator.predict(np.random.normal(0.0, 1.0, (self.batch_size, self.latent_dim)))

      # Train discriminator (real as ones and fake as zeros)
      if discriminator_smooth_real_labels:
        disc_real_labels = np.random.uniform(0.8, 1.0, size=(self.batch_size, 1))
      else:
        disc_real_labels = np.ones(shape=(self.batch_size, 1))

      if discriminator_smooth_fake_labels:
        disc_fake_labels = np.random.uniform(0, 0.2, size=(self.batch_size, 1))
      else:
        disc_fake_labels = np.zeros(shape=(self.batch_size, 1))

      if feed_prev_gen_batch:
        if len(prev_gen_images) > 0:
          tmp_imgs = replace_random_images(gen_imgs, prev_gen_images, feed_old_perc_amount)
          prev_gen_images += deque(gen_imgs)
          gen_imgs = tmp_imgs
        else:
          prev_gen_images += deque(gen_imgs)

      # Adding random noise to discriminator labels
      if self.discriminator_label_noise and self.discriminator_label_noise > 0:
        disc_real_labels = noising_labels(disc_real_labels, self.discriminator_label_noise / 2)
        disc_fake_labels = noising_labels(disc_fake_labels, self.discriminator_label_noise / 2)

      self.discriminator.trainable = True
      disc_real_loss = self.discriminator.train_on_batch(imgs, disc_real_labels)
      disc_fake_loss = self.discriminator.train_on_batch(gen_imgs, disc_fake_labels)

      ### Train Generator ###
      # Train generator (wants discriminator to recognize fake images as valid)
      if generator_smooth_labels:
        gen_labels = np.random.uniform(0.8, 1.0, size=(self.batch_size, 1))
      else:
        gen_labels = np.ones(shape=(self.batch_size, 1))
      self.discriminator.trainable = False
      gan_loss = self.combined_generator_model.train_on_batch(np.random.normal(0.0, 1.0, (self.batch_size, self.latent_dim)), gen_labels)

      self.episode_counter += 1
      self.tensorboard.step = self.episode_counter
      self.tensorboard.update_stats(disc_real_loss=disc_real_loss, disc_fake_loss=disc_fake_loss, gan_loss=gan_loss, disc_label_noise=self.discriminator_label_noise if self.discriminator_label_noise else 0)

      # Decay label noise
      if self.discriminator_label_noise and self.discriminator_label_noise_decay:
        self.discriminator_label_noise = max([self.discriminator_label_noise_min, (self.discriminator_label_noise * self.discriminator_label_noise_decay)])

        if (self.discriminator_label_noise_min == 0) and (self.discriminator_label_noise != 0) and (self.discriminator_label_noise < 0.001):
          self.discriminator_label_noise = 0

      # Seve stats and print them to console
      if self.episode_counter % self.AGREGATE_STAT_INTERVAL == 0:
        self.tensorboard.log_kernels_and_biases(self.generator)

        # Change color of log according to state of training
        print(Fore.GREEN + f"{self.episode_counter}/{end_episode}, Remaining: {time_to_format(mean(epochs_time_history) * (end_episode - self.episode_counter))}\t\t[D-R loss: {round(float(disc_real_loss), 5)}, D-F loss: {round(float(disc_fake_loss), 5)}] [G loss: {round(float(gan_loss), 5)}] - Epsilon: {round(self.discriminator_label_noise, 4) if self.discriminator_label_noise else 0}" + Fore.RESET)

      # Save progress
      if self.training_progress_save_path is not None and progress_images_save_interval is not None and self.episode_counter % progress_images_save_interval == 0:
        self.__save_imgs(save_raw_progress_images)

      # Save weights of models
      if weights_save_interval is not None and self.episode_counter % weights_save_interval == 0:
        self.__save_weights()

      # Save checkpoint
      if self.episode_counter % self.CHECKPOINT_SAVE_INTERVAL == 0:
        self.save_checkpoint()
        print(Fore.BLUE + "Checkpoint created" + Fore.RESET)

      if self.episode_counter % self.GRADIENT_CHECK_INTERVAL == 0:
        # Generate evaluation noise and labels
        eval_noise = np.random.normal(0.0, 1.0, (self.batch_size, self.latent_dim))
        eval_labels = np.ones(shape=(self.batch_size, 1))

        # Create gradient function and evaluate based on eval noise and labels
        norm_gradient = get_gradients([eval_noise, eval_labels, np.ones(len(eval_labels))])[0]

        # Check norm gradient
        if norm_gradient > 100 and self.episode_counter > self.CONTROL_THRESHOLD:
          print(Fore.RED + f"Current generator norm gradient: {norm_gradient}")
          print("Gradient too high!" + Fore.RESET)
          if input("Do you want exit training?\n") == "y": return
        elif norm_gradient < 0.2 and self.episode_counter > self.CONTROL_THRESHOLD:
          print(Fore.RED + f"Current generator norm gradient: {norm_gradient}")
          print("Gradient vanished!" + Fore.RESET)
          if input("Do you want exit training?\n") == "y": return
        else:
          print(Fore.BLUE + f"Current generator norm gradient: {norm_gradient}" + Fore.RESET)

        # Change seed
        np.random.seed(None)
        random.seed()

      epochs_time_history.append(time.time() - ep_start)

    # Shutdown helper threads
    print(Fore.GREEN + "Training Complete - Waiting for other threads to finish" + Fore.RESET)
    if self.testing_batchmaker: self.testing_batchmaker.__terminate = True
    self.batch_maker.terminate()
    self.save_checkpoint()
    self.__save_weights()
    self.batch_maker.join()
    if self.testing_batchmaker: self.testing_batchmaker.join()
    print(Fore.GREEN + "All threads finished" + Fore.RESET)

  # Function for saving progress images
  def __save_imgs(self, save_raw_progress_images:bool=True):
    if not os.path.exists(self.training_progress_save_path + "/progress_images"): os.makedirs(self.training_progress_save_path + "/progress_images")
    gen_imgs = self.generator.predict(self.static_noise)

    # Rescale images 0 to 255
    gen_imgs = (0.5 * gen_imgs + 0.5) * 255

    final_image = np.zeros(shape=(self.image_shape[0] * self.progress_image_dim[1], self.image_shape[1] * self.progress_image_dim[0], self.image_channels)).astype(np.float32)

    cnt = 0
    for i in range(self.progress_image_dim[1]):
      for j in range(self.progress_image_dim[0]):
        if self.image_channels == 3:
          final_image[self.image_shape[0] * i:self.image_shape[0] * (i + 1), self.image_shape[1] * j:self.image_shape[1] * (j + 1), :] = gen_imgs[cnt]
        else:
          final_image[self.image_shape[0] * i:self.image_shape[0] * (i + 1), self.image_shape[1] * j:self.image_shape[1] * (j + 1), 0] = gen_imgs[cnt, :, :, 0]
        cnt += 1
    final_image = cv.cvtColor(final_image, cv.COLOR_RGB2BGR)

    if save_raw_progress_images:
      cv.imwrite(f"{self.training_progress_save_path}/progress_images/{self.episode_counter}.png", final_image)
    self.tensorboard.write_image(np.reshape(cv.cvtColor(final_image, cv.COLOR_BGR2RGB) / 255, (-1, final_image.shape[0], final_image.shape[1], final_image.shape[2])).astype(np.float32))

  def save_models_structure_images(self):
    save_path = self.training_progress_save_path + "/model_structures"
    if not os.path.exists(save_path): os.makedirs(save_path)
    plot_model(self.combined_generator_model, os.path.join(save_path, "combined.png"), expand_nested=True, show_shapes=True)
    plot_model(self.generator, os.path.join(save_path, "generator.png"), expand_nested=True, show_shapes=True)
    plot_model(self.discriminator, os.path.join(save_path, "discriminator.png"), expand_nested=True, show_shapes=True)

  def load_checkpoint(self):
    checkpoint_base_path = os.path.join(self.training_progress_save_path, "checkpoint")
    if not os.path.exists(os.path.join(checkpoint_base_path, "checkpoint_data.json")): return None, None

    with open(os.path.join(checkpoint_base_path, "checkpoint_data.json"), "rb") as f:
      data = json.load(f)

      if data:
        self.episode_counter = int(data["episode"])
        if data["disc_label_noise"]:
          self.discriminator_label_noise = float(data["disc_label_noise"])
        self.initiated = True
        return data["gen_path"], data["disc_path"]
      return None, None

  def save_checkpoint(self):
    checkpoint_base_path = os.path.join(self.training_progress_save_path, "checkpoint")
    if not os.path.exists(checkpoint_base_path): os.makedirs(checkpoint_base_path)

    gen_path = f"{checkpoint_base_path}/generator_{self.gen_mod_name}.h5"
    disc_path = f"{checkpoint_base_path}/discriminator_{self.disc_mod_name}.h5"

    if os.path.exists(gen_path): os.rename(gen_path, f"{checkpoint_base_path}/generator_{self.gen_mod_name}.h5.lock")
    if os.path.exists(disc_path): os.rename(disc_path, f"{checkpoint_base_path}/discriminator_{self.disc_mod_name}.h5.lock")

    self.generator.save_weights(gen_path)
    self.discriminator.save_weights(disc_path)

    if os.path.exists(f"{checkpoint_base_path}/generator_{self.gen_mod_name}.h5.lock"): os.remove(f"{checkpoint_base_path}/generator_{self.gen_mod_name}.h5.lock")
    if os.path.exists(f"{checkpoint_base_path}/discriminator_{self.disc_mod_name}.h5.lock"): os.remove(f"{checkpoint_base_path}/discriminator_{self.disc_mod_name}.h5.lock")

    data = {
      "episode": self.episode_counter,
      "gen_path": gen_path,
      "disc_path": disc_path,
      "disc_label_noise": self.discriminator_label_noise
    }

    with open(os.path.join(checkpoint_base_path, "checkpoint_data.json"), "w", encoding='utf-8') as f:
      json.dump(data, f)

  def __save_weights(self):
    save_dir = self.training_progress_save_path + "/weights/" + str(self.episode_counter)
    if not os.path.exists(save_dir): os.makedirs(save_dir)
    self.generator.save_weights(f"{save_dir}/generator_{self.gen_mod_name}.h5")
    self.discriminator.save_weights(f"{save_dir}/discriminator_{self.disc_mod_name}.h5")

  def make_progress_gif(self, frame_duration:int=16):
    if not os.path.exists(self.training_progress_save_path): os.makedirs(self.training_progress_save_path)
    if not os.path.exists(self.training_progress_save_path + "/progress_images"): return

    frames = []
    img_file_names = os.listdir(self.training_progress_save_path + "/progress_images")

    for im_file in img_file_names:
      if os.path.isfile(self.training_progress_save_path + "/progress_images/" + im_file):
        frames.append(Image.open(self.training_progress_save_path + "/progress_images/" + im_file))

    if len(frames) > 2:
      frames[0].save(f"{self.training_progress_save_path}/progress_gif.gif", format="GIF", append_images=frames[1:], save_all=True, optimize=False, duration=frame_duration, loop=0)


from PHCommon import *

PH_PLAYLISTS_URL =			BASE_URL + '/playlists'
PH_PLAYLIST_URL =			BASE_URL + '/playlist'

MAX_PLAYLISTS_PER_PAGE =	36

@route(ROUTE_PREFIX + '/playlists')
def BrowsePlaylists(title=L("DefaultBrowsePlaylistsTitle")):

	# Create a dictionary of menu items
	browsePlaylistsMenuItems = OrderedDict([
		('Most Recent',				{'function':ListPlaylists, 'functionArgs':{'url':addURLParameters(PH_PLAYLISTS_URL, {'o':'mr'})}}),
		('Top Rated - All Time',		{'function':ListPlaylists, 'functionArgs':{'url':addURLParameters(PH_PLAYLISTS_URL, {'o':'tr', 't':'a'})}}),
		('Top Rated - Monthly',		{'function':ListPlaylists, 'functionArgs':{'url':addURLParameters(PH_PLAYLISTS_URL, {'o':'tr', 't':'m'})}}),
		('Top Rated - Weekly',		{'function':ListPlaylists, 'functionArgs':{'url':addURLParameters(PH_PLAYLISTS_URL, {'o':'tr', 't':'w'})}}),
		('Top Rated - Daily',		{'function':ListPlaylists, 'functionArgs':{'url':addURLParameters(PH_PLAYLISTS_URL, {'o':'tr', 't':'t'})}}),
		('Most Viewed - All Time',	{'function':ListPlaylists, 'functionArgs':{'url':addURLParameters(PH_PLAYLISTS_URL, {'o':'mv', 't':'a'})}}),
		('Most Viewed - Monthly',		{'function':ListPlaylists, 'functionArgs':{'url':addURLParameters(PH_PLAYLISTS_URL, {'o':'mv', 't':'m'})}}),
		('Most Viewed - Weekly',		{'function':ListPlaylists, 'functionArgs':{'url':addURLParameters(PH_PLAYLISTS_URL, {'o':'mv', 't':'w'})}}),
		('Most Viewed - Daily',		{'function':ListPlaylists, 'functionArgs':{'url':addURLParameters(PH_PLAYLISTS_URL, {'o':'mv', 't':'d'})}}),
		('Most Favorited',			{'function':ListPlaylists, 'functionArgs':{'url':addURLParameters(PH_PLAYLISTS_URL, {'o':'mf'})}})
	])

	return GenerateMenu(title, browsePlaylistsMenuItems)

@route(ROUTE_PREFIX + '/playlists/list')
def ListPlaylists(title, url = PH_PLAYLISTS_URL, page=1):

	# Create a dictionary of menu items
	listPlaylistsMenuItems = OrderedDict()

	# Add the page number into the query string
	if (int(page) != 1):
		url = addURLParameters(url, {'page':str(page)})

	# Get the HTML of the page
	html = HTML.ElementFromURL(url)

	# Use xPath to extract a list of playlists
	playlists = html.xpath("//ul[contains(@class, 'user-playlist')]/li[contains(@id, 'playlist')]")

	# Loop through all playlists
	for playlist in playlists:

		# Make sure Playlist isn't empty
		if (len(playlist.xpath(".//span[contains(@class,'playlist-videos')]/span[contains(@class,'number')]/span[text()='0']")) < 1):

			# Use xPath to extract playlist details
			playlistTitle =		playlist.xpath("./div/div[contains(@class, 'thumbnail-info-wrapper')]/span[contains(@class, 'title')]/a[contains(@class, 'title')]/text()")[0]
			playlistURL =		BASE_URL + playlist.xpath("./div/div[contains(@class, 'thumbnail-info-wrapper')]/span[contains(@class, 'title')]/a[contains(@class, 'title')]/@href")[0]
			playlistThumbnail =	playlist.xpath("./div/div[contains(@class, 'linkWrapper')]/img[contains(@class, 'largeThumb')]/@data-mediumthumb")[0]

			# Add a menu item for the playlist
			listPlaylistsMenuItems[playlistTitle] = {'function':BrowseVideos, 'functionArgs':{'url':playlistURL}, 'directoryObjectArgs':{'thumb':playlistThumbnail}}

	# There is a slight change that this will break... If the number of playlists returned in total is divisible by MAX_PLAYLISTS_PER_PAGE with no remainder, there could possibly be no additional page after. This is unlikely though and I'm too lazy to handle it.
	if (len(playlists) == MAX_PLAYLISTS_PER_PAGE):
		listPlaylistsMenuItems['Next Page'] = {'function':ListPlaylists, 'functionArgs':{'title':title, 'url':url, 'page':int(page)+1}, 'nextPage':True}

	return GenerateMenu(title, listPlaylistsMenuItems)


#!/usr/bin/env python

import curses
import curses.textpad
import time

stdscr = curses.initscr()

curses.noecho()
stdscr.nodelay(1)

curses.textpad.rectangle(stdscr,0,0,10,10)
curses.textpad.rectangle(stdscr,0,11,10,21)
curses.textpad.rectangle(stdscr,0,22,10,33)
stdscr.refresh()
curses.curs_set(1)
win = curses.newwin(9,9,1,1)
updatewin = curses.newwin(9,9,1,12)
numberbox = curses.newwin(9,9,1,23)

rate = .1
number = 0
x = -1
string = ''

def number_print(number,win):
	win.erase()
	win.addstr(str(number))
	numberbox.move(1,1)
	win.noutrefresh()
back = False
while x != 27:
	if x == 127:
		string = string[:-1]
		win.erase()
	if x != -1 and x != 127:
		string+=chr(x)

	if x == 10:
		if string == "hello\n":
			updatewin.erase()
			updatewin.addstr(0,0,"and hello to you!")
			updatewin.noutrefresh()
			win.erase()
			string=''
		if string == "slow\n":
			rate = .001
			win.erase()
			string=''
		if string == "back\n":
			back = True
			win.erase()
			string=''

	number_print(number,numberbox)
	win.addstr(0,0,string)
	win.noutrefresh()
	x = stdscr.getch()
	if back == False:
		number+=rate
	else:
		number-=rate
	curses.doupdate()

curses.endwin()


#!/usr/bin/env python
#

import pygame
from pygame.locals import *
from sys import exit
import random

pygame.init()

screen=pygame.display.set_mode((1024,480),0,32)
pygame.display.set_caption("Cards by Rich Schumacher")

#Create a  background.
background = pygame.Surface((1024,480))
background.fill((0,255,0))

#Load cards image
card_image = pygame.image.load('cards.gif')
CARD_WIDTH=71
CARD_HEIGHT=96

#Display A Card Function
#cardnum : 0:12 = Ace to King, Hearts, 13:25 = Hearts, 25:38 = Clubs, 39:51 = Spades
#loc_x, loc_y : x,y coordinate on screen to place image
def display_a_card(cardnum, loc_x, loc_y):
    cardnum = cardnum % 52
    suit = int(cardnum/13)
    cardnum = cardnum % 13
    card_to_show = pygame.Rect((cardnum * CARD_WIDTH, suit * CARD_HEIGHT),
                               (CARD_WIDTH, CARD_HEIGHT))
    screen.blit(card_image,(loc_x,loc_y),card_to_show)

#Initialize locals
number = 0
suit = 0

#clock and font objects
clock = pygame.time.Clock()
font = pygame.font.SysFont("calibri",40)

#Create a Deck 0..51
myDeck = list(range(52))
spacing = CARD_WIDTH

#Shuffle Deck
def shuffle():
    effect = pygame.mixer.Sound('shuffling-cards-1.wav')
    effect.play()

def display_deck(deck):
    xpos = 0
    ypos = 0

    for j in range(4):
        for i in range(13):
            display_a_card(deck[i+j+j*12], xpos, ypos)
            xpos += spacing
        xpos = 0
        ypos += CARD_HEIGHT

while True:
    for event in pygame.event.get():
        if event.type == QUIT:
            exit()
        if event.type == KEYDOWN:
            flag = True
        if event.type == KEYUP:
            if (event.key == K_s) and (flag == True):
                random.shuffle(myDeck)
                shuffle()
                flag = False
            if (event.key == K_d) and (flag == True):
                spacing /= 2
                flag = False
            if (event.key == K_i) and (flag == True):
                spacing *= 2
                flag = False

    screen.blit(background,(0,0))
    display_deck(myDeck)
    text = font.render('Hit S to Shuffle', True,(0,0,0))
    screen.blit(text,(250,410))
    text2 = font.render('Hit i or d to change spacing', True,(0,0,0))
    screen.blit(text2,(250,440))

    pygame.display.update()


from geospark.core.geom.envelope import Envelope
from tests.test_base import TestBase

class TestGeomPrimitives(TestBase):

    def test_jvm_envelope(self):
        envelope = Envelope(0.0, 5.0, 0.0, 5.0)
        jvm_instance = envelope.create_jvm_instance(self.spark.sparkContext._jvm)
        envelope_area = jvm_instance.getArea()
        assert envelope_area == 25.0, f"Expected area to be equal 25 but {envelope_area} was found"


#!/usr/bin/env python

# Program Description:
#
# Word Index is a program that takes a plain text file as input and
# outputs all the words contained in it
# sorted alphabetically along with the page numbers on which they occur.
# The program assumes that a page is a
# sequence of 45 lines, each line has max 80 characters, and there is no
# hyphenation. Additionally, Word Index
# must ignore all words that occur more than 100 times.

####################################
# Free Flow, a.k.a. No Style
####################################

import sys, string

# Global "constants"
LINES_PER_PAGE = 45
MAX_SIZE_LINE = 80
STOP_FREQUENCY_LIMIT = 100

def lineIndexToPage(lineIndex):
    return lineIndex / LINES_PER_PAGE + 1

# Defining a main method makes testing easier
def main(file_path):
    file = open(file_path)

    wordsToOccurrences = {}
    lineIndex = 0
    for line in file:
        line = line.replace('\n', '')
        page = lineIndexToPage(lineIndex)
        words = line.split(' ')

        for word in words:
            if word:
                if word in wordsToOccurrences:
                    occurrences = wordsToOccurrences[word]
                else:
                    occurrences = []

                if page not in occurrences:
                    occurrences.append(page)

                wordsToOccurrences[word] = occurrences

    words = sorted(wordsToOccurrences.keys())

    for word in words:
        occurrences = wordsToOccurrences[word]

        if len(occurrences) <= STOP_FREQUENCY_LIMIT:
            print(word, wordsToOccurrences[word])

if __name__ == "__main__":
    main(sys.argv[1])


# Author:Cecilia
import socket
import struct
import json
from concurrent.futures import ThreadPoolExecutor
pool = ThreadPoolExecutor(100)

from db import user_data
from interface import common_interface
from interface import admin_interface
from interface import user_interface
from lib import common

# 做任务分发的功能函数字典
func_dic = {
    'register':common_interface.register_interface,
    'login':common_interface.login_interface,
    'check_movie':common_interface.check_movie_interface,
    'upload_movie':admin_interface.upload_movie_interface,
    'get_movie_list':common_interface.get_movie_list_interface,
    'delete_movie':admin_interface.delete_movie_interface,
    'send_notice':admin_interface.send_notice_interface,
    'buy_vip':user_interface.buy_vip_interface,
    'download_free_movie':user_interface.download_free_movie_interface,
    'download_nofree_movie':user_interface.download_nofree_movie_interface,
    'check_movie_record':user_interface.check_movie_record_interface,
    'check_notice':user_interface.check_notice_interface,

}

# 服务端入口
def run():
    server = socket.socket()
    server.bind(('127.0.0.1',8007))
    server.listen(100)

    while True:
        conn,addr = server.accept()
        print(f'{addr}已经连接服务器')

        # 由线程池对象提交异步任务
        pool.submit(recv_work,conn,addr)

# 执行每个连接对象的请求操作
def recv_work(conn,addr):
    while True:
        try:
            # 接收数据头
            headers = conn.recv(4)
            data_len = struct.unpack('i',headers)[0]# 获取数据的总长度
            json_data = conn.recv(data_len) # 接收数据部分
            back_dic = json.loads(json_data.decode('utf8')) # 将数据反序列化
            back_dic['addr'] = addr

            # func是做任务分发工作的，将每个客户端的任务接收到，转去另一个地方执行
            func(back_dic,conn)
        except Exception as e:
            print(e)
            print(f'{addr}已经断开服务器连接了。。。。。。。')
            user_data.metux.acquire()
            user_data.online_user.pop(addr)
            user_data.metux.release()
            conn.close()
            break

# 任务分发函数
def func(back_dic,conn):
    if back_dic.get('type') not in func_dic:
        send_dic = {'flag':False,'msg':'请求错误！'}
        common.send_msg(send_dic,conn)

    else:
        print('进入',back_dic.get('type'))
        func_dic[back_dic.get('type')](back_dic,conn)
        print('结束',back_dic.get('type'))


"""Main entry point of program. Here, a configs file is parsed and the trainer is instantiated and run."""

import argparse

from senn.trainer import init_trainer

def main():
    """
    Entry point to the trainer.
    Binds together the config and the Trainer class
    """
    parser = argparse.ArgumentParser()
    parser.add_argument('--config', default="configs/compas_lambda1e-4_seed111111.json", help='experiment config file')
    args = parser.parse_args()

    trainer = init_trainer(args.config)
    trainer.run()
    trainer.finalize()

if __name__ == "__main__":
    main()


#!/usr/bin/python
# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
### BEGIN LICENSE
# Copyright (C) 2012 Caffeinated Code <caffeinatedco.de>
# Copyright (C) 2012 Jono Cooper
# Thanks to <adamwhitcroft.com> for Climacons!
#
# DON'T BE A DICK PUBLIC LICENSE
#
#                     Version 1, December 2009
#
#  Copyright (C) 2009 Philip Sturgeon <email@philsturgeon.co.uk>
#
#  Everyone is permitted to copy and distribute verbatim or modified
#  copies of this license document, and changing it is allowed as long
#  as the name is changed.
#
#                   DON'T BE A DICK PUBLIC LICENSE
#     TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
#
#   1. Do whatever you like with the original work, just don't be a dick.
#
#      Being a dick includes - but is not limited to - the following instances:
#
#  1a. Outright copyright infringement - Don't just copy this and change the name.
#  1b. Selling the unmodified original with no work done what-so-ever, that's REALLY being a dick.
#  1c. Modifying the original work to contain hidden harmful content. That would make you a PROPER dick.
#
#   2. If you become rich through modifications, related works/services, or supporting the original work,
#  share the love. Only a dick would make loads off this work and not buy the original works
#  creator(s) a pint.
#
#   3. Code is provided with no warranty. Using somebody else's code and bitching when it goes wrong makes
#  you a DONKEY dick. Fix the problem yourself. A non-dick would submit the fix back.#  you a DONKEY dick. Fix the problem yourself. A non-dick would submit the fix back.#  you a DONKEY dick. Fix the problem yourself. A non-dick would submit the fix back.#  you a DONKEY dick. Fix the problem yourself. A non-dick would submit the fix back.#  you a DONKEY dick. Fix the problem yourself. A non-dick would submit the fix back.### END LICENSE

import sys
import os.path
import unittest
sys.path.insert(0, os.path.realpath(os.path.join(os.path.dirname(__file__), "..")))

from stormcloud import AboutStormcloudDialog

class TestExample(unittest.TestCase):
    def setUp(self):
        self.AboutStormcloudDialog_members = [
        'AboutDialog', 'AboutStormcloudDialog', 'gettext', 'logger', 'logging']

    def test_AboutStormcloudDialog_members(self):
        all_members = dir(AboutStormcloudDialog)
        public_members = [x for x in all_members if not x.startswith('_')]
        public_members.sort()
        self.assertEqual(self.AboutStormcloudDialog_members, public_members)

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


"""
Flask App for LHS
"""

from flask import Flask, request, jsonify
from flask_pymongo import PyMongo
from utils import AppUtils

# Create an instance of Flask for our app
app = Flask(__name__)

# Connect to our mongo database
app.config['MONGO_URI'] = "mongodb://localhost:27017/test"
mongo = PyMongo(app)

@app.route('/', methods=['GET'])
def query_records():
    """
    Query records in database
    :return: JSON of the records returned
    """
    # Get details from request
    name = request.args.get('name')
    email = request.args.get('email')

    # Form search query
    query = AppUtils.make_search_query(email, name)

    # Search database
    users = mongo.db.users.find(query)

    # Get output into form we want
    output = [AppUtils.object_id_to_string(user) for user in users]

    # Return JSON of users
    return jsonify(output)

# This is the bit that runs:
if __name__ == "__main__":
    # Start the flask app
    app.run()


# -*- coding=utf-8 -*-
# Created Time: 2015年06月08日 星期一 17时10分23秒
# File Name: Order.py

class Order(object):
    ''' 订单 '''

    def __init__(self, orderId, orderDesc, price, user):
        # 订单 Id
        self.orderId = orderId
        # 订单描述
        self.orderDesc = orderDesc
        # 价钱
        self.price = price
        # 谁的订单
        self.user = user


"""
Requests in these tests should not be handled by the middleware.
"""

from django.conf import settings as django_settings

from tests.utils import patch_response_validation_middleware_settings

from django_swagger_tester.configuration import SwaggerTesterSettings

def test_exempt_url(client, caplog, monkeypatch):
    monkeypatch.setattr(
        django_settings,
        'SWAGGER_TESTER',
        patch_response_validation_middleware_settings(
            'VALIDATION_EXEMPT_URLS', [{'url': '^api/v1/cars/correct$', 'status_codes': ['*']}]
        ),
    )
    settings = SwaggerTesterSettings()
    monkeypatch.setattr('django_swagger_tester.middleware.settings', settings)
    client.get('/api/v1/cars/correct')
    assert (
        'Validation skipped: GET request to `/api/v1/cars/correct` with status code 200 is in VALIDATION_EXEMPT_URLS'
        in caplog.messages
    )

def test_non_endpoint_options_request(client, caplog):
    """
    Makes sure these types of requests are *not* handled by the middleware.
    """
    for path in ['', 'test']:
        client.options(path)
        assert 'Validation skipped: `/%s` is not a relevant endpoint' % path in caplog.messages


from flask import Flask, render_template, request, redirect
import sqlite3
from flask.helpers import url_for
import folium
from flask_paginate import Pagination, get_page_parameter

app = Flask(__name__)

@app.route('/')
def base():
    conn = sqlite3.connect('quotes.db')
    conn.row_factory = sqlite3.Row
    cur = conn.cursor()
    cur.execute("select * from webdata")
    datas = cur.fetchall();
    conn.close()
    return render_template('index.html', datas = datas)

@app.route('/folium')
def maps():
    start_coords = (42, 43)
    folium_map = folium.Map(location=start_coords, zoom_start=8)
    folium_map.save('templates/folmap.html')
    return render_template('maps.html')

@app.route('/', methods=['GET', 'POST'])
def search():
    a = request.form['search-input']
    conn = sqlite3.connect('quotes.db')
    conn.row_factory = sqlite3.Row
    cur = conn.cursor()
    cur.execute("select * from webdata where content=? or name=?", (a,a))
    datas = cur.fetchall();
    conn.close()
    return render_template("search.html", datas = datas)

"""@app.route('/', methods=['GET', 'POST'])
def query_search():
    a = request.form['search-input']
    return redirect(url_for("search"), a=a)"""

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


# -*- coding: utf-8 -*-
"""
Created on Wed Aug 26 00:14:06 2020

@author: Min
"""

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.metrics import roc_curve,auc
from sklearn.metrics import accuracy_score, f1_score, average_precision_score
from sklearn.metrics import confusion_matrix
from sklearn.metrics import precision_recall_curve
from sklearn.model_selection import GridSearchCV, train_test_split
from sklearn.ensemble import RandomForestClassifier
from sklearn.linear_model import LinearRegression, LogisticRegression
from sklearn import preprocessing
from sklearn.cluster import KMeans

loc=r"C:\Users\Min\Downloads\takehome_ds_written.csv"
df=pd.read_csv(loc)
df.head()
df.columns
df.amount_usd_in_cents =round(df.amount_usd_in_cents/100)

df.dtypes
df.describe()

df.isnull().sum()

#perMerchant=df.groupby("merchant").size()

def perc1(sr):
    return np.percentiles(sr, np.linspace(0,100,11))

def perc2(sr):
    return np.percentile(sr, np.linspace(0,100,21))

#plt.scatter(range(perMerchant.shape[0]), perMerchant, sort_values())
#plt.ylim( 1,5000)

np.percentile(df.amount_usd_in_cents, np.linspace(95,100,20))

plt.hist(np.log(df.amount_usd_in_cents))

df.time=pd.to_datetime(df.time)
df['hour']=df.time.dt.hour
df['weekday' ]=df.time.dt.weekday

#df['wknd']=df['weekday' ]<5
df['wknd']=df['weekday' ]>=5

df=df.sort_values(by=['merchant', 'time'])
df['time_1']=df.time.shift(-1)
df['day']=df.time.dt.day

#characterize transaction type using amount usd in cents", tint, heuer', day weekday, song, end of month, early month

tranlist=df.copy(deep=True)
def generatefeatures(tranlist, time_st, time_end):
    from scipy.stats import linregress
    eligible = (tranlist.time >time_st) & (tranlist.time<time_end)
    df=tranlist[eligible]

    df['merchant_1']=df.merchant.shift(-1)
    df['merchant_1_']=df.merchant.shift(1)

    df['tint']=(df.time_1-df.time).dt.days
    df['tint'][df.merchant != df.merchant_1] = None
    df['stt']= df.merchant != df.merchant_1_

    df["endt" ]=df.merchant != df.merchant_1
    df['timeindays']=(time_end - df.time).apply(lambda x: x.days).values

    df['tinactive']=np.nan
    df['tinactive'][df.merchant != df.merchant_1]= df['timeindays'][df.merchant != df.merchant_1]
    df.tint[df.merchant != df.merchant_1]=None
    df['time2']=((df.time-time_st).dt.seconds+(df.time-time_st).dt.days*24*60*60)/3600
    dayAgg=df.groupby(['merchant','timeindays'])['amount_usd_in_cents'].sum().reset_index()

    def percentile(n):
        def percentile_(x):
            return np.percentile(x, n)
        percentile_.__name__ = 'percentile_%s' % n
        return percentile_

    df_agg=df.groupby('merchant').agg({ 'amount_usd_in_cents':['mean','std',percentile(95),percentile(50),percentile(5)],
                                   'tint':['mean','std'],
                                   'day':['mean','std'],
                                   'wknd':['sum'],
                                   'merchant':['count'],
                                   'hour':['mean','std']})
    df_agg.columns=['_'.join(col).strip() for col in df_agg.columns.values]
    df_agg['trend']=df.groupby('merchant').apply(lambda v: linregress(v.time2, v.amount_usd_in_cents)[0])
    df_agg['trendtind']=df.dropna(subset=['tint']).groupby('merchant').apply(lambda v: linregress(v.time2, v.tint)[0])
    df_agg['trendDay']=dayAgg.groupby('merchant').apply(lambda v: linregress(v.timeindays, v.amount_usd_in_cents)[0])
    df_agg['endtime']=df.time[df.endt].values
    df_agg['length']= pd.Series(df.time[df.endt].values - df.time[df.stt].values).apply(lambda x: x.days).values
    df_agg['tinactive']=pd.Series(time_end-df.time[df.endt]).apply(lambda x: x.days).values

    bins=pd.IntervalIndex.from_tuples([(-1,15),(15,31)])
    df['dayCut']=pd.cut(df.day,bins)
    df['dayCut']=df['dayCut'].astype(str)

    bins=pd.IntervalIndex.from_tuples([(-1,8),(8,18),(18,23)])
    df['hourCut']=pd.cut(df.hour,bins)
    df['hourCut']=df['hourCut'].astype(str)

    bins=pd.IntervalIndex.from_tuples([(-1,2),(2,7),( 7,60),(60,1000)])
    df['tintCut']=pd.cut(df.tint,bins)
    df['tintCut']=df['tintCut'].astype(str)

    bins=pd.IntervalIndex.from_tuples([(-1,50),(50,100),(100,1000),(1000,1000000)])
    df['amtCut']=pd.cut(df.amount_usd_in_cents,bins)
    df['amtCut']=df['amtCut'].astype(str)

    df['I']=1
    t1=pd.pivot_table(df, values='I', index='merchant', columns='hourCut',aggfunc=np.sum).fillna(0)
    t1.columns=[x+' transaction hour' for x in t1.columns]
    t1=t1.iloc[:,1:]
    t1_p=t1.divide( df_agg.merchant_count, axis=0)

    df['I']=1
    t2=pd.pivot_table(df, values='I', index='merchant', columns='amtCut',aggfunc=np.sum).fillna(0)
    t2.columns=[x+' $ amount' for x in t2.columns]
    t2=t2.iloc[:,1:]
    t2_p=t2.divide( df_agg.merchant_count, axis=0)

    df['I']=1
    t3=pd.pivot_table(df, values='I', index='merchant', columns='tintCut',aggfunc=np.sum).fillna(0)
    t3.columns=[x+' day bet trans.' for x in t3.columns]
    t3=t3.iloc[:,1:]
    del t3['nan day bet trans.']
    t3_p=t3.divide( df_agg.merchant_count, axis=0)

    df['I']=1
    t4=pd.pivot_table(df, values='I', index='merchant', columns='dayCut',aggfunc=np.sum).fillna(0)
    t4.columns=[x+' day' for x in t4.columns]
    t4=t4.iloc[:,1:]
    t4_p=t4.divide(df_agg.merchant_count, axis=0)

    wk_p=df_agg[['wknd_sum']].divide(df_agg.merchant_count, axis=0)
    df_stat=pd.concat([pd.concat([t1,t2,t3,t4], axis=1), df_agg],axis=1)
    df_stat.columns=[x+'_O' for x in df_stat.columns]

    return(pd.concat([df_stat,t1_p,t2_p,t3_p,t4_p, wk_p], axis=1) )

time_st=pd.to_datetime('2032-12-31 20:07:57')
time_end=pd.to_datetime('2034-12-31 20:07:57')

df_filtered=generatefeatures(df, time_st, time_end)

df_filtered['logged_amt']=np.log(df_filtered.amount_usd_in_cents_mean_O)
df_filtered['logged_int']=np.log(df_filtered.tint_mean_O+1)

featuresCluster=['(18, 23] transaction hour',
       '(8, 18] transaction hour', '(100, 1000] $ amount',
       '(1000, 1000000] $ amount', '(50, 100] $ amount',
       '(2, 7] day bet trans.', '(60, 1000] day bet trans.',
       '(7, 60] day bet trans.', '(15, 31] day',
       'wknd_sum', 'logged_amt', 'logged_int']

featuresClusterO=['(18, 23] transaction hour',
       '(8, 18] transaction hour', '(100, 1000] $ amount',
       '(1000, 1000000] $ amount', '(50, 100] $ amount',
       '(2, 7] day bet trans.', '(60, 1000] day bet trans.',
       '(7, 60] day bet trans.', '(15, 31] day',
       'wknd_sum', 'amount_usd_in_cents_mean_O', 'tint_mean_O']

from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
ss=df_filtered.merchant_count_O>2
(scaler.fit(df_filtered[featuresCluster][ss]))
X=scaler.transform(df_filtered[featuresCluster][ss])
from sklearn.cluster import KMeans

wcss=[]
for i in range(1, 11):
    km = KMeans(n_clusters = i, init = 'k-means++',
                                        random_state = 42)
    km.fit(X)
    wcss.append(km.inertia_)
plt.plot(range(1,11), wcss,'-bo')
plt.title('elbow method')
plt.xlabel('# clusters')
plt.ylabel('wcss')
plt.show()

i=7
km = KMeans(n_clusters = i, init = 'k-means++',
                                        random_state = 42)
km.fit(X)
#import pickle
#pickle.dump( km, open( "km.pkl", "wb" ) )
#km=pickle.load(open( "km.pkl", "rb" ))

df_filtered['label']=np.nan
df_filtered['label'][ss]=km.labels_
df_filtered[featuresClusterO+['label']].groupby('label').mean().to_csv(r'C:\Users\Min\clusters.csv')
df_filteredO=df_filtered.copy(deep=True)

fixedTh=90
mincap=30
maxcap=180
factorStd=4
mischurn=[]
for i in range(3,10):
    midpt=pd.to_datetime('2033-12-31 20:07:57')+pd.Timedelta(i,unit='M')
    eligiblet = (df.time>pd.to_datetime('2032-12-31 20:07:57')) & (df.time < midpt)

    tdf=df[eligiblet]

    tdf['merchant_1_']=tdf.merchant.shift(1)
    tdf['merchant_1']=tdf.merchant.shift(-1)
    tdf['time_1']=tdf.time.shift(-1)
    tdf['tint']= (tdf.time_1-tdf.time).dt.days
    tdf['endt']=tdf.merchant_1 != tdf.merchant
    tdf['tint'][tdf.endt]= None
    tdf['tinactive']=np.nan
    tdf['tinactive'][tdf.endt]=(midpt-tdf.time)[tdf.endt].apply(lambda x: x.days)
    tdf_agg=tdf.groupby('merchant').agg({'tint':['mean','std'],'tinactive':'mean'})

    tdf_agg.columns=['tintM','tintS','inactiveM']
    churn1MID=tdf_agg.index[(tdf_agg.inactiveM > fixedTh)]
    churn2MID=tdf_agg.index[(tdf_agg.inactiveM > (tdf_agg.tintM + tdf_agg.tintS * factorStd).apply(lambda x: max(min(x,maxcap),mincap) ))]

    eligiblet = (df.time> midpt)
    tdf2=df[eligiblet]
    year2MID=tdf2.merchant.unique()

    mischurn.append([midpt, sum(churn1MID.isin(year2MID)), sum(churn2MID.isin(year2MID)),len(churn1MID), len(churn2MID), tdf_agg.shape[0]])

mischurn

fixedTh=90
mincap=30
maxcap=180
factorStd=4
df_filtered.isnull().sum()
import numpy as np
from sklearn.preprocessing import Imputer
imp = Imputer(missing_values=np.nan, strategy='mean')
imp.fit(df_filtered[[  'tint_mean_O', 'tint_std_O' ]].values)
df_filtered[[  'tint_mean_O', 'tint_std_O' ]]=imp.transform(df_filtered[[ 'tint_mean_O', 'tint_std_O'  ]])

churnETA=(df_filtered.tint_mean_O+df_filtered.tint_std_O * factorStd).apply(lambda x: max(min(int(x),maxcap),mincap) )
#perc1(churnETA)

churnind=df_filtered.tinactive_O>churnETA
churnedID=df_filtered.index[churnind]
churnedTime=df_filtered.endtime_O[churnind] + churnETA.apply(lambda x: np.timedelta64(x,'D'))[churnind]

len(churnedID)/df_filtered.shape[0]
df_filtered['churned']=churnind

tmpp=df_filtered.groupby('label')['churned'].agg(['sum','size'])
tmpp.columns=['Churned merchant', 'Total merchants']
tmpp.index=[int(x+1) for x in tmpp.index.values]
ax=tmpp.plot(kind='bar',title='# of merchant counts and churned per cluster')
ax.set_xlabel('cluster')
ax.set_ylabel('# of merchants')

ax=(tmpp.iloc[:,0]/tmpp.iloc[:,1]*100).plot(kind='bar',title='% of churn per cluster')
ax.set_xlabel('cluster')
ax.set_ylabel('% of churn')

churnobsMonths=3
trainMonths=15
churnstart=pd.to_datetime('2034-12-31 20:07:57')-pd.Timedelta(churnobsMonths,unit='M')
time_st=churnstart-pd.Timedelta(trainMonths,unit='M')
time_end=churnstart

churned2034=churnedID[(churnedTime>churnstart)  ]
churned2033=churnedID[churnedTime<churnstart]

df_train_2033=generatefeatures(df, time_st, time_end)
del df_train_2033['endtime_O']
df_train_2033.isnull().sum()

df_train_2033 = df_train_2033[~(df_train_2033.index.isin(churned2033))]
df_train_2033.isnull().sum()

imp = Imputer(missing_values=np.nan, strategy='mean')
imp.fit(df_train_2033.values)
df_train_2033[:]=imp.transform(df_train_2033)

import seaborn as sns
corr=df_train_2033.corr()
kot=corr[corr>0.95]
plt.figure(figsize=(12,8))
sns.heatmap(kot, cmap='Greens')

y=df_train_2033.index.isin(churned2034)
xTrain, xTest, yTrain, yTest = train_test_split(df_train_2033, y, test_size=0.25, random_state=5)

model_params = {
    'n_estimators': [200, 400],
    'max_depth': [5, 20, 50]
}
rf_model = RandomForestClassifier(random_state=1)
grid_clf = GridSearchCV(rf_model, model_params, cv=5)
RF = grid_clf.fit(xTrain, yTrain)
sc_RF=RF.score(xTest, yTest)
RF.best_params_
RF_p=RF.predict_proba(xTest)

precision, recall, thresholds=precision_recall_curve(yTest, RF_p[:,1])
auc0=auc(recall, precision)
false_positive_rate, true_positive_rate, threshold=roc_curve(yTest, RF_p[:,1])
roc_auc=auc(false_positive_rate, true_positive_rate)

plt.plot(false_positive_rate, true_positive_rate, color='b',  label='ROC curve (area = %0.2f)' % roc_auc)
plt.plot([0, 1], [0, 1], color='navy',   linestyle='--')
plt.xlim([0.0, 1.0])
plt.ylim([0.0, 1.05])
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')
plt.legend(loc="lower right")
plt.show()

plt.plot(recall,precision, color='b',  label='ROC curve (area = %0.2f)' % auc0)
plt.plot([0, 1], [0, 0], color='navy',  linestyle='--')
plt.xlim([0.0, 1.0])
plt.ylim([0.0, 1.05])
plt.xlabel('Recall')
plt.ylabel('Precision')
plt.legend(loc="lower right")
plt.show()

coef=[]
cols=df_train_2033.columns
for col in cols:
    coef=coef+[np.corrcoef(df_train_2033[col],y)[0,1]]
corcoef=pd.DataFrame({'corr_coef':coef, 'colname':cols})
corcoef['abs_corr_coef']=abs(corcoef.corr_coef)
corcoef=corcoef.sort_values('abs_corr_coef')

ftrImp=pd.DataFrame({'imp_RF':RF.best_estimator_.feature_importances_, 'colname':cols})
ftrImp=ftrImp.merge(corcoef, on='colname',how='left')
ftrImp=ftrImp.sort_values(['imp_RF'], ascending=[0])

f, ax = plt.subplots(figsize=(6, 15))
sns.set_color_codes("pastel")
sns.barplot(y="colname", x="imp_RF", data=ftrImp,
            label="randomForest", color="b")

sns.set_color_codes("muted")
sns.barplot(y="colname", x="corr_coef", data=ftrImp,
            label="PearsonCorrelation", color="g",alpha=0.3)

ax.legend(ncol=2, loc="lower right", frameon=True)
ax.set(xlim=(0, 24), ylabel="",
       xlabel="feature importance")
sns.despine(left=True, bottom=True)

n=20

RF1 = RandomForestClassifier( n_estimators= 400, max_depth=20, class_weight='balanced').fit(xTrain[ftrImp.colname[:n]],yTrain)
sc_RF1=RF1.score(xTest[ftrImp.colname[:n]], yTest)
RF1_p=RF1.predict_proba(xTest[ftrImp.colname[:n]])

precision, recall, thresholds=precision_recall_curve(yTest, RF1_p[:,1])
auc1=auc(recall, precision)
false_positive_rate, true_positive_rate, threshold=roc_curve(yTest, RF1_p[:,1])
roc_auc1 = auc(false_positive_rate, true_positive_rate)

RF2 = RandomForestClassifier( n_estimators= 400, max_depth=20, class_weight='balanced').fit(xTrain.tinactive_O.values.reshape(-1,1),yTrain)
sc_RF2=RF2.score(xTest.tinactive_O.values.reshape(-1,1), yTest)

print([churnobsMonths, trainMonths, sc_RF, sc_RF1, sc_RF2, auc0, auc1, roc_auc, roc_auc1])

#grid={"C":np.logspace(-3,3,7), "penalty":["l1","l2"]}
#logreg=LogisticRegression()
#logreg_cv=GridSearchCV(logreg,grid,cv=10)
#logreg_cv.fit(xTrain,yTrain)
#logreg_cv.score(xTest,yTest)
#

import scikitplot as skplt
skplt.metrics.plot_lift_curve(y_true=yTest, y_probas = RF_p)

df_score=generatefeatures(df, pd.to_datetime('2034-12-31 20:07:57')-pd.Timedelta(trainMonths,unit='M'), pd.to_datetime( '2034-12-31 20:07:57') )
del df_score['endtime_O']
df_score=df_score[~(df_score.index.isin(churnedID))]

imp = Imputer(missing_values=np.nan, strategy='mean')
imp.fit(df_score.values)
df_score[:]=imp.transform(df_score)

p=RF.predict_proba(df_score)

tmp=RF_p[:,1]
tmp.sort()
thresholdP=np.percentile(tmp, 70)

df_score['churnLabel']='Not churned'
df_score['churnLabel'][p[:,1]>=thresholdP]='Likely to churn'
df_score.groupby('churnLabel').size().plot(kind='bar')
sum(df_score['churnLabel']=='Likely to churn' )/df_score.shape[0]

df_score['propensityScore']=p[:,1]
df_score[['propensityScore','churnLabel']].to_csv(r'C:\Users\Min\scored.csv')

df_filtered['churned'].to_csv(r'C:\Users\Min\churned.csv')

df_filtered_O['churned'] =  df_filtered_O.tinactive>90
df_filtered_O['churned'] =  df_filtered['churned']
perc2(df_filtered_O.tint_mean_O.dropna())

sns.distplot(df_filteredO.tint_mean_O[df_filteredO.churned].dropna(), color="dodgerblue", label="churned")
sns.distplot( df_filteredO.tint_mean_O[~df_filteredO.churned].dropna(), color="orange", label="not churned")
plt.legend(loc='upper right')
plt.xlabel('# days between first and latest transactions')
plt.title('Density of inactive days comparison (churned vs. active users)')
plt.show()
df_filtered['loggedTintMean']= np.log(df_filtered.tint_mean_O+1)
fig =  sns.boxplot(x="churned", y="loggedTintMean", data=df_filtered, palette="Set3")
fig.set(  ylabel='logged average # days between transaction')

sns.distplot(df_filteredO.tint_std_O[df_filtered.churned].dropna(), color="dodgerblue", label="churned")
sns.distplot( df_filteredO.tint_std_O[~df_filtered.churned].dropna(), color="orange", label="not churned")
plt.legend(loc='upper right')
plt.xlabel('# days between first and latest transactions')
plt.title('Density of identified account tenure comparison (churned vs. active users)')
plt.show()
df_filtered['loggedTintStd']= np.log(df_filtered.tint_mean_O+1)
fig =  sns.boxplot(x="churned", y="loggedTintStd", data=df_filtered, palette="Set3")
fig.set(  ylabel='# days holding the account')

fig =  sns.boxplot(x="churned", y="length_O", data=df_filtered, palette="Set3")
fig.set(  ylabel='# days holding the account')

fig =  sns.boxplot(x="churned", y="tinactive_O", data=df_filtered, palette="Set3")
fig.set(  ylabel='# days from the latest transaction')

# check if the score stays similar

churnobsMonths=3
trainMonths=15
churnstart=pd.to_datetime('2034-09-30 20:07:57')-pd.Timedelta(churnobsMonths,unit='M')
time_st=churnstart-pd.Timedelta(trainMonths,unit='M')
time_end=churnstart

churned2034=churnedID[(churnedTime>churnstart)  ]
churned2033=churnedID[churnedTime<churnstart]

df_train_2033=generatefeatures(df, time_st, time_end)
del df_train_2033['endtime_O']
df_train_2033.isnull().sum()

df_train_2033 = df_train_2033[~(df_train_2033.index.isin(churned2033))]
df_train_2033.isnull().sum()

imp = Imputer(missing_values=np.nan, strategy='mean')
imp.fit(df_train_2033.values)
df_train_2033[:]=imp.transform(df_train_2033)

y=df_train_2033.index.isin(churned2034)
sc_RF=RF.score(df_train_2033, y)
p1=RF.predict_proba(df_train_2033)

precision, recall, thresholds=precision_recall_curve(yTest, p1[:,1])
auc0=auc(recall, precision)
false_positive_rate, true_positive_rate, threshold=roc_curve(yTest, p1[:,1])
roc_auc=auc(false_positive_rate, true_positive_rate)


for i in range(4):
    print(i)
range(4) # = range(0, 4)
list(range(4)) # =[0, 1, 2, 3]
list(range(0, 100, 2))

colours = ['pink', 'blue', 'yellow', 'green']
for colour in range(len(colours)):
    print('The colour at index ' + str(colour) + ' in the list of coulours is ' + colours[colour])

### multiple assignment
cat = ['fat', 'orange', 'loud']
size = cat[0]
colour = cat[1]
disposition = cat[2]
##instead:
dog = ['small', 'brown', 'quiet']
size, colour, disposition = dog
print(colour)

##swapping variables
a = 'AAA'
b = 'BBB'

a, b = b, a
print(a, b)


#automatic.pyを実行し、search.pyを呼び出す
from selenium import webdriver
import search

#chromedriverのpathを指定する
browser = webdriver.Chrome(executable_path='/Users/MatsumotoNasa/Desktop/step/hw1/chromedriver')
browser.get('https://icanhazwordz.appspot.com/')

total_score = 0
#search.pyのdictionary関数を呼び出す
dic = search.dictionary()

#単語入力を10回繰り返す
for i in range(10):
	character = ""
	letters = ""

	#ゲームのWebサイトから16文字を読み込む
	for i in range(1,5):
		for j in range(1,5):
			character = browser.find_element_by_xpath('//table[1][@border="2"]/tbody/tr/td[1]/table/tbody/tr[' + str(j) + ']/td[' + str(i) + ']/div')
			letters = letters + character.text

	#search.pyのmain関数を呼び出す
	high = search.main(letters, dic)
	high_words = high[0]
	total_score = total_score + high[1]

	#scoreをSubmitする。16文字で１つも単語が作れない場合はPASSする。
	if (high[1] > 0):
		browser.find_element_by_id("MoveField").send_keys(high_words)
		browser.find_element_by_xpath('//input[@type="submit"]').click()
	else:
		browser.find_element_by_name('pass').click()

#total score を出力
print('total_score = ' + str(total_score))


#! /usr/bin/env python
# -*- coding: UTF8 -*-

"""
anatomy.py
Description:    Manage the anatomical components of a rig
Syntax:         Called through the maya 2013 command line as a python module
Algorithm:      None
Usage example: 'rt.anatomy.*part*()'

This script takes several arguments and prints out any errors that might occur
during processing
"""

#==============================================================================
# auther:           Teddy Dlukulu
# version:          0.1
# status:           prototype
# date:             11/07/2013
# maintainer:       "www.teddydlukulu.com"
# credits:          "Thanks to Everyone"
# Platform:         Maya 2013
# Python Version:   2.7.5
#==============================================================================

"""
The following classes describe the various states and properties held in each
known anatomical part in the rig. The script is to be either copied and
renamed for each instance of the rig then stored into a project specific folder,
or instantiated and used locally by the referencing script.

Setting a value:
boneName['property'] = 'value'
"""

import maya.cmds as mc
from RtLib import bones

toolsFolder = "G:\\RigTools\\Python"

# Property storage template for skeleton
class bone(joint, count = 1):
    # Get the reference geometry
    bneloc = joint.replace("Bne", "BneLoc")

    # Transforms
    transform = {trnX: mc.getAttr('%s.translateX' % joint), \
                 trnY: mc.getAttr('%s.translateY' % joint), \
                 trnZ: mc.getAttr('%s.translateZ' % joint), \
                 rotX: mc.getAttr('%s.rotateX' % joint), \
                 rotY: mc.getAttr('%s.rotateY' % joint), \
                 rotZ: mc.getAttr('%s.rotateZ' % joint), \
                 sclX: mc.getAttr('%s.scaleX' % joint), \
                 sclY: mc.getAttr('%s.scaleY' % joint), \
                 sclZ: mc.getAttr('%s.scaleZ' % joint)}

    # Position in world space
    position = {posX: '%s.translateX' % bneLoc, \
                posY: '%s.translateY' % bneLoc, \
                posZ: '%s.translateZ' % bneLoc}

    # Set the names of the geomatry referenced by the joint
    # Generic bone properties dictionary:
    properties = {geo: joint, \
                  loc: bneLoc, \
                  file: toolsFolder + "\\RtSetup\\RtAssets\\bneLib\\%s" % (joint + ".ma"), \
                  parent: 'bones.%s[parent]' % joint, \
                  child: 'bones.%s[child]' % joint, \
                  description: 'bones.%s[description]' % joint, \
                  parentConst: 'bones.%s[parentConst]' % joint, \
                  fkControl: 'bones.%s[fkCtrl]' % joint, \
                  ikControl: 'bones.%s[ikCtrl]' % joint, \
                  useLimit: False, \
                  limitX: 'bones.%s[lim[0]]' % joint, \
                  limitY: 'bones.%s[lim[1]]' % joint, \
                  limitZ: 'bones.%s[lim[2]]' % joint, \
                  limitOffset: (0.0, 0.0, 0.0), \
                  jntBnd: joint.replace("Bne", "JntBnd"), \
                  jntFk: joint.replace("Bne", "JntFk%i" % count), \
                  jntIk: joint.replace("Bne", "JntIk%i" % count), \
                  jntMk: joint.replace("Bne", "JntMk%i" % count), \
                  jntTk: joint.replace("Bne", "JntTk%i" % count), \
                  ctlFk: joint.replace("Bne", "CtlFk%i" % count), \
                  ctlIk: joint.replace("Bne", "CtlIk%i" % count), \
                  CtlMk: joint.replace("Bne", "CtlMk%i" % count), \
                  CtlTk: joint.replace("Bne", "CtlTk%i" % count)}

class direction():
    # hand placement definitions
    handPlaceDef = {"inferiorly": 'palm down', \
                        "superiorly": 'palm up', \
                        "medially": 'palm in', \
                        "laterally": 'palm out', \
                        "posteriorly": 'palm back', \
                        "anteriorly": 'palm foreward'}

    # anatomical direction definitions
    anatomicalDirecttion = {"anterior": 'foreward', \
                                "posterior": 'backward', \
                                "superior": 'upward', \
                                "inferior": 'downward', \
                                "median": 'inward', \
                                "lateral": 'outward'}

    # relative proximity definitions
    relativeProximity = {"proximal": 'closer to midsaggital', \
                             "distal": 'further from midsaggital', \
                             "cranial": 'towards the head', \
                             "caudal": 'towards the tail end', \
                             "ventral": 'towards the belly', \
                             "dorsal": 'towards the backside'}

    # anatomical plane definitions
    anatomicalPlanes = {"coronal": 'fornt & back', \
                            "midsaggital": 'left & right', \
                            "transverse": 'top & bottom'}

    # joint motion definition
    # description
    jntMotDescription = "All movements are relative to the vector of their parent joint"
    # definition
    jointMotion = {"flexion": 'decrease the angle between 2 articulating joints', \
                       "extension": 'increase the angle between 2 articulating joints', \
                       "abduction": 'move the joint away from the midsaggital', \
                       "adduction": 'move the joint towards the midsaggital', \
                       "rotation": 'the joint twists around its own axis', \
                       "circumduction": 'the distal end moves around its proximal', \
                       "supination": 'rotate the hand so that palm is superior', \
                       "pronation": 'rotate the hand so that the palm is inferior', \
                       "inversion": 'turn the foot so that the sole faces inwards', \
                       "eversion": 'turn the foot so that the sole faces outwards', \
                       "elevation": 'raising a body part', \
                       "depression": 'lowering a body part', \
                       "protraction": 'jut a body part out', \
                       "retraction": 'jut a body part in', \
                       "hyperextension": 'beyond the normal extension', \
                       "planter flexion": 'extension of the foot away from the transverse plane', \
                       "dorsiflexion": 'retraction of the foot towards the transverse plane'}
    # types
    angularJntTypes = ['hinge', 'ellipsoidal', 'saddle']
    jointMotionTypes = {"arthrodial": 'gliding joint', \
                            "angular": 'hinge, ellipsoidal, saddle', \
                            "hinge": 'single axis (mono-axial)', \
                            "ellipsoidal": 'double axis (bi-axial)', \
                            "saddle": '3+ axis (multi-axial)', \
                            "pivot": 'multidirectional rotation (multi-axial)', \
                            "ball & socket": 'complex rotation (multi-axial/spheroidal)'}

    # creature chatacteristic definitions
    # leg count definitions
    legCount = {"bipedal": '2 legs', \
                    "quadropedal": '4 legs'}
    # thorax placement
    thoraxOrientation = {"orthograde": 'shoulders above hips', \
                             "pronograde": 'shoulders in front of hips'}
    # creature types
    creatureType = {"aquatic": 'swimmer', \
                        "volant": 'flyer', \
                        "cursorial": 'runner', \
                        "scansorial": 'climber', \
                        "saltatorial": 'hopper', \
                        "fossorial": 'digger'}


kontakty = {'Paweł':123456789, 'Marek':147258369, 'Julia':147963258, 'Katarzyna':123654789, 'Ola':159482673}
co = 0
while co != 4:
    co = int(input('Co chcesz zrobić?:\n'
                '1 - wyświetl listę kontaktów\n'
                '2 - dodaj kontakt\n'
                '3 - usuń kontakt\n'
                '4 - wyjdź'))
    if co == 1:
        for kontakt,numer in kontakty.items():
            print(kontakt, 'ma numer telefonu:', numer)
        continue
    elif co == 2:
        x = str(input('Podaj imię:'))
        if x in kontakty:
            print('Ten kontakt już istnieje')
            break
        y = int(input('Podaj numer telefonu:'))
        kontakty[x] = y
        print(x, 'został dodany. Jego numer to ', y, '.')
    elif co == 3:
        d = str(input('Podaj imię kontaktu do usunięcia:'))
        if d in kontakty:
            kontakty.pop(d)
            print('Kontakt "%s" został usunięty.' % d)
        else:
            print('Taki kontakt nie istnieje.')
    elif co == 4:
        print('Do widzenia!')
    else:
        print('Niestety podałeś nieprawidłową komendę :/')


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

import telegram
import info

class Telegram:

    __bot = None
    user_id = info.Telegram.user_id

    @staticmethod
    def init():
        my_token = info.Telegram.token
        Telegram.__bot = telegram.Bot(token=my_token)

    @staticmethod
    def print_update():
        updates = Telegram.__bot.getUpdates()

        for u in updates:
            print(u.message)

    @staticmethod
    def send_message(text):
        Telegram.__bot.sendMessage(chat_id=Telegram.user_id,
                                   text=text)

if __name__ == '__main__':

    Telegram.init()
    Telegram.send_message('???')


#avg2.py
# A Simple program to average two exam scores
# Illustrates use of multiple input

def main():
    print ("This program computes the average of two exam scores.")

    score1, score2 = eval(input("Enter two scores seperated by a comma: ")) #What is user enters text or single value?
    # We could also use
    # score1 = eval(input("Enter the first score "))
    # score2 = eval(input("Enter the second s core "))
    average = (score1 + score2) / 2

    print ("The average of the scores is:", average)

main()
# calling the script from idle or python:
# import average or average.main()


"""
    Question : Let's Create a quiz system
        program give some questions and user try to correct answer
        finally program will show result table
"""

class Question():
    def __init__(self, text, choice, answer):
        self.text = text
        self.choice = choice
        self.answer = answer

    def checkAnswer(self, answer):
        return self.answer == answer

class Quiz():
    def __init__(self, questions):
        self.questions = questions
        self.score = 0
        self.questionIndex = 0

    def getQuestion(self):
        return self.questions[self.questionIndex]

    def diplayQuestion(self):
        a = 1
        question = self.getQuestion()
        print(f'Question {self.questionIndex + 1} : {question.text}')
        for i in question.choice:
            print(f'{a} -> '+i)
            a += 1
        answer = input('Answer : ')
        self.guess(answer)
        self.loadQuestion()

    def guess(self, answer):
        question = self.getQuestion()

        if(question.checkAnswer(answer)):
            self.score += 50
        self.questionIndex += 1

    def loadQuestion(self):
        if(len(self.questions) == self.questionIndex):
            self.showScore()
        else:
            self.diplayQuestion()

    def showScore(self):
        print(f'Your score is : {self.score} ')

q1 = Question('Whats the first programming language ? (50 points)',
              ['Pascal', 'Cobol', 'Plankalkül', 'Ada'], 'Plankalkül')
# You can create more than one question like this

q2 = Question('whats the first procedural language ? (50 points)',
              ['Pascal', 'Cobol', 'Plankalkül', 'Fortran'], 'Fortran')

question = [q1, q2]

quiz = Quiz(question)
question = quiz.getQuestion()
quiz.diplayQuestion()
print('The End')


#!/usr/bin/env python3

'''Test creating a WindowSurface bound to an X11 window.'''

# Copyright (c) 2014 Tim Pederick.
# Based on examples/draw.py from python-x11:
#     Copyright (c) 2000 Peter Liljenberg <petli@ctrl-c.liu.se>
#
# This file is part of Pegl.
#
# Pegl is free software: you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Pegl is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
# License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Pegl. If not, see <http://www.gnu.org/licenses/>.

from pegl import display, config, surface
from Xlib import X, display as Xdisplay

class TestApp:
    '''A bare-bones X11 window.'''
    def __init__(self, dpy):
        self.Xdisplay = dpy
        self.screen = self.Xdisplay.screen()

        self.window = self.screen.root.create_window(5, 5, 640, 480, 1,
                                                     self.screen.root_depth)
        self.DELETE_WINDOW = self.Xdisplay.intern_atom('WM_DELETE_WINDOW')
        self.PROTOCOLS = self.Xdisplay.intern_atom('WM_PROTOCOLS')

        self.window.set_wm_name('Pegl test: X11')
        self.window.set_wm_protocols((self.DELETE_WINDOW,))

        self.EGLdisplay = display.Display()
        self.config = config.get_configs(self.EGLdisplay)[0]
        self.surface = surface.WindowSurface(self.EGLdisplay, self.config, {},
                                             self.window.id)
        self.window.map()

    def loop(self):
        while True:
            ev = self.Xdisplay.next_event()

            if ev.type == X.DestroyNotify:
                raise SystemExit()
            elif ev.type == X.ClientMessage:
                fmt, data = ev.data
                if fmt == 32 and data[0] == self.DELETE_WINDOW:
                    raise SystemExit()

if __name__ == '__main__':
    app = TestApp(Xdisplay.Display())
    app.loop()


#!/usr/bin/python3

'''
Date: 17/Nov/2021
Author name: Luis Felipe Cedeño Pérez (pipecedeno@gmail.com)
version: 1.0

Program Description:
This program is used to delete non A,T,C,G or N letters from the genome were the kmers are going to be aligned,
this is important because razers marks an error is any other letter is found in the sequence. The non ATCGN
letters are passed to N, and a new file is created with the modified genome so the original file isn't modified.

Inputs:
-f genome file to be processed
-o name of the output file (the processed genome)
'''

import argparse

parser = argparse.ArgumentParser(description="")
parser.add_argument("-f", "--file",dest="file",required=True) #genome file
parser.add_argument("-o", "--output", dest="output", required=True) #output file
args = parser.parse_args()

genome=open(args.file,"r")
resp=open(args.output,"w")

for line in genome:
	if(">" in line):
		resp.write(line)
	else:
		for base in list(line.rstrip("\n")):
			if((set(base) <= set('ATCG'))):
				resp.write(base)
			else:
				resp.write("N")
		resp.write("\n")
genome.close()
resp.close()


from model.contact import Contact
import re

class ContactHelper:

    def __init__(self, app):
        self.app = app

    def modification_contact(self, middlename, address, email):
        wd = self.app.wd
        self.home_page()
        # select contact
        wd.find_element_by_name("selected[]").click()
        # edit contact
        wd.find_element_by_xpath("//table[@id='maintable']/tbody/tr[2]/td[8]/a/img").click()
        # middlename
        wd.find_element_by_name("middlename").click()
        wd.find_element_by_name("middlename").clear()
        wd.find_element_by_name("middlename").send_keys(middlename)
        # address
        wd.find_element_by_name("address").click()
        wd.find_element_by_name("address").clear()
        wd.find_element_by_name("address").send_keys(address)
        # email
        wd.find_element_by_name("email").click()
        wd.find_element_by_name("email").clear()
        wd.find_element_by_name("email").send_keys(email)
        # submit modification
        wd.find_element_by_name("update").click()

    def select_contact_by_index(self, index):
        wd = self.app.wd
        wd.find_elements_by_name("selected[]")[index].click()

    def select_contact_by_id(self, id):
        wd = self.app.wd
        wd.find_element_by_css_selector("input[value='%s']" % id).click()

    def delete_first_contact(self):
        self.delete_contact_by_index(0)

    def delete_contact_by_index(self, index):
        wd = self.app.wd
        self.home_page()
        self.select_contact_by_index(index)
        #submit deletion
        wd.find_element_by_xpath("//div[@id='content']/form[2]/div[2]/input").click()
        wd.switch_to_alert().accept()
        self.contact_cache = None

    def delete_contact_by_id(self, id):
        wd = self.app.wd
        self.home_page()
        self.select_contact_by_id(id)
        #submit deletion
        wd.find_element_by_xpath("//div[@id='content']/form[2]/div[2]/input").click()
        wd.switch_to_alert().accept()
        self.contact_cache = None

    def select_first_contact(self):
        wd = self.app.wd
        wd.find_element_by_name("selected[]").click()

    def create(self, contact):
        wd = self.app.wd
        self.home_page()
        self.open_add_new_page()
        self.fill_contact_form(contact)
        # submit contact creation
        wd.find_element_by_xpath("//div[@id='content']/form/input[21]").click()
        self.contact_cache = None

    def fill_contact_form(self, contact):
        wd = self.app.wd
        self.change_field_value_contact("firstname", contact.firstname)
        self.change_field_value_contact("lastname", contact.lastname)
        self.change_field_value_contact("title", contact.title)
        self.change_field_value_contact("company", contact.company)
        self.change_field_value_contact("address", contact.address)
        self.change_field_value_contact("mobile", contact.mobilephone)
        self.change_field_value_contact("email", contact.email)

    def change_field_value_contact(self, field_firstname, text):
        wd = self.app.wd
        if text is not None:
            wd.find_element_by_name(field_firstname).click()
            wd.find_element_by_name(field_firstname).clear()
            wd.find_element_by_name(field_firstname).send_keys(text)

    def home_page(self):
        wd = self.app.wd
        if not (wd.current_url.endswith("/addressbook/") and
                len(wd.find_elements_by_xpath("//div/div[4]/form[2]/input[2]")) > 0):
            wd.find_element_by_link_text("home").click()

    def open_add_new_page(self):
        wd = self.app.wd
        wd.find_element_by_link_text("add new").click()

    def modify_first_contact(self, new_contact_data):
        self.modify_contact_by_index(0, new_contact_data)

    def modify_contact_by_index(self, index, new_contact_data):
        wd = self.app.wd
        self.home_page()
        #self.select_contact_by_index(index)
        # open modification form
        wd.find_element_by_xpath("//table[@id='maintable']/tbody/tr["+str(index)+"]/td[8]/a/img").click()
        # fill contact form
        self.fill_contact_form(new_contact_data)
        # submit modification
        wd.find_element_by_name("update").click()
        self.contact_cache = None

    def modify_contact_by_id(self, id, new_contact_data):
        wd = self.app.wd
        self.home_page()
        # open modification form
        wd.find_element_by_xpath('//a[@href="edit.php?id='+id+'"]').click()
        # fill contact form
        self.fill_contact_form(new_contact_data)
        # submit modification
        wd.find_element_by_name("update").click()
        self.contact_cache = None

    contact_cache = None

    def get_contact_list(self):
        if self.contact_cache is None:
            wd = self.app.wd
            self.home_page()
            self.contact_cache = []
            for row in wd.find_elements_by_name("entry"):
                cells = row.find_elements_by_tag_name("td")
                lastname = cells[1].text
                firstname = cells[2].text
                address = cells[3].text
                #id = cells[0].find_element_by_name("selected[]").get_attribute("value")
                id = cells[0].find_element_by_tag_name("input").get_attribute("value")
                all_phones = cells[5].text
                all_emails = cells[4].text
                #contact = Contact(firstname=cells[2].text, lastname=cells[1].text, id=id)
                self.contact_cache.append(Contact(firstname=firstname,
                                                  lastname=lastname,
                                                  address=address,
                                                  id=id,
                                                  all_phones_from_home_page=all_phones,
                                                  all_emails_from_home_page=all_emails))
        return list(self.contact_cache)

    def open_contact_to_edit_by_index(self, index):
        wd = self.app.wd
        self.home_page()
        row = wd.find_elements_by_name("entry")[index]
        cell = row.find_elements_by_tag_name("td")[7]
        cell.find_element_by_tag_name("a").click()

    def open_contact_view_by_index(self, index):
        wd = self.app.wd
        self.home_page()
        row = wd.find_elements_by_name("entry")[index]
        cell = row.find_elements_by_tag_name("td")[6]
        cell.find_element_by_tag_name("a").click()

    def get_contact_info_from_edit_page(self, index):
        wd = self.app.wd
        self.open_contact_to_edit_by_index(index)
        firstname = wd.find_element_by_name("firstname").get_attribute("value")
        lastname = wd.find_element_by_name("lastname").get_attribute("value")
        id = wd.find_element_by_name("id").get_attribute("value")
        homephone = wd.find_element_by_name("home").get_attribute("value")
        workphone = wd.find_element_by_name("work").get_attribute("value")
        mobilephone = wd.find_element_by_name("mobile").get_attribute("value")
        secondaryphone = wd.find_element_by_name("phone2").get_attribute("value")
        email = wd.find_element_by_name("email").get_attribute("value")
        email2 = wd.find_element_by_name("email2").get_attribute("value")
        email3 = wd.find_element_by_name("email3").get_attribute("value")
        address = wd.find_element_by_name("address").get_attribute("value")
        return Contact(firstname=firstname, lastname=lastname, id=id, homephone=homephone,
                       workphone=workphone, mobilephone=mobilephone, secondaryphone=secondaryphone,
                       email=email, email2=email2, email3=email3, address=address)

    def get_contact_from_view_page(self, index):
        wd = self.app.wd
        self.open_contact_view_by_index(index)
        text = wd.find_element_by_id("content").text
        homephone = re.search("H: (.*)", text).group(1)
        workphone = re.search("W: (.*)", text).group(1)
        mobilephone = re.search("M: (.*)", text).group(1)
        secondaryphone = re.search("P: (.*)", text).group(1)
        return Contact(homephone=homephone,
                       workphone=workphone, mobilephone=mobilephone, secondaryphone=secondaryphone)

    def add_contact_to_group(self, contact_id, group_id):
        wd = self.app.wd
        wd.find_element_by_id(contact_id).click()
        wd.find_element_by_xpath("//select[@name='to_group']/option[@value='"+group_id+"']").click()
        wd.find_element_by_name("add").click()
        wd.find_element_by_link_text("home").click()
        wd.find_element_by_xpath("//select[@name='group']/option[@value='" + group_id + "']").click()

    def delete_contact_from_group(self, contact_id, group_id ):
        wd = self.app.wd
        wd.find_element_by_xpath("//select[@name='group']/option[@value='"+group_id+"']").click()
        wd.find_element_by_id(contact_id).click()
        wd.find_element_by_name("remove").click()
        wd.find_element_by_link_text("home").click()
        wd.find_element_by_xpath("//select[@name='group']/option[@value='" + group_id + "']").click()

    def count(self):
        wd = self.app.wd
        self.home_page()
        return len(wd.find_elements_by_name("selected[]"))


#!/usr/bin/python
# -*- codding: utf-8 -*-
import os
import sys
sys.path.append(os.path.dirname(os.path.abspath(os.path.dirname(__file__))))
from common.execute_command import write_one_parameter

# url : https://awscli.amazonaws.com/v2/documentation/api/latest/reference/autoscaling/create-or-update-tags.html
if __name__ == '__main__':
    """

    """

    parameter_display_string = """
    # tags : One or more tags.
(structure)

Describes a tag for an Auto Scaling group.
ResourceId -> (string)

The name of the group.

ResourceType -> (string)

The type of resource. The only supported value is auto-scaling-group .

Key -> (string)

The tag key.

Value -> (string)

The tag value.

PropagateAtLaunch -> (boolean)

Determines whether the tag is added to new instances as they are launched in the group.
    """
    add_option_dict = {}

    #######################################################################
    # parameter display string
    add_option_dict["parameter_display_string"] = parameter_display_string
    # ex: add_option_dict["no_value_parameter_list"] = "--single-parameter"
    write_one_parameter("autoscaling", "create-or-update-tags", "tags", add_option_dict)


#!/usr/bin/env python
# -*- coding:utf-8 -*-

#!/usr/bin/env python
# -*- coding:utf-8 -*-
from config.random_date import *
import uiautomator2 as u2
import unittest
import time
from utx import *
import uiautomator2.ext.ocr as ocr

class TestCase(unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        cls.d = u2.connect()
        ocr.API = "http://ocr.open.netease.com/api/ocr"
        u2.plugin_register("ocr", ocr.OCR)
        cls.d.set_orientation('natural')
        cls.d.healthcheck()
        cls.d.implicitly_wait(10)
        cls.d.app_clear("com.xiaoxiao.ludan")
        cls.d.app_stop_all()
        cls.NowTime = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
        cls.test_random = test_random_date()
        Case_DIR = os.path.abspath(os.path.dirname(__file__))
        cls.loanID_PATH = os.path.join(Case_DIR + "\\config\\loan_info.txt")

    def setUp(self):
        self.d.set_fastinput_ime(True)
        self.sess = self.d.session("com.xiaoxiao.ludan")
        self.name = self.test_random.get_name()
        self.phone = self.test_random.createPhone()
        self.idcard = self.test_random.idcard_generator()

    def tearDown(self):
        self.d.app_stop_all()
        self.d.set_fastinput_ime(False)

    def login(self,username,password):
        d = self.sess
        d.watchers.remove()
        d.watchers.watched = False
        log.info('开始登录>>>>>>>>>>')
        d.watcher("获取app权限").when(resourceId="android:id/button1").when(text="允许").click(text="允许")
        d.watchers.run()
        d(resourceId="com.xiaoxiao.ludan:id/et_account").set_text(username,timeout=10)
        d(resourceId="com.xiaoxiao.ludan:id/et_password").set_text(password,timeout=5)
        d(resourceId="com.xiaoxiao.ludan:id/bt_login").click_exists(timeout=5)
        if d(resourceId="com.xiaoxiao.ludan:id/title").exists(timeout=2) == True:
            d(resourceId="com.xiaoxiao.ludan:id/ed_vc").set_text('8888',timeout=5)
            d(resourceId="com.xiaoxiao.ludan:id/tv_sign").click(timeout=5)
        else:
            pass
        self.assertTrue(d(text=u"首页").exists(timeout=3),msg=d.toast.get_message(10, 5))
        log.info('服务器返回：%s' % d.toast.get_message(10, 10))
        print('服务器返回：%s' % d.toast.get_message(10, 10))

    @tag(Tag.Encoding)
    def test_update_loan(self):
        """ 按揭员更新贷款

        :return:
        """
        d = self.sess
        self.login(69,12345678)
        log.info('开始更新贷款>>>>>>>>>>')
        d(resourceId="com.xiaoxiao.ludan:id/tv_menu", text=u"贷款跟进").click(timeout=10)
        self.assertTrue(d(resourceId="com.xiaoxiao.ludan:id/et_pact_search").exists(timeout=3),msg=d.toast.get_message(10, 5))
        if d(resourceId="com.xiaoxiao.ludan:id/tv_search_type",text='客户名').exists() == True:
            d(resourceId="com.xiaoxiao.ludan:id/tv_search_type", text='客户名').click()
        else:
            self.d.ext_ocr.all()
            self.d.ext_ocr("客户名").click(timeout=3)
        d(text=u"贷款号").click(timeout=2)
        with open(self.loanID_PATH, 'r') as f:
            loan_id = f.read()
            log.info('本次待更新的贷款编号为：%s' % loan_id)
            print('本次待更新的贷款编号为：%s' % loan_id)
        d(resourceId="com.xiaoxiao.ludan:id/et_pact_search").clear_text()
        d(resourceId="com.xiaoxiao.ludan:id/et_pact_search").set_text(loan_id)
        self.d.set_fastinput_ime(False)
        d.send_action('search')
        self.d.set_fastinput_ime(True)
        self.assertTrue(d(resourceId="com.xiaoxiao.ludan:id/tv_loan_numb",text='%s' % loan_id).exists(timeout=5),msg=d.toast.get_message(10, 5))
        d(resourceId="com.xiaoxiao.ludan:id/tv_loan_numb", text='%s' % loan_id).click()
        d(resourceId="com.xiaoxiao.ludan:id/title",text='贷款详情').exists(timeout=3)
        d(resourceId="com.xiaoxiao.ludan:id/iv_add").click()
        d(resourceId="com.xiaoxiao.ludan:id/tv_bt_content",text='跟进').click(timeout=5)
        self.assertTrue(d(resourceId="com.xiaoxiao.ludan:id/title",text='已签约待面签').exists(timeout=5),msg=d.toast.get_message(10, 5))
        d(resourceId="com.xiaoxiao.ludan:id/tv_content_name",text='银行经理').sibling(resourceId="com.xiaoxiao.ludan:id/tv_content").click()
        d(text='猴赛雷').click(timeout=3)
        d(resourceId="com.xiaoxiao.ludan:id/tv_edit_title",text='备注').sibling('com.xiaoxiao.ludan:id/et_content').set_text(u"测试数据 - %s" % self.NowTime,timeout=2)
        d(resourceId="com.xiaoxiao.ludan:id/tv_add_manager").click()
        self.assertTrue(d(resourceId="com.xiaoxiao.ludan:id/title", text='贷款详情').exists(timeout=2),msg=d.toast.get_message(10, 5))

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


from flask import url_for
import pytest
from selenium.webdriver.support import expected_conditions
from selenium.webdriver.support.ui import WebDriverWait

def test_profile_no_auth(selenium, base_url):
    selenium.get(
        base_url + url_for('account', id='6e2cd664f6309c64803d5f4fdb0c19d9')
    )

    assert 'Login' in selenium.title

def test_signup_no_auth(selenium, base_url):
    selenium.get(base_url + url_for('signup'))

    assert 'Login' in selenium.title

@pytest.mark.parametrize('selenium', [['admin', 'admin']], indirect=True)
def test_profile(selenium, base_url):
    id = '6e2cd664f6309c64803d5f4fdb0c19d9'

    selenium.get(base_url + url_for('account', id=id))

    assert 'Marina Kuefer - Profil' in selenium.title

    delete = selenium.find_elements_by_css_selector('form[action="{}"]'.format(
        url_for('delete_account', id=id)))
    assert not delete
    selenium.find_element_by_css_selector('a[href="{}"]'.format(
        url_for('edit_account', id=id))).click()
    assert 'Benutzerkonto bearbeiten' in selenium.title

@pytest.mark.parametrize('selenium', [['admin', 'admin']], indirect=True)
def test_signup_edit_delete(selenium, base_url):
    selenium.get(base_url + url_for('signup'))

    assert 'Benutzerkonto erstellen' in selenium.title
    submit = selenium.find_element_by_id('submit')
    submit.click()

    assert 'Benutzerkonto erstellen' in selenium.title
    inputs = selenium.find_elements_by_css_selector(
        'input:required:not([type="email"])')
    for input in inputs:
        input.send_keys('test')
    submit.click()

    assert 'Benutzerkonto erstellen' in selenium.title
    email = selenium.find_element_by_name('email')
    assert email in selenium.find_elements_by_css_selector('input:invalid')
    email.send_keys('test@test.test')
    submit.click()

    wait = WebDriverWait(selenium, 10)
    wait.until(expected_conditions.title_contains('test test - Profil'))
    id = selenium.current_url.split('/')[-1]

    selenium.find_element_by_css_selector('a[href="{}"]'.format(
        url_for('edit_account', id=id))).click()

    for e in selenium.find_elements_by_css_selector(
        'input[name]:not([type="email"])'):
        assert e.get_attribute('value') == 'test'
    email = selenium.find_element_by_css_selector(
        'input[name][type="email"]')
    assert email.get_attribute('value') == 'test@test.test'

    selenium.get(base_url + url_for('account', id=id))
    selenium.find_element_by_css_selector('form[action="{}"] button'.format(
        url_for('delete_account', id=id))).click()
    selenium.get(base_url + url_for('account', id=id))

    assert '410 Gone' in selenium.title