import argparse
import os
from os import walk
from os.path import join
from shutil import copyfile
from zipfile import ZipFile

images_type = ["jpg", "jpeg", "png", "webp"]

HARD_LIMIT = 170
USE_CBZ = True
DEFAULT_NAME = "Vol "

def regroup_all_images(folder):
    out_folder = folder
    count_images = 0
    count_folder = 1
    volume = DEFAULT_NAME + "01"
    os.makedirs(out_folder, exist_ok=True)
    os.makedirs(join(out_folder, volume))
    current_dir = ""
    for (root, dirs, files) in walk(folder):
        for i in files:
            ext_file = i.split(".")[-1].lower()
            if ext_file in images_type:
                print("FOUND:", root, i)
                if count_images == HARD_LIMIT:
                    current_dir = root
                if count_images > HARD_LIMIT and current_dir != root:
                    current_dir = root
                    count_folder += 1
                    count_images = 0
                    volume = DEFAULT_NAME + str(count_folder).zfill(2)
                    os.makedirs(join(out_folder, volume), exist_ok=True)

                input_path = join(root, i)
                output_path = join(
                    out_folder, volume, str(count_images).zfill(3) + "." + ext_file
                )
                copyfile(input_path, output_path)
                count_images += 1

def regroup_all_images_cbz(folder, delete=False):
    out_folder = folder
    count_images = 0
    count_folder = 1
    volume = DEFAULT_NAME + "01.cbz"
    os.makedirs(out_folder, exist_ok=True)
    current_dir = ""
    cbz_file = None
    for (root, dirs, files) in walk(folder):
        dirs.sort()
        files.sort()
        if root == folder:
            continue
        for i in files:
            ext_file = i.split(".")[-1].lower()
            if ext_file in images_type:
                print("FOUND:", root, i)
                if count_images == HARD_LIMIT:
                    current_dir = root
                if count_images > HARD_LIMIT and current_dir != root:
                    current_dir = root
                    count_folder += 1
                    count_images = 0
                    cbz_file.close()
                    volume = DEFAULT_NAME + str(count_folder).zfill(2) + ".cbz"
                    cbz_file = ZipFile(join(out_folder, volume), "w")

                input_path = join(root, i)
                output_path = str(count_images).zfill(3) + "." + ext_file
                if not cbz_file:
                    # Lazy initialisation for empty folders
                    cbz_file = ZipFile(join(out_folder, volume), "w")
                cbz_file.write(input_path, output_path)
                if delete:
                    os.remove(input_path)
                count_images += 1
        if delete:
            print("DELETE", root)
            os.removedirs(root)
    if cbz_file:
        cbz_file.close()

if __name__ == "__main__":
    parser = argparse.ArgumentParser(description="Regroup all images inside a cbz according to a limit.")
    parser.add_argument("path", help="folder to rename", nargs="+")
    parser.add_argument("--delete", help="move and not copy", action="store_true")
    parser.add_argument("--limit", help="number of images per tome", default=HARD_LIMIT)
    args = parser.parse_args()
    HARD_LIMIT = args.limit
    for path in args.path:
        regroup_all_images_cbz(path, args.delete)


from __future__ import annotations

from abc import ABC, abstractmethod
from typing import TYPE_CHECKING, Dict, List, Optional, Tuple, Union

import gymnasium
import pymunk
import pymunk.matplotlib_util
from gymnasium import spaces
from gymnasium.core import ActType
from matplotlib import pyplot as plt

from spg.core.entity.communication import CommunicationMixin
from spg.core.playground.utils import zero_action_space
from spg.core.position import Coordinate, CoordinateSampler

from ..entity import Agent, Element, Entity
from ..entity.sensor import SensorMixin
from .manager import SpaceManager, ViewManager
from .manager.collision import CollisionManager
from .manager.communication import CommunicationManager
from .manager.sensor import SensorManager

if TYPE_CHECKING:
    from spg.components.elements.barrier import BarrierMixin

class Playground(
    gymnasium.Env,
    SpaceManager,
    ViewManager,
    CollisionManager,
    CommunicationManager,
    SensorManager,
    ABC,
):
    def __init__(self, size: Tuple[int, int], **kwargs) -> None:

        self.size = size
        self.width, self.height = self.size

        self.elements: List[Element] = []
        self.agents: List[Agent] = []

        ViewManager.__init__(self, **kwargs)
        SpaceManager.__init__(self, **kwargs)
        CollisionManager.__init__(self, **kwargs)
        CommunicationManager.__init__(self, **kwargs)
        SensorManager.__init__(self, **kwargs)

        self.reset()

    @abstractmethod
    def place_elements(self) -> List[Element]:
        pass

    @abstractmethod
    def place_agents(self) -> List[Agent]:
        pass

    ###############
    # Entities
    ###############

    @property
    def action_space(self):
        return spaces.Dict(
            {agent.name: agent.agent_action_space for agent in self.agents}
        )

    @property
    def null_action(self):
        return zero_action_space(self)

    @property
    def observation_space(self):
        return spaces.Dict(
            {agent.name: agent.agent_observation_space for agent in self.agents}
        )

    ###############
    # STEP
    ###############

    def step(self, action: ActType):
        """Update the Playground

        Updates the Playground.
        Time moves by one unit of time.

        Args:
            action: The action to be performed by the agents. Dict of spaces.Space

        """

        self._pre_step()

        for agent_name, agent_action in action.items():
            agent = self.name_to_agents[agent_name]
            agent.agent_apply_action(agent_action)

        self.pymunk_step()

        self._post_step()

        observation = self._compute_observation()
        reward = self._compute_reward()

        return observation, reward, self._terminated, False, {}

    def _pre_step(self):

        for view in self.views:
            view.updated = False

        for element in self.elements:
            element.pre_step()

        for agent in self.agents:
            agent.pre_step()

        self.clear_messages()

    def _post_step(self):

        for element in self.elements:
            element.post_step()

        for agent in self.agents:
            agent.post_step()

    def _compute_observation(self):

        self.update_sensors()

        obs = {}
        for agent in self.agents:
            obs[agent.name] = agent.agent_observation

        return obs

    def _compute_reward(self):
        return {agent: agent.reward for agent in self.agents}

    def reset(self):
        """
        Reset the Playground to its initial state.
        """

        # Initialization of the pymunk space, modelling all the physics
        self.initialize_space()
        self.add_interactions()

        for view in self.views:
            view.reset()

        # Mappings
        self.shapes_to_entities: Dict[pymunk.Shape, Entity] = {}
        self.name_to_agents: Dict[str, Agent] = {}
        self.uids_to_entities: Dict[int, Entity] = {}

        self.elements: List[Element] = []
        self.agents: List[Agent] = []
        self.barriers: List[BarrierMixin] = []

        # Lists containing elements in the playground
        self.place_elements()
        self.place_agents()

        self._terminated = False

        obs = self._compute_observation()

        return obs, {}

    # ADD REMOVE ENTITIES
    def get_uid(self):

        while True:
            uid = self.np_random.integers(0, 2**24)
            if uid not in self.uids_to_entities:
                return uid

    def add(
        self,
        entity: Entity,
        coordinate: Optional[Union[Coordinate, CoordinateSampler]] = None,
        allow_overlapping=True,
    ):

        entity.playground = self
        entity.uid = self.get_uid()

        if not entity.name:
            entity.name = f"{entity.__class__.__name__}_{entity.uid}"

        if entity.name in self.name_to_agents:
            raise ValueError(f"Agent {entity.name} already exists in the playground")

        if isinstance(entity, Element):
            self.elements.append(entity)

        elif isinstance(entity, Agent):
            self.agents.append(entity)

            if entity.name in self.name_to_agents:
                raise ValueError(
                    f"Agent {entity.name} already exists in the playground"
                )

            self.name_to_agents[entity.name] = entity

        self.shapes_to_entities.update({shape: entity for shape in entity.pm_shapes})
        self.uids_to_entities[entity.uid] = entity

        # Add to space:
        if entity.pm_body is not None:
            self.space.add(entity.pm_body)
        self.space.add(*entity.pm_shapes)

        for attached_entity in entity.attached:
            self.add(attached_entity)

        if isinstance(entity, SensorMixin):
            self.add_sensor(entity)

        # Once all attachements have been added, we can move the entity and fix the attachements
        if isinstance(entity, (Agent, Element)):
            assert coordinate is not None
            entity.move_to(coordinate, allow_overlapping)
            entity.fix_attached()

            # Add to the views
            for view in self.views:
                view.add(entity)

        if isinstance(entity, CommunicationMixin):
            entity.subscribe_to_topics()

    def remove(self, entity):

        if isinstance(entity, Agent):
            self.agents.remove(entity)
            self.name_to_agents.pop(entity.name)

        if isinstance(entity, Element):
            self.elements.remove(entity)

        self.uids_to_entities.pop(entity.uid)

        if entity.pm_body is not None:
            self.space.remove(entity.pm_body)

        self.space.remove(*entity.pm_shapes)

        for attached_entity in entity.attached:
            self.remove(attached_entity)

            if hasattr(attached_entity, "joint") and attached_entity.joint is not None:
                self.space.remove(attached_entity.joint)

            if hasattr(attached_entity, "motor") and attached_entity.motor is not None:
                self.space.remove(attached_entity.motor)

            if hasattr(attached_entity, "limit") and attached_entity.limit is not None:
                self.space.remove(attached_entity.limit)

        if isinstance(entity, (Agent, Element)):
            for view in self.views:
                view.remove(entity)

        if isinstance(entity, CommunicationMixin):
            entity.unsubscribe_from_topics()

    def within_playground(
        self,
        entity: Entity,
    ):

        if isinstance(entity, (Agent, Element)):
            for attached_entity in entity.attached:
                if not self.within_playground(attached_entity):
                    return False

        return self.coordinates_is_valid(entity.coordinates)

    def coordinates_is_valid(self, coordinate: Coordinate) -> bool:

        position = coordinate[0]

        if not -self.width / 2 <= position[1] <= self.width / 2:
            return False

        if not -self.height / 2 <= position[1] <= self.height / 2:
            return False

        return True

    def get_closest_agent(self, entity: Entity) -> Agent:
        return min(self.agents, key=lambda a: entity.position.get_dist_sqrd(a.position))

    def draw(self, plt_width=10, center=None, size=None):

        if not center:
            center = (0, 0)

        if not size:
            size = self.size

        fig_size = (plt_width, plt_width / size[0] * size[1])

        fig = plt.figure(figsize=fig_size)

        ax = plt.axes(
            xlim=(center[0] - size[0] / 2, center[0] + size[0] / 2),
            ylim=(center[1] - size[1] / 2, center[1] + size[1] / 2),
        )
        ax.set_aspect("equal")

        options = pymunk.matplotlib_util.DrawOptions(ax)
        options.collision_point_color = (10, 20, 30, 40)
        self.space.debug_draw(options)
        plt.show()
        del fig

class EmptyPlayground(Playground):
    def place_agents(self):
        pass

    def place_elements(self):
        pass


import asyncio

import discord
from adventureIO.constants import Emoji

class PlayerNotActivatedError(Exception):
    ...

class Player:
    def __init__(self, member):
        self.member = member
        self.id = member.id
        self.name = member.name
        self.display_name = member.display_name
        self.activated = False

    @classmethod
    def from_database(cls, member, row):
        (
            _, _, hp, max_hp,
            atk, res, crit, luck,
            skillpoints, level, xp,
            money, activ, adventure_id
        ) = row

        player = cls(member)
        player.health = hp
        player.max_health = max_hp
        player.attack = atk
        player.resistance = res
        player.crit = crit
        player.luck = luck
        player.skillpoints = skillpoints
        player.level = level
        player.xp = xp
        player.money = money
        player.activated = activ
        player.adventure_id = adventure_id
        return player

    def __getattribute__(self, name):
        activated_attributes = (
            "attack", "atk",
            "resistance", "res",
            "health", "hp",
            "max_health", "max_hp",
            "crit",
        )

        activated = object.__getattribute__(self, "activated")

        if name in activated_attributes:
            if activated:
                return object.__getattribute__(self, name)

            error = f"Can't fetch {name} value from an unactivated player"
            raise PlayerNotActivatedError(error)

        return object.__getattribute__(self, name)

    @property
    def row(self):
        return (
            self.id,
            self.health,
            self.max_health,
            self.attack,
            self.resistance,
            self.crit,
            self.luck,
            self.skillpoints,
            self.level,
            self.xp,
            self.money,
            self.activated,
            self.adventure_id
        )

    @property
    def dead(self):
        return self.health <= 0

    @property
    def hp(self):
        return self.health

    @property
    def max_hp(self):
        return self.max_health

    @property
    def atk(self):
        return self.attack

    @property
    def res(self):
        return self.resistance

    async def activate(self, ctx):
        if self.activated:
            return await ctx.send("You're already activated!")

        self.activated = True

        # TODO: Start session to add skillpoints to player
        embed = self.freeskillpoints_embed()
        msg = await ctx.send(embed=embed)

        reactions = (Emoji._1, Emoji._2, Emoji._3, Emoji._4, Emoji._5)

        ctx.bot.loop.create_task(
            self.add_skillpoints_loop(ctx.bot, msg, reactions)
        )
        for reaction in reactions:
            await msg.add_reaction(reaction)

        return
        await ctx.send("Activated!")

    async def add_skillpoints_loop(self, bot, msg, emojis):
        def check(r, u):
            if u.bot:
                return False
            if r.message.id != msg.id:
                return False
            if r.emoji not in emojis:
                return False
            return True

        while self.skillpoints > 0:
            try:
                reaction, member = await bot.wait_for(
                    "reaction_add",
                    check=check,
                    timeout=60
                )
            except asyncio.TimeoutError:
                return False

            if reaction.emoji == Emoji._1:
                self.max_health += 5
                self.health = self.max_health
            elif reaction.emoji == Emoji._2:
                self.attack += 1
            elif reaction.emoji == Emoji._3:
                self.resistance += 1
            elif reaction.emoji == Emoji._4:
                self.crit += 1
            elif reaction.emoji == Emoji._5:
                self.luck += 1
            else:
                print("Unknown emoji? ", reaction.emoji)
                continue

            if self.skillpoints > 0:  # Probably redundant
                self.skillpoints -= 1

            embed = self.freeskillpoints_embed()
            await msg.edit(embed=embed)
            await msg.remove_reaction(reaction, member)

        try:
            await msg.clear_reactions()
            await msg.add_reaction(Emoji.checkmark)
        except discord.Forbidden:
            print("Missing permissions to clear reactions")

        if bot.db:
            await bot.db.update_player(self)

    def revive(self):
        self.health = self.max_health

    def freeskillpoints_embed(self):
        embed = discord.Embed(
            title=f"Add skillpoints ({self.skillpoints} left)"
            )

        longest = max(
            [
                len(str(num))
                for num
                in (self.max_hp, self.attack, self.res, self.crit, self.luck)
            ]
        )

        embed.description = (
            "*Use the number reactions to add points*\n\n"
            "```"
            f"1. {'Health:':<12}  [{self.max_hp:>{longest}}] ⁺⁵ \n"
            f"2. {'Attack:':<12}  [{self.attack:>{longest}}] ⁺¹ \n"
            f"3. {'Resistance:':<12}  [{self.resistance:>{longest}}] ⁺¹ \n"
            f"4. {'Crit:':<12}  [{self.crit:>{longest}}] ⁺¹\n"
            f"5. {'Luck:':<12}  [{self.luck:>{longest}}] ⁺¹\n"
            "```"
        )
        url = "https://cdn.discordapp.com/emojis/470326273298792469.png?v=1"
        embed.set_footer(
            text="You can not retrieve spent skillpoints!",
            icon_url=url
        )
        return embed


import pytest

import ipsuite as ips

@pytest.mark.parametrize("eager", [True, False])
def test_ips_bin_property(data_repo, eager):
    """Test the BarycenterMapping class."""
    data = ips.AddData.from_rev(name="BMIM_BF4_363_15K")

    with ips.Project() as project:
        e_hist = ips.analysis.EnergyHistogram(data=data.atoms)
        f_hist = ips.analysis.ForcesHistogram(data=data.atoms, bins=100)

    project.run(eager=eager)
    if not eager:
        e_hist.load()
        f_hist.load()

    assert e_hist.labels_df["bin_edges"].shape == (1,)
    assert f_hist.labels_df["bin_edges"].shape == (100,)


# -*- coding: utf-8 -*-
"""
Created on Thu Aug 24 16:15:14 2023

@author: danie
"""

import torch
import matplotlib.pyplot as plt
import scipy

#constants
a0 = 5.29177210903e-11

#create some graphs for dissertation

num_points = 10000
boundary = 0.3e-9

x = torch.linspace(-boundary,boundary,num_points)
x_pm = x*10**12

x = x.reshape(-1,1)
R = 67e-12
R_pm = R*10**12

def sOrbital(r):
    rho = r/a0
    psi = torch.exp(-rho)/(torch.sqrt(torch.tensor(torch.pi*a0**3)))
    psi = psi.reshape(-1,1)
    return psi

# Cartesian Translation & Scaling:
x1 = torch.abs(x + R)
x2 = torch.abs(x - R)

psi1 = sOrbital(x1)
psi2 = sOrbital(x2)

#!!!!!!!!!!!!!Need to be normalised
#xlim is -300pm,300pm

psi_plus = torch.add(psi1,psi2)
psi_minus = torch.sub(psi1,psi2)

print(max(psi_plus))

psi_abs_plus = torch.pow(torch.abs(psi_plus),2)
psi_abs_minus = torch.pow(torch.abs(psi_minus),2)

N_plus = scipy.integrate.simpson(psi_abs_plus.reshape((-1)),x.reshape((-1)))
N_minus = scipy.integrate.simpson(psi_abs_minus.reshape((-1)),x.reshape((-1)))

psi_plus /= torch.tensor([N_plus])
psi_minus /= torch.tensor([N_minus])

psi_abs_plus = torch.pow(torch.abs(psi_plus),2)
psi_abs_minus = torch.pow(torch.abs(psi_minus),2)

figure, axis = plt.subplots(2,2,layout='compressed',dpi=200)

axis[0,0].plot(x_pm.cpu(),psi_plus.cpu())
axis[0,0].axvline(x=R_pm,color='r',linestyle='--')
axis[0,0].axvline(x=-R_pm,color='r',linestyle='--')
axis[0,0].annotate('A',(-R_pm,0),textcoords="offset points",xytext=(0,-15),ha='center')
axis[0,0].annotate('B',(R_pm,0),textcoords="offset points",xytext=(0,-15),ha='center')
#axis[0,0].xlabel('$x$')
axis[0,0].set_xticks([-300,-150,0,150,300])
axis[0,0].annotate('$x$ (pm)',(0,0),textcoords="offset points",xytext=(0,-30),ha='center')
axis[0,0].set_title('$\Psi_{+}$')

axis[0,1].plot(x_pm.cpu(),psi_minus.cpu())
axis[0,1].axvline(x=R_pm,color='r',linestyle='--')
axis[0,1].axvline(x=-R_pm,color='r',linestyle='--')
axis[0,1].axhline(0,color='grey',linestyle='--')
axis[0,1].annotate('A',(-R_pm,0),textcoords="offset points",xytext=(0,-58),ha='center')
axis[0,1].annotate('B',(R_pm,0),textcoords="offset points",xytext=(0,-58),ha='center')
#axis[0,1].xlabel('$x$')
axis[0,1].set_xticks([-300,-150,0,150,300])
axis[0,1].annotate('$x$ (pm)',(0,0),textcoords="offset points",xytext=(0,-73),ha='center')
axis[0,1].set_title('$\Psi_{-}$')

axis[1,0].plot(x_pm.cpu(),psi_abs_plus.cpu())
axis[1,0].axvline(x=R_pm,color='r',linestyle='--')
axis[1,0].axvline(x=-R_pm,color='r',linestyle='--')
axis[1,0].annotate('A',(-R_pm,0),textcoords="offset points",xytext=(0,-15),ha='center')
axis[1,0].annotate('B',(R_pm,0),textcoords="offset points",xytext=(0,-15),ha='center')
axis[1,0].set_xticks([-300,-150,0,150,300])
#axis[1,0].xlabel('$x$')
axis[1,0].annotate('$x$ (pm)',(0,0),textcoords="offset points",xytext=(0,-30),ha='center')
axis[1,0].set_title('$|\Psi_{+}|^{2}$')

axis[1,1].plot(x_pm.cpu(),psi_abs_minus.cpu())
axis[1,1].axvline(x=R_pm,color='r',linestyle='--')
axis[1,1].axvline(x=-R_pm,color='r',linestyle='--')
axis[1,1].annotate('A',(-R_pm,0),textcoords="offset points",xytext=(0,-15),ha='center')
axis[1,1].annotate('B',(R_pm,0),textcoords="offset points",xytext=(0,-15),ha='center')
#axis[1,1].xlabel('$x$')
axis[1,1].set_xticks([-300,-150,0,150,300])
axis[1,1].annotate('$x$ (pm)',(0,0),textcoords="offset points",xytext=(0,-30),ha='center')
axis[1,1].set_title('$|\Psi_{-}|^{2}$')

#plt.savefig('H2+_wavefunctions.png')


from common import ExtensionBase

# noinspection PyUnreachableCode
if False:
	# noinspection PyUnresolvedReferences
	from _stubs import *

try:
	import tdu
except ImportError:
	tdu = tdu

def onPulse(par):
	name = par.name
	action = tdu.base(name)
	num = tdu.digits(name)
	m = parent()

	if action.startswith('Cue'):
		timepar = getCuePar(num)
		if action == 'Cuetrigger':
			jumpTo(timepar.eval())
		elif action == 'Cueset':
			timepar.val = getCurrentFraction()
	elif action == 'Setrange':
		newstart = getCurrentFraction() if num == 1 else m.par.Timerange1.eval()
		newend = getCurrentFraction() if num == 2 else m.par.Timerange2.eval()
		setTimeRange(newstart, newend)

def setTimeRange(newstart, newend, rescalecues=True):
	m = parent()

	if rescalecues:
		oldstart = m.par.Timerange1.eval()
		oldend = m.par.Timerange2.eval()
		for cuepar in m.pars('Cuepoint*'):
			if cuepar.mode != ParMode.CONSTANT:
				continue
			oldpos = cuepar.eval()
			newpos = tdu.remap(oldpos, oldstart, oldend, newstart, newend)
			cuepar.val = tdu.clamp(newpos, 0, 1)
	m.par.Timerange1 = newstart
	m.par.Timerange2 = newend

def getCuePar(i):
	return getattr(parent().par, 'Cuepoint' + str(i))

def getRangePar(i):
	return getattr(parent().par, 'Timerange' + str(i))

def jumpTo(percent):
	moviein = op('moviefilein')
	moviein.par.cuepoint = percent
	moviein.par.cue.pulse()

def getCurrentFraction():
	return op('info')['index_fraction'][0]

class VideoPlayerCore(ExtensionBase):
	def _SetTimeRange(self, start: float, end: float, rescaleCues=True):
		if rescaleCues:
			oldStart = self.par.Timerange1.eval()
			oldEnd = self.par.Timerange2.eval()
			for cuePar in self.ownerComp.pars('Cuepoint*'):
				if cuePar.mode != ParMode.CONSTANT:
					continue
				oldPos = cuePar.eval()
				newPos = tdu.remap(oldPos, oldStart, oldEnd, start, end)
				cuePar.val = tdu.clamp(newPos, 0, 1)
		self.par.Timerange1.val = start
		self.par.Timerange2.val = end

	def JumpTo(self, percent: float):
		movieIn = self.op('moviefilein')
		movieIn.par.cuepoint = percent
		movieIn.par.cue.pulse()

	def _CuePar(self, i: int):
		return getattr(self.par, f'Cuepoint{i}')

	def _CurrentFraction(self):
		return self.op('info')['index_fraction'][0]

	def OnPulse(self, par: 'Par'):
		action = tdu.base(par.name)
		num = tdu.digits(par.name)
		if action == 'Resetstate':
			self.JumpTo(0)
		elif action.startswith('Cue'):
			timePar = self._CuePar(num)
			if action == 'Cuetrigger':
				self.JumpTo(timePar.eval())
			elif action == 'Cueset':
				timePar.val = self._CurrentFraction()
		elif action == 'Setrange':
			start = self._CurrentFraction() if num == 1 else self.par.Timerange1.eval()
			end = self._CurrentFraction() if num == 2 else self.par.Timerange2.eval()
			self._SetTimeRange(start, end, rescaleCues=True)


from typing import List, Union, Any, Dict, List, Tuple
import random
import numpy as np
from gym import utils
from gym.envs.mujoco import HalfCheetahEnv as HalfCheetahEnv_
from gym.envs.mujoco import mujoco_env

class HalfCheetahEnv(HalfCheetahEnv_):
    def __init__(self):
        mujoco_env.MujocoEnv.__init__(self, "half_cheetah.xml", 5)
        utils.EzPickle.__init__(self)

    def _get_obs(self) -> np.ndarray:
        return (
            np.concatenate(
                [
                    self.data.qpos.flat[1:],
                    self.data.qvel.flat,
                    self.get_body_com("torso").flat,
                ],
            )
            .astype(np.float32)
            .flatten()
        )

    def viewer_setup(self) -> None:
        camera_id = self.model.camera_name2id("track")
        self.viewer.cam.type = 2
        self.viewer.cam.fixedcamid = camera_id
        self.viewer.cam.distance = self.model.stat.extent * 0.35
        self.viewer._hide_overlay = True

    def render(self, mode: str = "human") -> Union[List[float], None]:
        if mode == "rgb_array":
            self._get_viewer(mode).render()
            width, height = 500, 500
            data = self._get_viewer().read_pixels(width, height, depth=False)
            return data
        elif mode == "human":
            self._get_viewer(mode).render()

class HalfCheetahDirEnv(HalfCheetahEnv):
    def __init__(self, num_tasks=2) -> None:
        if num_tasks==1:
            directions = [1]
        elif num_tasks==2:
            directions = [-1, 1]
        else:
            raise "num tasks > 2"

        self.tasks = [{"direction": direction} for direction in directions]
        #assert num_tasks == len(self.tasks)
        self._task =  self.tasks[0]
        self._goal_dir = self._task["direction"]
        super().__init__()

    def step(self, action: np.ndarray) -> Tuple[np.ndarray, np.float64, bool, Dict[str, Any]]:
        xposbefore = self.data.qpos[0]
        self.do_simulation(action, self.frame_skip)
        xposafter = self.data.qpos[0]

        progress = (xposafter - xposbefore) / self.dt
        run_cost = self._goal_dir * progress
        control_cost = 0.5 * 1e-1 * np.sum(np.square(action))

        observation = self._get_obs()
        reward = run_cost - control_cost
        done = False
        info = dict(run_cost=run_cost, control_cost=-control_cost, task=self._task)
        return observation, reward, done, info

    def get_all_task_idx(self) -> List[int]:
        return list(range(len(self.tasks)))

    def reset_task(self, idx: int) -> None:
        self._task = self.tasks[idx]
        self.set_task(self._task["direction"])
        self.reset()

    def set_task(self, task):
        self._goal_dir = task

    def get_task(self):
        return np.array(self._goal_dir)

class HalfCheetahVelEnv(HalfCheetahEnv):
    def __init__(self, num_tasks: int) -> None:
        self.tasks = self.sample_tasks(num_tasks)
        self._task = self.tasks[0]
        self._goal_vel = self._task["velocity"]
        super().__init__()

    def step(self, action: np.ndarray) -> Tuple[np.ndarray, np.float64, bool, Dict[str, Any]]:
        xposbefore = self.data.qpos[0]
        self.do_simulation(action, self.frame_skip)
        xposafter = self.data.qpos[0]

        progress = (xposafter - xposbefore) / self.dt
        run_cost = progress - self._goal_vel
        scaled_run_cost = -1.0 * abs(run_cost)
        control_cost = 0.5 * 1e-1 * np.sum(np.square(action))

        observation = self._get_obs()
        reward = scaled_run_cost - control_cost
        done = False
        info = dict(run_cost=run_cost, control_cost=-control_cost, task=self._task)
        return observation, reward, done, info

    def sample_tasks(self, num_tasks: int):
        np.random.seed(0)
        velocities = np.random.uniform(0.0, 2.0, size=(num_tasks,))
        tasks = [{"velocity": velocity} for velocity in velocities]
        return tasks

    def get_all_task_idx(self) -> List[int]:
        return list(range(len(self.tasks)))

    def reset_task(self, idx: int) -> None:
        self._task = self.tasks[idx]
        self._goal_vel = self._task["velocity"]
        self.reset()


"""
Create a dataframe with your name , age , mail id and phone number and add your friends’s information to the same.
"""

import pandas as pd

data = {'Name': ['Test'], 'Age': [20], 'Mail Id': ['testuser@email.com'], 'Phone No': ['9034xxxxxxx']}
df = pd.DataFrame(data)

df.loc[1] = ['User1', 21, 'user1@email.com', '942xxxxxx']
df.loc[2] = ['User2', 20, 'user2@email.com', '827xxxxxxx']
df.loc[3] = ['User3', 20, 'user3@email.com', '717xxxxxxx']
print("Dataframes defined are as follows: ", df)
print("\n")


"""
Core Definitions for
Herbert and Herbert-
Submodules
"""

import logging

from telegram.ext import Updater, InlineQueryHandler, CallbackContext
from telegram import InlineQueryResultArticle, InputTextMessageContent, Update

from common.herbert_utils import is_cmd_decorated
import path

__all__ = ['Herbert']

logging.basicConfig(
    style='{',
    datefmt='%d.%m. %H:%M:%S',
    format='{asctime} [{levelname:5}] {message}',
    level=logging.INFO
)

logging.getLogger('requests').setLevel(logging.WARNING)
logging.getLogger('urllib3').setLevel(logging.WARNING)

berts = []
inline_methods = {}
inline_aliases = {}

class Herbert:
    """
    Wrap ptb's Updater

    .register_bot() will add all handlers
    for all methods of a BaseBert-subclass

    The bot can then run with .idle()
    """

    def __init__(self, token_file='token.txt') -> None:
        path.change_path()

        with open(token_file, 'r') as fobj:
            self.token = fobj.read().strip()

        self.updater = Updater(self.token)

    def register_bert(self, cls: type) -> None:
        """Adds a Bert to Herbert"""
        bot = cls()
        berts.append(bot)

        for method in bot.enumerate_members():
            if is_cmd_decorated(method):
                inf = method.cmdinfo
                for handler in inf.handlers(method):
                    self.updater.dispatcher.add_handler(handler)

                if inf.properties.allow_inline:
                    inline_methods[method.__name__] = inf.invoke(method)
                    for command in inf.properties.aliases:
                        inline_aliases[command] = method.__name__

            elif hasattr(method, 'callback_query_handler'):
                self.updater.dispatcher.add_handler(
                    method.callback_query_handler(method)
                )

        cmds = ", ".join((m.__name__ for m in bot.enumerate_cmds()))
        logging.getLogger('herbert.SETUP').debug("Registered Bert %s of type %s (%s)", bot, cls.__name__, cmds)

    def register_inline_handler(self) -> None:
        self.updater.dispatcher.add_handler(InlineQueryHandler(handle_inline_query))

    def start(self) -> None:
        self.updater.start_polling()

    def idle(self) -> None:
        """ start the updater event loop """
        self.start()
        self.updater.idle()

def handle_inline_query(update: Update, context: CallbackContext, line=None):
    """
    If python-telegram-bot receives an inline query, this function
    will select the correct command handler based on the query string,
    then run the command with an appropriate context object to allow
    answering the query by using the normal send methods
    """
    query = None

    if line is not None:
        query = line
    elif update.inline_query is not None:
        query = update.inline_query.query
    else:
        raise ValueError("Handler called without valid query")

    command, *args = query.split(" ")

    for alias, name in inline_aliases.items():
        if command == alias:
            inline_methods[name](
                update,
                context,
                inline=True,
                inline_query=update.inline_query,
                inline_args=args
            )

            return True

    if update.inline_query:
        update.inline_query.answer([
            InlineQueryResultArticle(
                id="error0",
                title='Failed to find Command "' + command + '".',
                input_message_content=InputTextMessageContent("Hello, guys!")
            )
        ])

    return False


# Open images and labels
# import cv2
import numpy as np
import json
import math
import os

# Do this in a function
def get_labels_and_image(camera_name, img_name):
    # Open image file
    # join path
    # img = cv2.imread(os.path.join('dataset', "images",  camera_name, '{}.JPG'.format(img_name)))
    # Open json label file
    labels = open(os.path.join('dataset', 'CompleteAnnotations_2016-07-11', '{}.json'.format(camera_name)), 'r')
    # Parse json file
    labels = json.load(labels)
    images = []
    for i in labels["dots"]:
        if i["imName"] == img_name:
            images.append(i)
    return images

# Create a function to save the labels
def save_labels(squares, img_name, camera_name=None):
    # Create a file
    if camera_name != None:
        # Check if the directory exists if not, create it recursively
        if not os.path.exists(os.path.join('dataset', 'labels', camera_name)):
            os.makedirs(os.path.join('dataset', 'labels', camera_name))

        f = open(os.path.join('dataset', 'labels', camera_name, '{}.txt'.format(img_name)), 'w')
    else:
        if not os.path.exists(os.path.join('dataset', 'labels')):
            os.makedirs(os.path.join('dataset', 'labels'))

        f = open(os.path.join('dataset', 'labels', '{}.txt'.format(img_name)), 'w')

    # Write the labels
    for i in range(len(squares)):
        # Square center
        x, y = (squares[i][0]), (squares[i][1])
        # Square width and height
        w, h = squares[i][2], squares[i][3]
        f.write('0 {} {} {} {}\n'.format(x, y, w, h))

# Create a function to process the labels
def process_labels(camera_name, img_name):
    # Get the image and the labels
    images = get_labels_and_image(camera_name, img_name)

    if images[0]["xy"] == [] or images[0]["xy"] == None or images[0]["xy"] == "_NaN_":
        return
    import pickle
    # Open pickle file
    with open('camera_info.pkl', 'rb') as f:
        camera_info = pickle.load(f)

    height = camera_info[camera_name]["height"]
    width = camera_info[camera_name]["width"]
    alpha = camera_info[camera_name]["distortion"]

    # Squares
    squares = []
    visited = False
    for i in images[0]["xy"]:
        # If i is not a list, or enpty, skip it
        if type(i) != list or i == [] or i == None or i == "_NaN_" or i == [''] or i == '':
            continue

        if not visited:
            for j in i:
                if type(j) != list or j == [] or j == None or j == "_NaN_" or j == [''] or j == '':
                    continue

                # plt.scatter(j[0], j[1], color='r', s=10)
                # Each square for a given point is proportional to what is the y value of that point. Initating from 0 to the height of the image
                # There is a linear relationship between the y value of the point and the area of the square
                # The area of the square is proportional to the y value of the point
                # To calculate the area of the square, we need to know the height of the image
                # Get the height of the image
                # Get the y value of the point
                y = j[1]
                # Calculate the area of the square
                area = ((y/height) + 0.1) * alpha - 0.1 * alpha

                # Save the square
                if area > 0:
                    # Turn the area into a percentage of the image
                    x = j[0] / width * 100
                    y = j[1] / height * 100
                    w = math.sqrt(area) / width * 100
                    h = math.sqrt(area) / height * 100
                    squares.append((x, y, w, h))
                    visited = True

    # Save the labels
    save_labels(squares, img_name)
    return squares

def main():
    # Use Tqdm to show the progress
    from tqdm import tqdm

    camera_name = {
        "BAILa": 150000,
        "DAMOa": 200000,
        "GEORa": 250000,
        "HALFb": 300000,
        "MAIVb": 50000,
        "MAIVc": 50000
    }

    for cam in camera_name:
        print("Processing camera: {}".format(cam))
        # Get all the images
        images = os.listdir("dataset/images/{}".format(cam))

        # Process the labels for each image
        for img in tqdm(images):
            # If the image is not a .JPG file, skip it
            if img[-3:] != 'JPG':
                continue
            # Process the labels
            # process_labels(cam, img[:-4], alpha=camera_name[cam])

            # move image to new folder ../../images
            os.rename(os.path.join("dataset", "images", cam, img), os.path.join("dataset", "images", img))

if __name__ == '__main__':
    main()


# Learn Python the Hard Way
# https://learnpythonthehardway.org/python3/ex6.html

# Sets variable value to 10
types_of_people = 10
# Sets x variable value to (formatted) string w/ variable value inside
x = f"There are {types_of_people} types of people."  # str in str

# Sets variable to string
binary = "binary"
# Sets variable to string
do_not = "don't"
# Sets y variable value to (formatted) strings w/ variable values inside
y = f"Those who know {binary} and those who {do_not}."  # str in str

# Print string x
print(x)
# Print string y
print(y)
# Print (formatted) string w/ x variable value inside
print(f"I said: {x}")  # str in str
# Print (formatted) string w/ y variable value inside
print(f"I also said: '{y}'")  # str in str

# Sets variable to boolean False
hilarious = False
# Sets variable to a not formatted string, thus {} is not evaluated here
joke_evaluation = "Isn't that joke so funny?! {}"  # str in str?
# Prints evaluated string with 'hilarious' variable content evaluated in {}s
print(joke_evaluation.format(hilarious))

# Sets variable w to string
w = "This is the left side of..."
# Sets variable e to string
e = "a string with a right side."

# Prints both variables concatenated (notice no space is added like w/ commas)
print(w + e)

# Study Drills

# 1. Go through this program and write a comment above each line explaining it.
# 2. Find all the places where a string is put inside a string. There are four places.
# 3. Are you sure there are only four places? How do you know? Maybe I like lying.
# 4. Explain why adding the two strings w and e with + makes a longer string.
# A: Adding strings concatenates them w/o spaces in between


from image_search.db import DB
import colorsys
import math

def list_add(l1, l2):
    return [a1 + a2 for (a1, a2) in zip(l1, l2)]

def cosine_sim(l1, l2):
    dot = sum([a1 * a2 for (a1, a2) in zip(l1, l2)])
    norm1 = math.sqrt(sum([a * a for a in l1]))
    norm2 = math.sqrt(sum([a * a for a in l2]))
    return dot / (norm1 * norm2)

def search_query(query):
    query = query.lower()
    tokens = query.split(' ')
    candidates = {}

    for token in tokens:
        token = token.strip()
        if not token in DB.word_vec: continue
        embed = DB.word_vec[token]
        all_sim = [(k, max([round(cosine_sim(embed, e), 4) for e in v['embed']])) for k, v in DB.label_info.items()]
        all_sim.sort(key=lambda x: x[1], reverse=True)
        print(all_sim[:3])
        for i, (label, sim) in enumerate(all_sim[:3]):
            label_info = DB.label_info[label]
            for img, score in label_info['invert_idx']:
                val = math.pow(10000, sim)
                if val < 0: val = 0
                if img in candidates:
                    candidates[img] += score * val
                else:
                    if score > 0.05:
                        candidates[img] = score * val
    candidates = list(candidates.items())
    candidates.sort(key=lambda x: x[1], reverse=True)

    for can in candidates[:10]:
        can_id = can[0]
        pos_labels = DB.img_info[can_id]['pos_labels']
        print(can[0], can[1], pos_labels)
    return [c[0] for c in candidates]

def search_similar(image_id, num):
    if image_id in DB.img_info:
        pos_labels = DB.img_info[image_id]['pos_labels']
        candidates = {}
        for label in pos_labels:
            invert_idx = DB.label_info[label]['invert_idx']
            for img, score in invert_idx:
                if img == image_id: continue
                if score < 0.05: break
                if img in candidates:
                    candidates[img] += score
                else:
                    candidates[img] = score
        candidates = list(candidates.items())
        candidates.sort(key=lambda x: x[1], reverse=True)
        return [c[0] for c in candidates[:num]]
    else:
        return []

def hex2rgb(hexcode):
    r = int(hexcode[1:3], 16)
    g = int(hexcode[3:5], 16)
    b = int(hexcode[5:7], 16)
    return r, g, b

def rgb_dist(c1, c2):
    c1 = colorsys.rgb_to_hsv(c1[0]/255, c1[1]/255, c1[2]/255)
    c2 = colorsys.rgb_to_hsv(c2[0]/255, c2[1]/255, c2[2]/255)
    dh = min(abs(c1[0] - c2[0]), 1 - abs(c1[0] - c2[0])) / 0.5
    ds = abs(c1[1] - c2[1])
    dv = abs(c1[2] - c2[2])
    distance = math.sqrt(dh * dh + ds * ds + dv * dv)
    return distance

def filter_color_size(images, color, size):
    if color == '' and size == '':
        return images
    if color != '':
        color_rgb = hex2rgb(color)

    candidates = []
    for img in images:
        info = DB.img_info[img]
        main_color = info['main_color']
        img_size = info['size']
        match = False
        match_diff = 0
        if color != '':
            for c in main_color:
                c_rgb = c[0]
                c_prop = c[1]
                diff = rgb_dist(color_rgb, c_rgb)
                if c_prop > 0.1 and diff < 0.25:
                    match = True
                    match_diff = diff
                    break
        if (size == '' or img_size == size) and (color == '' or match):
            candidates.append((img, match_diff))
    # candidates.sort(key=lambda x: x[1])
    return [c[0] for c in candidates]


# 总路由分发
from django.urls import path, re_path, include
from app01 import views

urlpatterns = [
    # -----基本的url配置： path(路径, views视图函数)-----
    path('login/', views.login),
    # -----基本的url配置2： re_path(可使用正则表达式之路径, views视图函数)-----
    re_path(r'^show_time/$', views.show_time),   # ^ 匹配字符串须为网址开头, $ 须为网址结尾
    # -----进阶路由分发(include(欲分配至的url档))-----
    re_path(r'^app01/', include('app01.urls')),  # 有关app01的网址都移到app01的urls，这样APP多时才不会搞混
]


"""Contains functions for running a 100 level challenge."""
from classes.features import Features
import coordinates as coords
import time

class Level(Features):
    """Contains functions for running a 100 level challenge.

    IMPORTANT

    Set target level for energy buster to 67 and charge shot to 33.
    Disable "Advance Energy" in augments
    Disable beards if you cap ultra fast.

    """
    def speedrun(self, duration):
        """Procedure for first rebirth in a 100LC."""
        self.nuke()
        time.sleep(2)
        self.fight()
        diggers = [3]
        self.adventure(highest=True)
        current_boss = int(self.get_current_boss())
        if current_boss < 28:
            self.augments({"CI": 1}, coords.INPUT_MAX)
        if current_boss > 48:
            self.adventure(highest=True)
            self.augments({"EB": 0.66, "CS": 0.34}, self.get_idle_cap(1))
        else:
            self.augments({"EB": 1}, coords.INPUT_MAX)
        if not self.check_pixel_color(*coords.COLOR_TM_LOCKED):
            self.time_machine(1e6, magic=True)
            self.gold_diggers(diggers)
        rb_time = self.get_rebirth_time()
        while int(rb_time.timestamp.tm_min) < duration:
            self.augments({"EB": 0.66, "CS": 0.34}, self.get_idle_cap(1))
            self.nuke()
            self.fight()
            current_boss = int(self.get_current_boss())
            if current_boss == 38:
                self.adventure(highest=True)
            self.gold_diggers(diggers)
            rb_time = self.get_rebirth_time()
            if not self.check_challenge() and rb_time.timestamp.tm_min >= 3:
                return
        if not self.check_challenge() and rb_time.timestamp.tm_min >= 3:
            return
        self.do_rebirth()
        return

    def start(self):
        """Handle LC run."""
        for x in range(5):
            self.speedrun(4)
            if not self.check_challenge():
                return
        for x in range(5):
            self.speedrun(7)
            if not self.check_challenge():
                return
        for x in range(5):
            self.speedrun(12)
            if not self.check_challenge():
                return
        for x in range(5):
            self.speedrun(60)
            if not self.check_challenge():
                return


import cv2
import numpy as np

src = cv2.imread("imori.png")
out = np.zeros_like(src)

[height, width, channels] = src.shape
h_num = height // 8
w_num = width // 8
for i in range(0, h_num):
    for j in range(0, w_num):
        for k in range(0, channels):
            out[i * 8: (i + 1) * 8, j * 8: (j + 1) * 8, k] = np.mean(src[i * 8: (i + 1) * 8, j * 8: (j + 1) * 8, k]).astype(np.uint8)

out = out.astype(np.uint8)

cv2.imshow("result", out)
cv2.imwrite("answer7.jpg", out)
cv2.waitKey(0)
cv2.destroyAllWindows()


# EXERCISE 21 :
# Stephen's speech module is broken. This module is responsible for his number pronunciation. He has to click to input all of the numerical digits in a figure, so when there are big numbers it can take him a long time. Help the robot to speak properly and increase his number processing speed by writing a new speech module for him. All the words in the string must be separated by exactly one space character. Be careful with spaces - it's hard to see if you place two spaces instead one.

FIRST_TEN = ["one", "two", "three", "four", "five", "six", "seven", "eight", "nine"]

SECOND_TEN = [
    "ten",
    "eleven",
    "twelve",
    "thirteen",
    "fourteen",
    "fifteen",
    "sixteen",
    "seventeen",
    "eighteen",
    "nineteen",
]

OTHER_TENS = [
    "twenty",
    "thirty",
    "forty",
    "fifty",
    "sixty",
    "seventy",
    "eighty",
    "ninety",
]

HUNDRED = "hundred"

def new_speech_module(number: int):
    """Takes a integer number and return them in the alphabetical form , and words are sepreated only with one space. So the robot can speak them easily."""
    result = []
    # assert 0 < number < 1000, "number is out of supported range (1-999)"
    assert number > 0 and number < 1000, "number is out of supported range (1-999)"
    # if 100 <= number < 1000:
    if number >= 100 and number < 1000:
        result.append(FIRST_TEN[(number // 100) - 1])
        result.append(HUNDRED)
        number = number % 100
    # if 20 <= number <= 99:
    if number >= 20 and number <= 99:
        result.append(OTHER_TENS[(number // 10) - 2])
        number = number % 10
    # elif 10 <= number <= 19:
    elif number >= 10 and number <= 19:
        result.append(SECOND_TEN[number - 10])
        number = 0
    # if 1 <= number <= 9:
    if number >= 1 and number <= 9:
        result.append(FIRST_TEN[number - 1])
    return " ".join(result)

number = int(input("Enter a number (not more than 3 digits) : "))

output = new_speech_module(number)

print(output)


import uvicorn
from fastapi import FastAPI

from .app import Application, Config, read_config

app = FastAPI(
    title='Summer Practice 2023',
    description='',
    version='0.4',
)

config = Config(**read_config('config.yml'))
application = Application(config=config, app=app)

@app.on_event('startup')
async def startup():
    await application.start()

@app.on_event('shutdown')
async def shutdown():
    await application.stop()

if __name__ == '__main__':
    uvicorn.run(
        'src.__main__:app',
        host=config.app['host'],
        port=config.app['port'],
        reload=True,
    )


"""
クロール・スクレイプ・保存をメイン関数にひとまとめ
"""

import requests
import lxml.html
import csv

def main():
    url = 'https://gihyo.jp/dp'
    html = fetch(url)
    books = scrape(html, url)
    save('books.csv', books)

def fetch(url):
    r = requests.get(url)
    return r.text

def scrape(html, base_url):
    books = []
    html2 = lxml.html.fromstring(html)
    html2.make_links_absolute(base_url)

    for a in html2.cssselect('#listBook>li>a[itemprop="url"]'):
        book_url = a.get('href')

        p = a.cssselect('p[itemprop = "name"]')[0]
        title = p.text_content()

        books.append({'url': book_url, 'title': title})
    return books

def save(file_path, books):
    with open(file_path, 'w', newline="")as f:
        writer = csv.DictWriter(f, ['url', 'title'])
        writer.writeheader()
        writer.writerows(books)

if __name__ == '__main__':
    main()


"""
Wrap the API in the standard API interface

The rest of the files here define a fully featured libgphoto2's API while this file wraps it in a simplified generic interface
"""

from base import smBasePath, smDataPath
from backend import interface

import os.path
import platform
import threading
import constants
import log
import tempfile

EVENTTYPE_TO_NAME = {
	constants.GPEvent.UNKNOWN: 'constants.GPEvent.UNKNOWN',
	constants.GPEvent.TIMEOUT: 'constants.GPEvent.TIMEOUT',
	constants.GPEvent.FILE_ADDED: 'constants.GPEvent.FILE_ADDED',
	constants.GPEvent.FOLDER_ADDED: 'constants.GPEvent.FOLDER_ADDED',
	constants.GPEvent.CAPTURE_COMPLETE: 'constants.GPEvent.CAPTURE_COMPLETE',
}

class API(interface.API):
	"""
	A standard API wrapper class around the WIA API

	This wraps WIA via ActiveX (pythonwin's win32com) directly rather than having in intermediate API as with most other backends
	"""

	def __init__(self,*args,**kargs):
		super(API,self).__init__(*args,**kargs)
		self.opened = False
		self.cameras = None

	def getName(self):
		return 'GPhoto (libgphoto2)'

	def getId(self):
		return 'libgphoto2'

	def open(self):

		if self.opened:
			return

		if platform.system().lower() == 'windows':
			from .remote import client
			self.api = client.GPhotoClient()
			self.opened = True
			self.api.open(workingDir=smDataPath(),basePath=os.path.join(smBasePath(),'backend','libgphoto2'))
		else:
			from . import api
			self.api = api.API()
			self.opened = True
			self.api.open()

	def getCameras(self):
		if self.cameras:
			return self.cameras
		out = []
		apiCameras = self.api.getCameras()
		for apiCamera in apiCameras:
			camera = Camera(self,apiCamera)
			out.append(camera)
		self.cameras = out
		return out

	def close(self):
		if self.cameras:
			for camera in self.cameras:
				try: camera.close()
				except: pass
		if self.opened:
			self.api.close()

class Camera(interface.Camera):

	def __init__(self,api,camera):
		super(Camera,self).__init__(api)
		self.camera = camera
		self.viewfinderThread = None
		self.opened = False
		self.afterOpened = False
		self.config = None
		self.configWidgets = {}
		self.capturedData = None
		self.capturedAuxFiles = []

		self.hasCaptureEvents = None #: None means automatically guess whether capture events are supported

		self.name = '%s %s'%(self.camera.getModel(),self.camera.getPort())

	def getName(self):
		return self.name

	def open(self):
		if self.opened:
			return

		self.opened = True
		self.camera.init()
		self.properties = []
		self.nameToProperty = {}

		# fetch current camera config
		self.configurationFromCamera()

		# try to wake the camera up so we get a complete set of properties to work with
		changed = False
		if 'capture' in self.configWidgets and self.configWidgets['capture']['value'] != 1:
			self.configWidgets['capture']['value'] = 1
			self.configWidgets['capture']['changed'] = True
			changed = True
		if changed:
			self.configurationToCamera()
			self.configurationFromCamera()

		if 'savedProperties' in self.settings:
			self.restoreProperties()
			self.configurationToCamera()
			"""
			try:
				self.restoreProperties()
				self.configurationToCamera()
			except:
				log.logException('Error attempting to restore properties:\n%s'%'\n'.join('  %s=%s'%(name,value) for name,value in self.settings.savedProperties),log.ERROR)
			"""

		# now create new CameraProperty instances in self.properties based on the configuration we just retrieved
		self.createProperties()

		self.afterOpened = True

	def hasViewfinder(self):
		return True

	def hasCapture(self):
		return True

	def capture(self):
		data = self.camera.captureImage()
		self.capturedData = data
		if not self.hasCaptureEvents:
			e = interface.CaptureCompleteEvent(self,data=data,auxFiles=[])
			self.captureComplete.emit(e)

	def getProperties(self):
		return self.properties

	def close(self):
		if not self.opened:
			return

		try:
			self.viewfinderThread.stopped = True
		except:
			pass
		try:
			if 'capture' in self.configWidgets and self.configWidgets['capture']['value'] != 0:
				self.configWidgets['capture']['value'] = 0
				self.configWidgets['capture']['changed'] = True
				self.configurationToCamera()
		except:
			log.logException('unable to turn off capture mode', log.WARNING)
		self.opened = False
		self.camera.exit()

	def ontimer(self):

		if not self.afterOpened:
			return

		while 1:
			eventType,data = self.camera.waitForEvent(timeout=0)
			if eventType == constants.GPEvent.TIMEOUT:
				return
			if self.hasCaptureEvents is None:
				if (eventType == constants.GPEvent.UNKNOWN and data.startswith('PTP Property')) or eventType == constants.GPEvent.FILE_ADDED or eventType == constants.GPEvent.CAPTURE_COMPLETE:
					### TEMP: if we get any valid event we guess that the camera supports PTP end capture events -- not ideal!
					self.hasCaptureEvents = True
			if not eventType == constants.GPEvent.UNKNOWN and data.startswith('PTP Property'):
				# log everything except timeouts and PTP property change events
				log.debug('%s %r'%(EVENTTYPE_TO_NAME[eventType],data))
			if eventType == constants.GPEvent.UNKNOWN and data.startswith('PTP Property'):
				changed = self.configurationFromCamera()
				if not changed:
					continue
				changedProperties = [self.getPropertyByName(widget['name']) for widget in changed]
				event = interface.PropertiesChangedEvent(self,changedProperties)
				self.propertiesChanged.emit(event)
			elif eventType == constants.GPEvent.FILE_ADDED:
				path,fn = data
				tempFn = os.path.join(tempfile.gettempdir(),tempfile.gettempprefix()+fn)
				self.camera.downloadFile(path,fn,tempFn)
				self.capturedAuxFiles.append(tempFn)
			elif eventType == constants.GPEvent.CAPTURE_COMPLETE:
				e = interface.CaptureCompleteEvent(self,data=self.capturedData,auxFiles=self.capturedAuxFiles)
				self.capturedAuxFiles = []
				self.captureComplete.emit(e)

	def startViewfinder(self):
		if 'output' in self.configWidgets and 'LCD' in self.configWidgets['output']['choices'] and self.configWidgets['output']['value'] != 'LCD':
			self.configWidgets['output']['value'] = 'LCD'
			self.configWidgets['output']['changed'] = True
			self.configurationToCamera()
		if self.viewfinderThread and not self.viewfinderThread.stopped:
			return
		self.viewfinderThread = ViewfinderCaptureThread(self)
		self.viewfinderThread.start()

	def stopViewfinder(self):
		if self.viewfinderThread:
			self.viewfinderThread.stopped = True

	def isViewfinderStarted(self):
		if self.viewfinderThread and not self.viewfinderThread.stopped:
			return True
		else:
			return False

	#
	# Non-interface
	#

	def configurationToCamera(self):
		n = 0
		toClear = []
		for section in self.config['children']:
			for widget in section['children']:
				n += 1
				if widget['changed']:
					toClear.append(widget)
		if toClear:
			s = ', '.join(['%s (%s)=%r'%(i['name'],i['label'],i['value']) for i in toClear])
			try:
				self.camera.setConfiguration(self.config)
			except:
				log.logException('Failed setting camera properties %s'%s,log.WARNING)
			else:
				log.debug('Successfully changed camera properties %s'%s)

			for i in toClear:
				i['changed'] = False

	def configurationFromCamera(self):
		old = dict()
		old.update(self.configWidgets)
		changed = []

		self.config = self.camera.getConfiguration()
		for section in self.config['children']:
			for widget in section['children']:
				self.configWidgets[widget['name']] = widget
				if (widget['name'] in old) and (widget['value'] != old[widget['name']]['value']):
					changed.append(widget)

		if changed:
			changedString = '\n        '.join(['%s (%s)=%r'%(i['name'],i['label'],i['value']) for i in changed])

		return changed

	def getWidget(self,id):
		return self.configWidgets[id]

	def createProperties(self):
		self.nameToProperty = {}
		for section in self.config['children']:
			for widget in section['children']:
				if widget['type'] == constants.GPWidget.BUTTON:
					property = GPhotoCameraButton(self,widget['name'])
				else:
					property = GPhotoCameraValueProperty(self,widget['name'])
				property.section = section['label']
				self.properties.append(property)
				self.nameToProperty[widget['name']] = property

		for property in self.api.propertyClasses:
			self.properties.append(property(self,None))

	def getPropertyByName(self,name):
		return self.nameToProperty[name]

	def saveSettings(self):
		saved = []
		if 'config' in self.settings:
			savedProperties = [i['control'] for i in self.settings.config.savedProperties]
			for name in savedProperties:
				if name not in self.configWidgets:
					continue
				value = self.configWidgets[name]['value']
				saved.append((name,value))
		self.settings.savedProperties = saved

	def restoreProperties(self):
		if 'savedProperties' not in self.settings:
			return
		saved = list(self.settings.savedProperties)
		saved.reverse()
		for name,value in saved:
			if name not in self.configWidgets:
				log.warning('could not find property %s to restore'%name)
				continue
			self.configWidgets[name]['value'] = value
			self.configWidgets[name]['changed'] = True

class ViewfinderCaptureThread(threading.Thread):

	def __init__(self,camera):
		super(ViewfinderCaptureThread,self).__init__()
		self.camera = camera
		self.stopped = False

	def run(self):
		while 1:
			if self.stopped:
				break

			data = self.camera.camera.capturePreview()
			e = interface.ViewfinderFrameEvent(self.camera,data=data)
			self.camera.viewfinderFrame.emit(e)

	def stop(self):
		self.stopped = True

WidgetToControlType = {
	constants.GPWidget.WINDOW: None,
	constants.GPWidget.SECTION: None,
	constants.GPWidget.TEXT: interface.ControlType.LineEdit,
	constants.GPWidget.RANGE: interface.ControlType.Slider,
	constants.GPWidget.TOGGLE: interface.ControlType.Checkbox,
	constants.GPWidget.RADIO: interface.ControlType.Combo,
	constants.GPWidget.MENU: interface.ControlType.Combo,
	constants.GPWidget.BUTTON: interface.ControlType.Button,
	constants.GPWidget.DATE: interface.ControlType.LineEdit, ### TODO: Add a date field
}

WidgetNameToControlType = {
	'focuslock': interface.ControlType.TwinButton,
}

def cached(f):
	def withCache(*args,**kargs):
		self = args[0]
		if f.__name__ not in self._cache:
			rc = f(*args,**kargs)
			self._cache[f.__name__] = rc
		return self._cache[f.__name__]
	return withCache

class GPhotoCameraValueProperty(interface.CameraValueProperty):

	def __init__(self,camera,widgetId):
		super(GPhotoCameraValueProperty,self).__init__()
		self.camera = camera
		self.widgetId = widgetId
		self.name = self.widget['label']

	def getName(self):
		return self.name

	def getIdent(self):
		return self.widget['name']

	def getControlType(self):
		if self.widget['name'] in WidgetNameToControlType:
			return WidgetNameToControlType[self.widget['name']]
		else:
			return WidgetToControlType[self.widget['type']]

	def getRawValue(self):
		return self.widget['value']

	def setRawValue(self,v):
		if self.widget['value'] != v:
			self.widget['value'] = v
			self.widget['changed'] = True
			self.camera.configurationToCamera()
			self.camera.configurationFromCamera()

	def rawToDisplay(self,rawValue):
		if self.widget['type'] == constants.GPWidget.TOGGLE:
			if rawValue == 0:
				return None
			elif rawValue == 1:
				return True
			elif rawValue == 2:
				return True
			else:
				log.warn('Unsupported raw value %r for camera toggle control %s'%(rawValue,self.getName()))
		else:
			return rawValue

	def displayToRaw(self,displayValue):
		if self.widget['type'] == constants.GPWidget.TOGGLE:
			if displayValue is None:
				return None
			elif displayValue is False:
				return 0
			elif displayValue is True:
				return 1
			else:
				log.warn('Unsupported display value %r for camera toggle control %s'%(displayValue,self.getName()))
		return displayValue

	def getMin(self):
		return self.widget['range'][0]

	def getMax(self):
		return self.widget['range'][1]

	def getStep(self):
		return self.widget['range'][2]

	def getPossibleValues(self):
		return [(i,i) for i in self.widget['choices']]

	def isSupported(self):
		return True

	def isReadOnly(self):
		return self.widget['readonly']

	def getSection(self):
		return self.section

	#
	# Non-interface
	#
	def getWidget(self):
		return self.camera.getWidget(self.widgetId)
	widget = property(getWidget)

class GPhotoCameraButton(GPhotoCameraValueProperty):

	def getRawValue(self):
		return True

	def go(self):
		self.setRawValue(1)
		self.camera.configurationFromCamera()

API.propertyClasses = []


"""
Final Assignment by
    Lukas Cunningham
    7/26/2021
    Prepare DataBase to load data from a csv file and run advanced
    unit testing.
"""

import csv
from enum import Enum

class EmptyDatasetError(Exception):
    pass

class NoMatchingItems(Exception):
    pass

filename = './AB_NYC_2019.csv'

conversions = {
    "USD": 1,
    "EUR": .84,
    "CAD": 1.23,
    "GBP": .72,
    "CHF": .92,
    "NZD": 1.41,
    "AUD": 1.32,
    "JPY": 110.8
}

home_currency = ''

class DataSet:
    """ the DataSet class will present summary tables based on
    information imported from a .csv file
    """

    copyright = "No copyright has been set"

    class Categories(Enum):
        LOCATION = 1
        PROPERTY_TYPE = 2

    class Stats(Enum):
        MIN = 0
        AVG = 1
        MAX = 2

    def __init__(self, header=""):
        self._data = None
        try:
            self.header = header
        except ValueError:
            self._header = ""

        self._labels = {
            self.Categories.LOCATION: set(),
            self.Categories.PROPERTY_TYPE: set()
        }

    def load_file(self):
        """ Load data into self._data """
        with open(filename, 'r', newline='') as file:
            csv_reader = csv.reader(file)
            next(csv_reader)
            self._data = [(item[1], item[2], int(item[3]))
                          for item in csv_reader]
            print(len(self._data))

        self._initialize_sets()
        # return len(self._data)

    def _initialize_sets(self):
        if self._data is None:
            raise EmptyDatasetError

        for item in self._data:
            (self._labels[self.Categories.LOCATION].add(item[0]))
            (self._labels[self.Categories.PROPERTY_TYPE].add(item[1]))

    @property
    def header(self):
        return self._header

    @header.setter
    def header(self, header: str):
        if len(header) <= 30:
            self._header = header
        else:
            raise ValueError

    def _cross_table_statistics(self,
                                descriptor_one: str, descriptor_two: str):
        """ Given a label from each category, calculate summary
        statistics for the items matching both labels.

        Keyword arguments:
            descriptor_one -- the label for the first category
            descriptor_two -- the label for the second category

        Returns a tuple of min, average, max from the matching rows.
        """
        if not self._data:
            raise EmptyDatasetError

        my_rents = [item[2] for item in self._data if
                    descriptor_one == item[0] and
                    descriptor_two == item[1]]

        if len(my_rents) == 0:
            raise NoMatchingItems

        return float(min(my_rents)), float(sum(my_rents) / len(my_rents)),\
            float(max(my_rents))

    def display_cross_table(self, stat: Stats):
        """
        Print a table of rent statistics
        :param stat: Enum for Min, Avg, Max Rents
        """
        if not self._data:
            raise EmptyDatasetError

        properties = list(self._labels[DataSet.Categories.PROPERTY_TYPE])
        locations = list(self._labels[self.Categories.LOCATION])

        print(20 * " ", end="")
        for header in properties:
            print(f"{header:<22}", end="")
        print()

        for row in locations:
            print(f"{row:<20}", end="")
            for col in properties:
                try:
                    prices = self._cross_table_statistics(row, col)[stat.value]
                    print(f"$ {prices:<20.2f}", end="")
                except NoMatchingItems:
                    na = "N/A"
                    print(f"$ {na:<20}", end="")
            print()

def print_menu():
    """ Display the main menu text. """
    print("Main Menu")
    print("1 - Print Average Rent by Location and Property Type")
    print("2 - Print Minimum Rent by Location and Property Type")
    print("3 - Print Maximum Rent by Location and Property Type")
    print("4 - Load Data")
    print("9 - Quit")

def currency_converter(source_curr: str, target_curr: str, quantity: float):
    """ Convert from one unit of currency to another.

    Keyword arguments:
        quantity -- a float representing the amount of currency to be
                    converted.
        source_curr -- a three letter currency identifier string from
                       the conversions dictionary
        target_curr -- a three letter currency identifier string from
                       the conversions dictionary
    """
    if quantity < 0:
        raise ValueError
    return (quantity / (conversions[source_curr])) * conversions[target_curr]

def currency_options(base_curr: str):
    """ Present a table of common conversions from base_curr to other
    currencies.
    """
    currency_list = []

    print(f"Options for converting from {home_currency}:")

    print(f"{base_curr:10}", end="")
    for item in conversions:
        if item != base_curr:
            currency_list.append(item)
            print(f"{item:10}", end="")
    print()

    for row in range(10, 100, 10):
        print(f"{row:<10.2f}", end="")
        for column in currency_list:
            print(f"{currency_converter(base_curr, column, row):<10.2f}",
                  end="")
        print()
    print()

def menu(dataset: DataSet):
    """ present user with options to access the Airbnb dataset """

    currency_options(home_currency)

    print(dataset.copyright)

    while True:
        print(dataset.header)
        print_menu()

        try:
            user_choice = int(input("What is your choice? "))
        except ValueError:
            print("Please enter a number")
            continue

        if user_choice == 1:
            try:
                dataset.display_cross_table(DataSet.Stats.AVG)
            except EmptyDatasetError:
                print("Please load a DataSet first")

        elif user_choice == 2:
            try:
                dataset.display_cross_table(DataSet.Stats.MIN)
            except EmptyDatasetError:
                print("Please load a DataSet first")

        elif user_choice == 3:
            try:
                dataset.display_cross_table(DataSet.Stats.MAX)
            except EmptyDatasetError:
                print("Please load a DataSet first")

        elif user_choice == 4:
            dataset.load_file()

        elif user_choice == 9:
            print("Goodbye!  Thank you for using the database")
            break

        else:
            print("Please enter a valid number")

def main():
    global home_currency
    DataSet.copyright = "copyright 2021 Luke Cunningham"
    air_bnb = DataSet()

    user_name = input("Please enter your name: ")
    print(f"Hi {user_name}, welcome to Foothill's database project.")

    while home_currency not in conversions:
        home_currency = input("What is your home currency? ")

        if home_currency not in conversions:
            print(f"Please enter AUD, USD, EUR, CAD, GBP, CHF, NZD or JPY")

    while True:
        try:
            air_bnb.header = input("Enter a header for the menu:\n")
            break
        except ValueError:
            print("Header must be a string less than or equal to thirty "
                  "characters long")

    menu(air_bnb)

if __name__ == "__main__":
    main()

"""
Please enter your name: Luke
Hi Luke, welcome to Foothill's database project.
What is your home currency? USD
Enter a header for the menu:
AirBNB 2021
Options for converting from USD:
USD       EUR       CAD       GBP       CHF       NZD       AUD       JPY
10.00     8.40      12.30     7.20      9.20      14.10     13.20     1108.00
20.00     16.80     24.60     14.40     18.40     28.20     26.40     2216.00
30.00     25.20     36.90     21.60     27.60     42.30     39.60     3324.00
40.00     33.60     49.20     28.80     36.80     56.40     52.80     4432.00
50.00     42.00     61.50     36.00     46.00     70.50     66.00     5540.00
60.00     50.40     73.80     43.20     55.20     84.60     79.20     6648.00
70.00     58.80     86.10     50.40     64.40     98.70     92.40     7756.00
80.00     67.20     98.40     57.60     73.60     112.80    105.60    8864.00
90.00     75.60     110.70    64.80     82.80     126.90    118.80    9972.00

copyright 2021 Luke Cunningham
AirBNB 2021
Main Menu
1 - Print Average Rent by Location and Property Type
2 - Print Minimum Rent by Location and Property Type
3 - Print Maximum Rent by Location and Property Type
4 - Load Data
9 - Quit
What is your choice? 1
Please load a DataSet first
AirBNB 2021
Main Menu
1 - Print Average Rent by Location and Property Type
2 - Print Minimum Rent by Location and Property Type
3 - Print Maximum Rent by Location and Property Type
4 - Load Data
9 - Quit
What is your choice? 2
Please load a DataSet first
AirBNB 2021
Main Menu
1 - Print Average Rent by Location and Property Type
2 - Print Minimum Rent by Location and Property Type
3 - Print Maximum Rent by Location and Property Type
4 - Load Data
9 - Quit
What is your choice? 3
Please load a DataSet first
AirBNB 2021
Main Menu
1 - Print Average Rent by Location and Property Type
2 - Print Minimum Rent by Location and Property Type
3 - Print Maximum Rent by Location and Property Type
4 - Load Data
9 - Quit
What is your choice? 4
48895
AirBNB 2021
Main Menu
1 - Print Average Rent by Location and Property Type
2 - Print Minimum Rent by Location and Property Type
3 - Print Maximum Rent by Location and Property Type
4 - Load Data
9 - Quit
What is your choice? 1
                    Private room          Shared room           Entire home/apt
Bronx               $ 66.79               $ 59.80               $ 127.51
Queens              $ 71.76               $ 69.02               $ 147.05
Staten Island       $ 62.29               $ 57.44               $ 173.85
Brooklyn            $ 76.50               $ 50.53               $ 178.33
Manhattan           $ 116.78              $ 88.98               $ 249.24
AirBNB 2021
Main Menu
1 - Print Average Rent by Location and Property Type
2 - Print Minimum Rent by Location and Property Type
3 - Print Maximum Rent by Location and Property Type
4 - Load Data
9 - Quit
What is your choice? 2
                    Private room          Shared room           Entire home/apt
Bronx               $ 0.00                $ 20.00               $ 28.00
Queens              $ 10.00               $ 11.00               $ 10.00
Staten Island       $ 20.00               $ 13.00               $ 48.00
Brooklyn            $ 0.00                $ 0.00                $ 0.00
Manhattan           $ 10.00               $ 10.00               $ 0.00
AirBNB 2021
Main Menu
1 - Print Average Rent by Location and Property Type
2 - Print Minimum Rent by Location and Property Type
3 - Print Maximum Rent by Location and Property Type
4 - Load Data
9 - Quit
What is your choice? 3
                    Private room          Shared room           Entire home/apt
Bronx               $ 2500.00             $ 800.00              $ 1000.00
Queens              $ 10000.00            $ 1800.00             $ 2600.00
Staten Island       $ 300.00              $ 150.00              $ 5000.00
Brooklyn            $ 7500.00             $ 725.00              $ 10000.00
Manhattan           $ 9999.00             $ 1000.00             $ 10000.00
AirBNB 2021
Main Menu
1 - Print Average Rent by Location and Property Type
2 - Print Minimum Rent by Location and Property Type
3 - Print Maximum Rent by Location and Property Type
4 - Load Data
9 - Quit
What is your choice? 9
Goodbye!  Thank you for using the database
"""


from flask_app import app
from flask import render_template,redirect,request,session,flash
from flask_app.models.model_message import Message
#from flask_app.controllers import controller_routes

@app.route('/login/send', methods=["POST"])
def send_message():
    is_valid = Message.validate_form(request.form)
    if not is_valid:
        return redirect('/login')
    print(request.form["which_form"])
    data = {
        "content" : request.form["content"],
        "recipient_id" : request.form["which_form"],
        "account_id" : session["user_id"]
    }
    print(data)
    new_message_id=Message.insert_one(data)
    return redirect('/login')

@app.route('/login/delete/<message_id>')
def delete_message(message_id):
    data = {
        "message_id" : message_id
    }
    Message.delete_one(data)
    return redirect('/login')


import asyncio
from typing import Callable

import pytest

from async_lru import alru_cache

async def test_cache_close(check_lru: Callable[..., None]) -> None:
    @alru_cache()
    async def coro(val: int) -> int:
        await asyncio.sleep(0.2)

        return val

    assert not coro.cache_parameters()["closed"]

    inputs = [1, 2, 3, 4, 5]

    coros = [coro(v) for v in inputs]

    gather = asyncio.gather(*coros)

    await asyncio.sleep(0.1)

    check_lru(coro, hits=0, misses=5, cache=5, tasks=5)

    close = coro.cache_close()

    check_lru(coro, hits=0, misses=5, cache=5, tasks=5)

    await close

    check_lru(coro, hits=0, misses=5, cache=5, tasks=0)
    assert coro.cache_parameters()["closed"]

    with pytest.raises(asyncio.CancelledError):
        await gather

    check_lru(coro, hits=0, misses=5, cache=5, tasks=0)
    assert coro.cache_parameters()["closed"]

    # double call is no-op
    await coro.cache_close()


from __future__ import print_function
import shutil
import glob
from pyrocko import util, model
km = 1000.

data_path='/'
file_sta='loc.txt'

def read_loki_catalog(fn):
    names = set()
    events = []
    with open(fn, 'r') as f:
        for line in f:
            w = line.split()

            t = util.str_to_time(w[0], format='%Y-%m-%dT%H:%M:%S.OPTFRAC') #converti str in formato tempo
            lat = float(w[1])
            lon = float(w[2])
            depth = float(w[3])*km

            name = util.time_to_str(t, format='%Y_%m_%d_%H_%M_%S') #converti tempo in str

            if name in names:
                continue

            names.add(name)

            event = model.Event(
                time=t,
                lat=lat,
                lon=lon,
                depth=depth,
                name=name)

            event.old_name = w[0].strip()

            events.append(event)

    return events

events_loki = read_loki_catalog(data_path+file_sta)
model.dump_events(events_loki, data_path +'loc.pf') #save events as pyrocko catalog


#coding: utf-8
import os
import sys
import re
import jieba
import math
import random
#import numpy as np
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.naive_bayes import MultinomialNB
from sklearn.pipeline import Pipeline
from sklearn.feature_extraction.text import TfidfVectorizer, HashingVectorizer, CountVectorizer
from sklearn import metrics
from sklearn.naive_bayes import BernoulliNB
from sklearn.neighbors import KNeighborsClassifier
from sklearn.svm import LinearSVC
from sklearn.cluster import KMeans
from sklearn import tree
class feature:
	def __init__(self,train_path,test_path):
		self.train_path = train_path
		self.test_path=test_path
		self.allClass = []
		self.stop=[]
		for (dirname,dirs,files) in os.walk(self.train_path):
			for eachdir in dirs:
				self.allClass.append(eachdir)

	def buildcorpus(self,pathh):
		corpus= []
		for eachclass in self.allClass:
			current_path = os.path.join(pathh,eachclass)
			for (dirname,dirs,filenames) in os.walk(current_path):
				for filename in filenames:
					with open(os.path.join(current_path,filename),'r') as f:
						content = f.read()
						corpus.append((content,eachclass))
		return corpus
	def train_and_test_data(self,corpus_train,corpus_test):
		train_data = [each[0] for each in corpus_train]
		train_target = [each[1] for each in corpus_train]
		test_data = [each[0] for each in corpus_test]
		test_target = [each[1] for each in corpus_test]
		return train_data, train_target, test_data, test_target

	def jieba_tokenizer(self,x):
		return jieba.cut(x)

	def calculate_result(self,pred,test):
			count=0
			for left,right in zip(pred,test_target):
				if left==right:
					count+=1
			return str(count/float(len(test_target)))
	def classifier(self,train_data,train_target,test_data,test_target):

		words_tfidf_vec = TfidfVectorizer(binary=False, tokenizer=self.jieba_tokenizer)
		train = words_tfidf_vec.fit_transform(train_data)
		test = words_tfidf_vec.transform(test_data)
		clf_svc = LinearSVC().fit(train, train_target)
		pred_svc=clf_svc.predict(test)
		#......................svm........................................
		clf_bayes=MultinomialNB().fit(train,train_target)
		pred_bayes=clf_bayes.predict(test)
		#.......................bayes......................................
		clf_knn=KNeighborsClassifier().fit(train,train_target)
		pred_knn=clf_knn.predict(test)
		#..........................knn......................................
		clf_tree=tree.DecisionTreeClassifier().fit(train,train_target)
		pred_tree=clf_tree.predict(test)
		#self.calculate_result(pred_kmeans.labels_,test_target)
		f=open('F:/classify/classify_content/result/result_sklearn.txt','w')
		f.write("sklearn分类器的分类结果为：")
		f.write("\n")
		f.write("svm分类器的分类结果为：")
		f.write(self.calculate_result(pred_svc,test_target))
		f.write("\n")
		f.write("Bayes分类器的分类结果为：")
		f.write(self.calculate_result(pred_bayes,test_target))
		f.write("\n")
		f.write("KNN分类器的分类结果为：")
		f.write(self.calculate_result(pred_knn,test_target))
		f.write("\n")
		f.write("决策树分类器的分类结果为：")
		f.write(self.calculate_result(pred_tree,test_target))
		f.write("\n")

#if __name__ == '__main__':
featureTest = feature('F:/classify/classify_content/data/ClassFile','F:/classify/classify_content/data/TestFile')
corpus_train=featureTest.buildcorpus('F:/classify/classify_content/data/ClassFile')
corpus_test=featureTest.buildcorpus('F:/classify/classify_content/data/TestFile')
train_data, train_target, test_data, test_target = featureTest.train_and_test_data(corpus_train,corpus_test)
featureTest.classifier(train_data, train_target, test_data, test_target)


import cgi
import logging
import os.path
import time
import urllib
import datetime
from data import models
from google.appengine.ext import db
from google.appengine.ext import webapp
from google.appengine.ext.webapp import template
from google.appengine.ext.webapp.util import run_wsgi_app
from google.appengine.ext.db import djangoforms
from django.utils import simplejson
from google.appengine.api import mail
from django.core.validators import email_re
import lilcookies
import hashlib
import django.newforms as forms
import random
from googlemaps import GoogleMaps
import facebook

class TestBase(webapp.RequestHandler):
    template_path = '/templates/service_test/'

    def get(self):
        self.post()
    def post(self):
        pass

    def param(self, name):
        return self.request.get(name)

    def write(self, mes):
        self.response.out.write(mes)

    def _create_item_code(self):
        alphabet = 'ABCDEFGHJKLMNPQRSTUVWXYZ23456789'
        return "".join(random.sample(alphabet,8))

    def generate (self, fileIn, values):
        ROOT_PATH = os.path.dirname(__file__)
        path = os.path.join(ROOT_PATH + self.template_path, str(fileIn))
        self.response.out.write(template.render(path, values))

    @property
    def enviroment(self):
        if not hasattr(self, "_enviroment"):
            self._enviroment = None
            self._enviroment = models.Environment.get_for_current_environment()
        return self._enviroment;

    @property
    def test_location(self):
        if not hasattr(self, "_test_location"):
            self._test_location = None
            if models.Category.all().count() <= 0:
                cat = models.Category(name="Food/Beverage", description="")
                cat.put()

                subcat = models.Category(name="Resturant", description="", parent_category=cat)
                subcat.put()

                subcat = models.Category(name="Coffee House", description="", parent_category=cat)
                subcat.put()

            self._test_location = models.Location.gql("WHERE name='Some Coffee Place'").get()
            if not self._test_location:
                models.Difficulty.load()
                self._test_location = models.Location(owner=models.User.get_test_user(), location=db.GeoPt(37, -122))
                self._test_location.address = "310 SW 3rd Street"
                self._test_location.name = "Some Coffee Place"
                self._test_location.description = "Some Coffee Place used for testing"
                self._test_location.category = models.Category.gql("WHERE name='Coffee House'").get()
                self._test_location.city = "Corvallis"
                self._test_location.state = "OR"
                self._test_location.zip = "97333"
                self._test_location.county = "USA"
                self._test_location.phone_number = "(541) 757-3025"
                self._test_location.rating = 48
                self._test_location.put()
                gmaps = GoogleMaps(self.enviroment.google_maps_key)
                lat, lng = gmaps.address_to_latlng(self._test_location.get_address())
                self._test_location.update_location(db.GeoPt(lat, lng))
                self._test_location.save()

                difficulty = models.Difficulty.find( 'MEDIUM' )
                oneMonth = datetime.timedelta(days=30)
                today = datetime.date.today()
                expires = today + oneMonth

                for i in range(1, 5):
                    code = self._create_item_code()
                    item = models.Item.get_by_key_name(code)
                    while item:
                        code = self._create_item_code()
                        item = models.Item.get_by_key_name(code)
                    item = models.Item(key_name=code, location=self._test_location,
                                       name="Free 20oz Coffee",
                                       details="Show Code at Counter to get a Free Coffee 20oz",
                                       active=True, code=code, expires=expires, difficulty=difficulty)
                    item.put()
            return self._test_location

class Index(TestBase):

    url = "/test"
    url2 = "/test/"
    template = "index.html"

    def post(self):
        cleared_message = self.request.get('cleared_message')
        u = models.User.get_test_user()
        if u:
            at = models.AccessToken.create_for_user(u)
        self.generate(Index.template, {'cleared_message':cleared_message, 'test_user_access_token':at.token, 'test_location_key':self.test_location.key()})

class Clear(TestBase):

    url = "/test/clear"

    def post(self):

        client = models.ServiceClient.valid("882AF324A4DC11DFB3BABF3DE0D72085")
        if client:
            try:
                for log in client.log:
                    if log.access_token:
                        if log.access_token.user:
                            try:
                                log.access_token.user.delete();
                            except:
                                pass
                        try:
                            log.access_token.delete()
                        except:
                            pass
                    log.delete()
            except:
                pass
        self.redirect('test?cleared_message=data cleared %s' % datetime.datetime.now().strftime("%m/%d/%y %I:%M:%S"))

application = webapp.WSGIApplication([
                                      (Index.url, Index),
                                       (Index.url2, Index),
                                       (Clear.url, Clear)
                                     ], debug=True)

def main():
    run_wsgi_app(application)

if __name__ == "__main__":
    main()


user_0 = {
    'username': 'eferm1',
    'first': 'enrico',
    'last': 'fermi',
}

# looping through the dictionary
for key, value in user_0.items():  # .items() is a method that returns a list of key-value pairs
    # ^     ^  these two variables can be defined with any variable name
    print("\nKey: " + key)
    print("Value: " + value)

favorite_language = {
    'jen': 'python',
    'sarah': 'c',
    'edward': 'ruby',
    'phil': 'python',
    }

for name, language in favorite_language.items():
    print(name.title() + "'s favorite language is " +
          language.title() + ".")

# looping through all the keys in a dictionary
favorite_language = {
    'jen': 'python',
    'sarah': 'c',
    'edward': 'ruby',
    'phil': 'python',
    }

for name in favorite_language.keys():  # keys() returns all the keys in dictionary
    print(name.title())
# above is equal to:
for name in favorite_language:
    print(name.title())

# looping through keys in dictionary with if statement
friends = ['phil','sarah']
for name in favorite_language:  # loop through dictionary
    print(name.title())
    if name in friends:  # if statement, check if within friend list
        print("Hi " + name.title() +
              ", I see your favorite language is " +
              favorite_language[name].title() + "!")

if 'erin' not in favorite_language.keys():
    print("Erin, please take our poll!")

# return items from dictionary in certain order
favorite_language = {
    'jen': 'python',
    'sarah': 'c',
    'edward': 'ruby',
    'phil': 'python',
    }

for name in sorted(favorite_language.keys()):  # sort the returned key list in order temporarily
    print(name.title() + ", thank you for taking the poll.")

# looping through all values in a dictionary
favorite_language = {
    'jen': 'python',
    'sarah': 'c',
    'edward': 'ruby',
    'phil': 'python',
    }
print("The following languages have been mentioned:")
for language in favorite_language.values():  # values() return all values in a dictionary
    print(language.title())

for language in sorted(set(favorite_language.values())):  # set() a unique list of all elements included
    print(language.title())

"Exercise"
# 6.5
rivers = {
    'nile':'egypt',
    'yellow river': 'china',
    'mississippi': 'usa',
    'rhine': 'france',
    }
for river, country in sorted(rivers.items()):
    print("The " + river.title() + " runs through " +
          country.title() + ".")

river_list = ""
for river in sorted(rivers.keys())[:-1]:
    river_list = river_list + river.title() + ", "
river_list = river_list + sorted(rivers.keys())[-1].title()
print(river_list)

country_list = [country for country in sorted(rivers.values())]
print_list = ""
for country in country_list[:-1]:
    print_list = print_list + country.title() + ", "
print_list = print_list + country_list[-1].upper()
print(print_list)

river_list = [river for river in sorted(rivers.keys())]
country_list = [country for country in sorted(rivers.values())]
print_tasks = [river_list, country_list]
for print_task in print_tasks:
    print_list = ""
    for item in print_task:
        print_list = print_list + item.title() + ", "
    print_list = print_list + print_task[-1].title()
    print(print_list)

# 6.6
favorite_languages = {
    'jen':'python',
    'sarah':'c',
    'edward':'ruby',
    'phil':'python',
    }
target_respondents = ['jen','sarah','jason','neal','kevin']

for individual in sorted(target_respondents):
    if individual in favorite_languages.keys():
        print(individual.title() +
              ", thank you for taking the poll!")
    else:
        print(individual.title() +
              ", please take the poll, thank you!")


import os

class processes:

    path = '>'

    '''
    errors_amount = 0

    def error(self, msg, type):

        self.errors_amount = 1
        errors = ['Bad command', 'Item or container not found']

        print("E: " + type + " error: " + msg if type(msg) == 'str' else errors[msg] if msg >= self.errors_amount else "Unknown error")
    '''
    def save(self, data, itempath):
        with open(itempath, 'w+') as f:
            try:
                f.write(data)
            except:
                processes.error(1, "fatal")
            finally:
                f.close()

    def load(self, itempath):
        with open(itempath, 'r+') as f:
            try:
                f.read()
            except:
                processes.error(1, "fatal")
            finally:
                f.close()

'''
class exec_cmd:

    def __init__(self):
        print("'exec_cmd': MODULE ACTIVATED.")

    def exec(self, cmd):
        if type(cmd) == 'int':
            pass
        else:
            if 'cd' in cmd:
                cmd = cmd.replace('cd ', '')
                os.chdir(cmd.replace('>', '/'))
            elif cmd == 'ls':
                os.listdir(path)

'''


import re, nltk, pickle, string, time
from text_tools import clean_comment, get_text_vectors
import numpy as np
import matplotlib.pyplot as plt
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.model_selection import train_test_split, KFold
from sklearn.metrics import confusion_matrix, accuracy_score, precision_score, recall_score
from sklearn.ensemble import GradientBoostingClassifier

def plot_confusion_matrix(test, pred):
	#Given test labels and predicted labels, plot the confusion matrix, and make it
	#pretty.
	labels = np.asarray(['Not Bot', 'Bot'])
	cm = confusion_matrix(labels[test], labels[pred], labels)
	fig = plt.figure()
	ax = fig.add_subplot(111)
	cax = ax.matshow(cm)
	plt.title('Confusion matrix of the classifier')
	fig.colorbar(cax)
	ax.set_xticklabels([''] + list(labels))
	ax.set_yticklabels([''] + list(labels))
	ax.xaxis.set_ticks_position("bottom")
	plt.xlabel('Predicted')
	plt.ylabel('True')
	plt.tight_layout()
	plt.show()

def remove_non_commenting_users(comment_dict, min_comments = 0, min_words = 0):
	#Some users haven't written much, or not at all. Remove those users because
	#the classifier won't be able to make a reliable prediction on them.
	#
	#The user can also make a cut based on the min number of comments. Also, note the
	#input is a dictionary with keys being usernames, and items being the comments
	#from that username.

	#If the user hasn't specified a min number of words, cut on number of comments.
	if not min_words:
		return {x[0]:x[1] for x in comment_dict.items() if len(x[1]) >= min_comments}

	#Else, sum up all the words in all their comments and cut users who have written
	#a number of words below that specified by the user.
	else:
		outdict = {}
		for uname, comments in comment_dict.items():
			#Get the total number of words written. Keep the user's comments if it
			#makes the cut.
			if sum([len(x.split()) for x in comments]) > min_words:
				outdict[uname] = comments
		return outdict

#Load in comments from bots and from normal users
with open("not_bot_comments_0-150.pkl", "rb") as f:
	not_bot_dict = pickle.load(f)
with open("bot_comments_dict.pkl", "rb") as f:
	bot_reddit_dict = pickle.load(f)

#Remove commenters who haven't commented much
bot_reddit_dict = remove_non_commenting_users(bot_reddit_dict, min_words=40)
not_bot_dict = remove_non_commenting_users(not_bot_dict, min_words=1000)

#Combine comments from users such that each element of the corpi list is the collection
#of all the comments written by a single user.
bot_reddit_corpi = [" ".join(bot_reddit_dict[x]) for x in bot_reddit_dict.keys()]
not_bot_reddit_corpi = [" ".join(not_bot_dict[x]) for x in not_bot_dict.keys()]

#Print info about how balanced the dataset is.
print("Got comments from %d bots and %d other users." % (len(not_bot_dict.keys()), len(bot_reddit_dict.keys())))

#Keep track of how long the process is taking.
stime = time.time()
print("Started", time.strftime("%a, %d %b %Y %H:%M:%S %Z", time.localtime()))

#Vectorize the comments. Also keep the vectorizer to use on new comments.
features, vectorizer = get_text_vectors(bot_reddit_corpi + not_bot_reddit_corpi, vectorizer=TfidfVectorizer())

#Label the data correctly.
labels = np.asarray([1]*len(bot_reddit_corpi) + [0]*len(not_bot_reddit_corpi))
print("Getting vectors took %0.1f minutes." % ((time.time()-stime)/60))

#We'll use K-fold cross validation here, where K is 6. This will allow a good number
#of folds with each fold having a decent amount of data in it
kf = KFold(n_splits=6, shuffle=True, random_state=90)
correct_probs = []
incorrect_probs = []
accs = []
preciss = []
recalls = []
i=0

#Keep track of how long the process is taking.
stime = time.time()
print("Started fitting at", time.strftime("%a, %d %b %Y %H:%M:%S %Z\n", time.localtime()))

#For each fold, train the model and print out performance metrics for it.
#The metric we care about most is precision, because if we're calling someone a Russian
#troll, we want to make sure we're right.
#The learning rate and n_estimators have been tuned externally.
for train_indices, test_indices in kf.split(features):
	#Get features and labels.
	features_train = features[train_indices]
	features_test = features[test_indices]
	labels_train = labels[train_indices]
	labels_test = labels[test_indices]

	#Make and fit the classifier.
	clf = GradientBoostingClassifier(learning_rate=0.33, n_estimators=500)
	clf.fit(features_train.toarray(), labels_train)

	#Make predictions.
	pred = clf.predict(features_test.toarray())
	pred_probs = clf.predict_proba(features_test.toarray())

	#Calculate and print information about each fold's training set/performance metrics.
	acc = 100*accuracy_score(labels_test, pred)
	prec = 100*precision_score(labels_test, pred)
	recall = 100*recall_score(labels_test, pred)
	accs.append(acc)
	preciss.append(prec)
	recalls.append(recall)
	print("Number of bots in training set:		 ", sum(labels_train))
	print("Number of regular users in training set:", len(labels_train)-sum(labels_train))
	print("Ratio of bots to regular users:		  %0.1f" % (sum(labels_train)/(len(labels_train)-sum(labels_train))))
	print("Performance metrics for fold %d:" % (i))
	print("Accuracy:  %0.1f" % (acc))
	print("Precision: %0.1f" % (prec))
	print("Recall:	%0.1f" % (recall))
	print()
	i += 1

#Print the average performance of the model.
print("Average accuracy:  %0.1f" % (sum(accs)/len(accs)))
print("Average precision: %0.1f" % (sum(preciss)/len(preciss)))
print("Average recall:	%0.1f" % (sum(recalls)/len(recalls)))
print("Time to completion: %0.1f min" % ((time.time()-stime)/60))

#Plot the confusion matrix
plot_confusion_matrix(labels_test, pred)

#Fit on all features/labels for final classifier.
clf.fit(features, labels)

#Now test the classifier out on users it hasn't seen before. Note that *none* of these
#should be bots/trolls.
with open("not_bot_comments_all.pkl", "rb") as f:
	all_not_bot_dict = pickle.load(f)

#Prep the data as before.
all_not_bot_dict = remove_non_commenting_users(all_not_bot_dict, min_words = 1000)
all_not_bot_reddit_corpi = [" ".join(all_not_bot_dict[x]) for x in all_not_bot_dict.keys()]

#Keep track of how long the process is taking.
stime = time.time()
print("Started geting vectors at", time.strftime("%a, %d %b %Y %H:%M:%S %Z", time.localtime()))
normal_features = get_text_vectors(all_not_bot_reddit_corpi, vectorizer=vectorizer)
normal_labels = np.asarray([0]*len(all_not_bot_reddit_corpi))
print("Getting vectors took %0.1f minutes." % ((time.time()-stime)/60))

#Make predictions based on the new users.
pred = clf.predict(normal_features)
pred_probs = clf.predict_proba(normal_features)
print("Incorrectly classified %0.1f percent of innocent users as bots." % (100*sum(pred)/len(pred)))

#Save the classifier and vectorizer.
#with open("final_classifier_vectorizer.pkl", "wb") as f:
#	pickle.dump([clf, vectorizer], f)