import discord
import os
import random
from keep_alive import keep_alive
import urllib.request, json
import time

from owoify import owoify
import TenGiphPy
# https://github.com/realSnosh/TenGiphPy

from Services import google_search
from Services import quote_search
from Services import to_binary
from datetime import datetime
from Services import eight_ball
from youtube_dl import YoutubeDL
from discord.utils import get
from discord import FFmpegPCMAudio
from Services import reddit_file

# Retrieve keys from .env storage
# (Note, you can replace os.getenv("tokenname") with "key")
discordKey = os.getenv("TOKEN")
# Discord Key is from https://discord.com/developers/applications
# Create bot, then go to Bot -> Token -> Copy
tenorBotKey = os.getenv("TENORKEY")
# Retrieved from https://tenor.com/developer/keyregistration
WolframAppId = os.getenv("APPID")
# Key retrieved from https://products.wolframalpha.com/simple-api/documentation/

tenorBot = TenGiphPy.Tenor(token=tenorBotKey)
client = discord.Client()

################################################
# Variables
################################################

# List of commands
visibleCommands = [
  "inspire (i.e. 'inspire me')", "gif (i.e. 'search a gif for dabbing')", "uwuify (i.e. uwuify to be or not to be)", "youtube" "calculate (i.e. 'calculate the definite integral of x from 0 to 1')",
  "search (i.e. 'search for when discord was made')", "find (i.e. 'find an article about james bond')", "image (i.e. 'find an image of James Bond')", "play (i.e. 'play Astronaut in the Ocean'", "meme"
]

# Indication of words to search for a youtube video
videoIndicatorWords = [
  "youtube",
  "video"
]

# Indication to search for a gif
gifIndicators = [
  "gif",
  "gifs"
]

# Indication of words to get uwu stuff
uwuifyIndicators = [
  "uwuify",
  "owoify"
]

# Indication of meme
memeIndicator =[
  "meme"
]

# Indication words to receive commands
helpindicators = [
  "help",
  "assistance",
  "command",
  "cmds"
]

# Indication words to receive a quote
inspireIndicator = [
  "inspire",
  "quote"
]

# Indication words to calculate or do math
calculateIndicator = [
  "mathematics",
  "math",
  "calculate",
  "calc",
  "solve",
  "wolfram"
]

# Indication words to calculate or do math, but will be kept in the message
calcWhitelistWords = [
  "definite integral",
  "indefinite integral",
  "integrate",
  "derivative",
  "derive",
  "integral",
  "add",
  "subtract",
  "multiply",
  "graph",
  "plot",
  "find max",
  "find min",
  "get max",
  "get min"
]

# Indication words to search for information
searchIndicator =[
  "search"
]

# Indication words to play for music
playIndicator =[
  "play"
]

# Indication words for disconnecting from voice channel
discionnectIndicators = [
  "disconnect",
  "dc",
  "leave",
  "bye"
]

# Indication words to find an article on the internet and share a link
findArticle = [
  "article",
  "link",
  "find"
]

# Indication of image search
findImage = [
  "picture",
  "image",
  "illustration",
  "illustrate",
  "img",
  "pic"
]

# Words that should be removed if they are in front of the indication that is found
slackWords = [
  "in",
  "for",
  "of",
  "to",
  "from",
  "about",
  "search",
  "the",
  "an"
]

def slicer(my_str,sub):
  index=my_str.find(sub)
  if index !=-1 :
    return my_str[(index):]
  else :
    return my_str

def removeIndicators(string, indicatorArray):
  stri = string.lower()
  for val in indicatorArray:
    stri = slicer(stri, val)

  for val in slackWords:
    try:
      index = stri.find(val)
      if index != -1 and index < (val.length()+1):
        stri = stri[val.length():]
    except:
      continue
  print(stri)
  return stri

def help():
	commandString = ""
	commandString += "**Commands** \n"
	commandString += "You can talk to me about the following \n"
	for val in visibleCommands:
		commandString += "- " + val + "\n"
	return commandString
################################################
# Discord Events
################################################

@client.event
async def on_ready():
  print("We have logged in as {0.user}".format(client))
  await client.change_presence(activity=discord.Game("DM me"))

@client.event
async def on_message(message):

	if message.author == client.user:
		return

	msg = message.content

  # If bot is mentioned or in dm's
	mention = f'<@!{client.user.id}>'
	if msg.find(mention) == -1:
		mention = f'<@{client.user.id}>'

	isDM = isinstance(message.channel, discord.DMChannel)
	channel_nsfw = False
	if not isDM:
		channel_nsfw = message.channel.is_nsfw()

	if mention in msg or isDM:
		try:
			if isDM:
				userText = msg
			else:
				userText = msg.split(mention, 1)[1]

			response = ""

			# If another user is mentioned, we would do an 8 ball response
			if len(message.mentions) > 1:
				# print("test")
				try:
					mes = userText.lower()
					if mes.find("what") != -1 or mes.find("where") != -1:
						response = eight_ball.what_ball()
					elif mes.find("who") != -1:
						response = eight_ball.who_ball()
					elif mes.find("why") != -1:
						response = eight_ball.why_ball()
					else:
						response = eight_ball.eight_ball()
				except Exception as err:
					print(err)

			# If Binary, convert to string
			elif to_binary.is_Binary(userText):
				response = to_binary.binaryConvert(userText)

      # If indicated to find an image
			elif any(word in msg.lower() for word in findImage):
				if channel_nsfw:
					try:
						random.seed(time.time())
						response = google_search.image_search(removeIndicators(userText, findImage), False)

					except Exception as err:
						if str(err).find("429") != -1:
							message.channel.send("Img quota exceeded, scraping...")
							response = google_search.image_search2(removeIndicators(userText, findImage), False)
						else:
							response = "Something with image search went wrong."

						print(err)
				else:
					try:
						random.seed(time.time())
						response = google_search.image_search(removeIndicators(userText, findImage), True)
						print(response)

					except Exception as err:
						if str(err).find("429") != -1:
							message.channel.send("Img quota exceeded, scraping...")
							response = google_search.image_search2(removeIndicators(userText, findImage), True)
						else:
							response = "Something with image search went wrong."
						print(err)

      # Disconnect from voice channel
			elif any(word in msg.lower() for word in discionnectIndicators):
				try:
					for x in client.voice_clients:
						if(x.guild == message.guild):
							return await x.disconnect()
					response = "Done :+1:"
				except:
					response = "Something went wrong..."

			# If video/youtube key word, search for a YouTube video or play a youtube song
			elif any(word in msg.lower() for word in videoIndicatorWords) or any(word in msg.lower() for word in playIndicator):
				try:

					toPlayMusic = any(word in msg.lower() for word in playIndicator)
					response = google_search.youtube_search(removeIndicators(removeIndicators(userText, videoIndicatorWords), playIndicator))

					if toPlayMusic:
						await message.channel.send("Loading Song")
						YDL_OPTIONS = {'format': 'bestaudio', 'noplaylist':'True'}
						FFMPEG_OPTIONS = {'before_options': '-reconnect 1 -reconnect_streamed 1 -reconnect_delay_max 5', 'options': '-vn'}
						voice = get(client.voice_clients, guild=message.guild )
						voice_channel = message.author.voice.channel

						if not voice or not voice.is_playing() or voice != voice_channel:
							if voice != voice_channel:
								voice = await voice_channel.connect()

							with YoutubeDL(YDL_OPTIONS) as ydl:
								info = ydl.extract_info(response, download=False)
							URL = info['formats'][0]['url']
							voice.play(FFmpegPCMAudio(URL, **FFMPEG_OPTIONS))
							voice.is_playing()
							await message.channel.send("Playing")
						else:
							await message.channel.send("Already playing song")
							return

				except Exception as err:
					print(err)

      # If indicated to find a meme
			elif any(word in msg.lower() for word in memeIndicator):
				response = reddit_file.get_meme()

      # If indicated as gif
			elif any(word in msg.lower() for word in gifIndicators):
				try:
					random.seed(time.time())
					response = tenorBot.random(removeIndicators(userText, gifIndicators))
				except Exception as err:
					print(err)
      # If indicated to find article
			elif any(word in msg.lower() for word in findArticle):
				try:
					random.seed(time.time())
					links = google_search.get_links(removeIndicators(userText, findArticle))
					response = random.choice(links)
				except Exception as err:
					print(err)

      # If indicated to calculate and do math
			elif any(word in msg.lower() for word in calculateIndicator) or any(word in msg.lower() for word in calcWhitelistWords):
				try:
					textToUse = removeIndicators(userText, calculateIndicator)
					inputVal = textToUse.replace("+", "%2B")
					inputVal = inputVal.replace(" ","+")
					wolfUrl = "https://api.wolframalpha.com/v2/query?input=" + inputVal +"&format=image&output=JSON&appid=" + WolframAppId + "&podstate=Step-by-step%20solution&format=plaintext"

					now = datetime.now()

					current_time = now.strftime("%H:%M:%S")
					print(message.author.name, "requested url", wolfUrl, "at", current_time)
					with urllib.request.urlopen(wolfUrl) as url:
						data = json.loads(url.read().decode())
						if data["queryresult"]:

							await message.channel.send("Note that log is the natural log ln, and there may be absolute values not present when calculating the integral.")
							resp1 = data["queryresult"]["pods"][0]["subpods"][0]["img"]["src"]
							print("Response 1", resp1)
							await message.channel.send(resp1)

							response = data["queryresult"]["pods"][1]["subpods"][0]["img"]["src"]

							resp2 = data["queryresult"]["pods"][0]["subpods"][0]["plaintext"]
							print("Response 2", resp2)
							await message.channel.send(resp2)
							await message.channel.send(data["queryresult"]["pods"][0]["subpods"][1]["img"]["src"])

				except Exception as err:
					print(err)

      # If indicated to search for information
			elif any(word in msg.lower() for word in searchIndicator):
				try:
					textToUse = removeIndicators(userText, calculateIndicator)
					inputVal = textToUse.replace("+", "%2B")
					inputVal = inputVal.replace(" ","+")
					wolfUrl = "https://api.wolframalpha.com/v2/query?input=" + inputVal +"&format=plaintext&output=JSON&appid=" + WolframAppId
					print(wolfUrl)
					with urllib.request.urlopen(wolfUrl) as url:
						data = json.loads(url.read().decode())
						if data["queryresult"]:
							response = data["queryresult"]["pods"][1]["subpods"][0]["plaintext"]

				except Exception as err:
					print(err)

      # If indicated to uwuify text
			elif any(word in msg.lower() for word in uwuifyIndicators):
				try:
					response = owoify(removeIndicators(userText, uwuifyIndicators))
				except Exception as err:
					print(err)

      # If indicated to receive help indications
			elif any(word in msg.lower() for word in helpindicators):
				cmd = help()
				await message.author.send(cmd)

				if not isDM:
					response = message.author.name + ", check your DM's bro"
				else:
					response = "Hope this helps"

      # If indicated to search for a random quote
			elif any(word in msg.lower() for word in inspireIndicator):
				response = quote_search.get_quote()

      # Else, search Google for a response
			else:
				try:
          # First query type tries to find if Google has
          # a system to find resources
					response = google_search.chatbot_query(userText)
					print(response)
				except:
          # If not, try to find our own resource
					response = google_search.chatbot_query2(userText)
			await message.channel.send(response)

		except:
      # Soon gonna add a small-talk AI bot here, if all else doesn't work
			await message.channel.send(
			    "I'm sorry, it appears that something wrong has occured. Please try again."
			)

keep_alive()
client.run(discordKey)


import logger
import argparse
import os
import json
import numpy as np; np.random.seed(0)

def main(args):
    render = args.render
    if not render:
        import matplotlib
        matplotlib.use('Agg')
        import matplotlib.pyplot as plt
    from envs import DoubleIntegratorEnv, MountainCarEnv, CartPoleEnv, SwingUpEnv
    from utils.utils import TabularPolicy, TabularValueFun
    from part1.tabular_value_iteration import ValueIteration
    from part2.look_ahead_policy import LookAheadPolicy
    from part2.discretize import Discretize
    envs = [DoubleIntegratorEnv(), MountainCarEnv(), CartPoleEnv(), SwingUpEnv()]

    for env in envs:
        env_name = env.__class__.__name__

        if env_name == 'MountainCarEnv':
            state_discretization = 51
        else:
            state_discretization = 21
        exp_dir = os.getcwd() + '/data/part2_d/%s/policy_type%s_mode%s_horizon%s/' % (env_name,
                                                                              args.policy_type,
                                                                              args.mode,
                                                                              args.horizon)
        logger.configure(dir=exp_dir, format_strs=['stdout', 'log', 'csv'])
        args_dict = vars(args)
        args_dict['env'] = env_name
        json.dump(vars(args), open(exp_dir + '/params.json', 'w'), indent=2, sort_keys=True)

        env = Discretize(env,
                         state_discretization=state_discretization,
                         mode=args.mode
                         )
        value_fun = TabularValueFun(env)
        if args.policy_type == 'tabular':
            policy = TabularPolicy(env)
        elif args.policy_type == 'look_ahead':
            policy = LookAheadPolicy(env, value_fun, args.horizon)
        else:
            raise NotImplementedError
        algo = ValueIteration(env,
                              value_fun,
                              policy,
                              render=render,
                              max_itr=args.max_iter,
                              num_rollouts=1,
                              render_itr=5,
                              log_itr=5)
        algo.train()

if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument("--exp_name", "-n", type=str, default='test',
                        help="folder name where the experiment will be saved")
    parser.add_argument("--render", "-r", action='store_true',
                        help="Vizualize the policy and contours when training")
    parser.add_argument("--mode", "-m", type=str, default='linear', choices=['nn', 'linear'],
                        help="Mode of interpolate between discrete points")
    parser.add_argument("--policy_type", "-p", type=str, default='look_ahead', choices=['tabular', 'look_ahead'],
                        help='Type of policy to use. Whether to use look ahead policy or tabular')
    parser.add_argument("--horizon", "-H", type=int, default=1,
                        help='Planning horizon for the look ahead policy')
    parser.add_argument("--max_iter", "-i", type=int, default=150,
                        help='Maximum number of iterations for the value iteration algorithm')
    args = parser.parse_args()
    main(args)


from gensim.models import word2vec
import MeCab
import sys
import re
from collections import Counter

#出題された単語を０番目、それ以降を候補としてリストで渡された場合を想定している

def WrongWord(Question):

	WrongWord_list = []#誤解等のリストの用意
	Word_list = []#分かちがきした単語のリストの用意
	Word_list2 = {}#辞書型で結果を保存するための用意

	#以下、単語じゃなかった場合などに対処するため、分かち書きの処理
	for i in Question:
		parse = MeCab.Tagger().parse(i)
		lines = parse.split('\n')
		items = (re.split('[\t,]', line) for line in lines)

        #分かちがきしたものをリストに保存する
		for item in items:
			word = item[0]
			Word_list.append(word)
			break

	#リストから出題された問題の単語を取り出す
	original = Word_list.pop(0)

	#以下、word2vecを使い、類似した単語を探す処理
	model = word2vec.Word2Vec.load("./wiki.model")

	#出題された単語と渡された各候補の類似度を計算して辞書型として保存する
	for i in Word_list:
		similarity = model.wv.similarity(original,i)
		Word_list2[i] = similarity

	print(Word_list2)#確認用
	#降順にソートしてリストに保存,類似度上位３つをリストで出力する
	num = 0

	for k, v in sorted(Word_list2.items(), key = lambda x:-x[1]):
		WrongWord_list.append(k)
		num += 1
		if num == 3:
			break

	return WrongWord_list


# Lists

def square_list(nums):
    i = 0
    while i < len(nums):
        nums[i] = nums[i] * nums[i]
        i += 1
    return nums

# Return the sum of all the numbers in the list

def sum_list(nums):
    total = 0
    i = 0
    while i < len(nums):
        total += nums[i]
        i += 1
    return total


import pandas as pd
from datetime import datetime

df = pd.read_csv('simple_nyc_green.csv')

count_pickup = {}
year_2013 = datetime.strptime('01-01-13', '%m-%d-%y').date().year

for index, row in df.iterrows():
    dt = datetime.strptime(row['pickup_datetime'], '%m-%d-%y %H:%M:%S').date()
    date = dt.strftime("%m-%d-%y")
    # print(dt)
    c = int(row['passenger_count'])
    # print(c)
    if date in count_pickup:
        count_pickup[date] += c
    else:
        count_pickup[date] = c

# print(count_pickup)

data_lst = []
value_lst = []
for date in count_pickup.keys():
    data_lst.append(date)
    value_lst.append(count_pickup[date])

data = {'Date': data_lst, 'Volumn': value_lst }
df = pd.DataFrame(data)

# def ret(row):
#     return count_pickup[row['Date']]
# df['volumn'] = df.apply(ret, axis=1)
df.to_csv('counts.csv')

# def ct(row):
#     # 08-25-13 03:04:20
#     dt = datetime.strptime(row['pickup_datetime'], '%m-%d-%y %H:%M:%S').date()
#     print(dt)
#     c = int(row['passenger_count'])
#     print(c)
#     if dt in count_pickup:
#         count_pickup[dt] += c
#     else:
#         count_pickup[dt] = c

#data = {"":}
# count = df.apply(ct, axis=1)

# df = pd.DataFrame(count)
# df.to_csv('counts.csv')


# Python解释器会自动检查参数个数
# 内置函数abs()有参数检查，自定义函数my_abs()没有，完善函数定义，只允许整数和浮点数：
def my_abs(x):
   if not isinstance(x, (int, float)):    #函数isinstance(object, classinfo)判断对象object是否为已知类型classinfo
       raise TypeError('bad operand type')    #如满足条件则抛出错误
   if x >= 0:
       return x
   else:
       return -x

# 测试git
# the first change
# the secound change
# the third change
# another change


from PyQt5.QtWidgets import QApplication, QPushButton, QVBoxLayout, QWidget, QMainWindow, QGroupBox, QGridLayout
import datetime

import button_stylesheets
from app import draw

class GUI(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle('GitHub Art')
        self.move(200, 200)
        self.main_widget = QWidget()
        self.main_layout = QVBoxLayout(self.main_widget)
        self.setCentralWidget(self.main_widget)

        self.dates_list = list()
        self.start_day = datetime.datetime(2017, 1, 1, 00, 00)
        day_value = int(self.start_day.strftime('%w'))

        if day_value != 0:
            self.start_day -= datetime.timedelta(days=day_value)

        self.main_layout.addWidget(self.create_grid_layout())

        submit_button = QPushButton('Submit')
        submit_button.clicked.connect(self.get_list_dates)
        self.main_layout.addWidget(submit_button)

        self.show()

    def create_grid_layout(self):
        group_box = QGroupBox("Draw desired graphics here")
        layout = QGridLayout()

        day_count = 0

        for column in range(52):
            for row in range(7):
                date_button = QPushButton(
                    (self.start_day + datetime.timedelta(days=day_count)).strftime('%Y-%m-%d %H:%M:%S')
                )

                date_button.setMinimumSize(15, 15)
                date_button.setMaximumSize(15, 15)
                date_button.setCheckable(True)
                date_button.setStyleSheet(button_stylesheets.UNCHECKED_BUTTON_STYLESHEET)
                date_button.clicked.connect(self.get_button_text)
                layout.addWidget(date_button, row, column)
                day_count += 1

        layout.setSpacing(3)
        group_box.setLayout(layout)
        return group_box

    def get_button_text(self):
        if self.sender().isChecked():
            self.sender().setStyleSheet(button_stylesheets.CHECKED_BUTTON_STYLESHEET)
            self.dates_list.append(self.sender().text())
        else:
            self.sender().setStyleSheet(button_stylesheets.UNCHECKED_BUTTON_STYLESHEET)
            self.dates_list.remove(self.sender().text())

        print(self.sender().text())

    def get_list_dates(self):
        draw(self.dates_list)

if __name__ == '__main__':
    app = QApplication([])
    gui = GUI()
    gui.setFixedSize(gui.size())
    app.exec_()


"""
Read file into texts and calls.
It's ok if you don't understand how to read files.
"""
import csv

with open('texts.csv', 'r') as f:
    reader = csv.reader(f)
    texts = list(reader)

with open('calls.csv', 'r') as f:
    reader = csv.reader(f)
    calls = list(reader)

"""
TASK 4:
The telephone company want to identify numbers that might be doing
telephone marketing. Create a set of possible telemarketers:
these are numbers that make outgoing calls but never send texts,
receive texts or receive incoming calls.

Print a message:
"These numbers could be telemarketers: "
<list of numbers>
The list of numbers should be print out one per line in lexicographic order with no duplicates.
"""

def find_telemarketers(calls, texts):
    '''
    returns the numbers that do not send or
    receive texts
    '''
    outgoing_calls = set()  # O(1)
    incoming_calls_texts = set()  # O(1)
    for call in calls:  # O(n)
        outgoing_calls.add(call[0])  # O(1)
        incoming_calls_texts.add(call[1])  # O(1)
    for text in texts:  # O(n)
        incoming_calls_texts.add(text[0])  # O(1)
        incoming_calls_texts.add(text[1])  # O(1)
    telemarketers = outgoing_calls - incoming_calls_texts  # O(n)
    result = sorted(telemarketers)  # O(n log n)
    return result  # O(1)

'''
Answer
'''

pt = find_telemarketers(calls, texts)
copy = "These numbers could be telemarketers: "
print(copy)
for elem in pt:
    print(elem)


from __future__ import unicode_literals, print_function, division
import argparse
import random
import time
import warnings

import numpy as np
import torch
import torch.nn as nn
from torch import optim

import codenames.supervised.agents as agents
import codenames.supervised.data as data
import codenames.supervised.embeddings as embeddings
import codenames.supervised.util as util

from codenames.supervised.util import printf

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

class TrainedModel:

    def __init__(self, args, board_vocab, board_embed, clue_vocab, clue_embed):
        # Training variables
        self.hidden_size = args.hidden_size
        self.learning_rate = args.learning_rate
        self.step = args.step
        self.loss = 0
        self.batch_size = args.batch_size

        # Game
        self.board_vocab = board_vocab
        self.board_embed = board_embed
        self.clue_vocab = clue_vocab
        self.clue_embed = clue_embed

        # Model
        self.spymaster = None
        self.guesser = None
        self.models = []
        self._create_model()

        # Optimizers
        self.spymaster_optimizer = None
        self.guesser_optimizer = None
        self.optimizers = []
        self._create_optimizers()

        # Persistence
        self.save_path = args.save_path
        if args.load_path:
            self._load_model(args.load_path)

    def train(self):
        for model in self.models:
            model.train()

    def eval(self):
        for model in self.models:
            model.eval()

    def _create_optimizers(self):
        lr = self.learning_rate

        self.spymaster_optimizer = optim.Adam(self.spymaster.parameters(), lr=lr)
        self.guesser_optimizer = optim.Adam(self.guesser.parameters(), lr=lr)

        self.optimizers = [self.spymaster_optimizer, self.guesser_optimizer]

    def _create_model(self):
        hs = self.hidden_size
        self.spymaster = agents.SpyMaster(
            enc_hidden_size=hs,
            dec_hidden_size=hs,
            board_vocab=self.board_vocab,
            board_embed=self.board_embed,
            clue_vocab=self.clue_vocab,
            clue_embed=self.clue_embed).to(device)
        self.guesser = agents.Guesser(hs, self.board_vocab, self.board_embed, self.clue_vocab, self.clue_embed).to(device)

        self.models = [self.spymaster, self.guesser]

    def _load_model(self, path):
        checkpoint = torch.load(path)

        self.spymaster.load_state_dict(checkpoint['spymaster_state_dict'])
        self.guesser.load_state_dict(checkpoint['guesser_state_dict'])

        self.spymaster_optimizer.load_state_dict(checkpoint['spymaster_optimizer_state_dict'])
        self.guesser_optimizer.load_state_dict(checkpoint['guesser_optimizer_state_dict'])

        self.step = checkpoint['step']
        self.loss = checkpoint['loss']
        self.learning_rate = checkpoint['learning_rate']

    def _save_model(self):
        if not self.save_path:
            warnings.warn("Called save_model() without a set save_path. Not saving.")

        torch.save({
            'step': self.step,
            'spymaster_state_dict': self.spymaster.state_dict(),
            'guesser_state_dict': self.guesser.state_dict(),
            'spymaster_optimizer_state_dict': self.spymaster_optimizer.state_dict(),
            'guesser_optimizer_state_dict': self.guesser_optimizer.state_dict(),
            'loss': self.loss,
            'learning_rate': self.learning_rate
        }, self.save_path)

    @staticmethod
    def _print_turn(team, board, clue_word, intended_output_words, guessed_words):
        printf("---------------------------------------------")
        util.print_board(board)
        printf("Clue word: {} [#{}, team {}]".format(clue_word, len(intended_output_words), team))
        printf("Intention: {}".format(",".join(intended_output_words)))
        printf("Guessed: {}".format(",".join(guessed_words)))
        printf("---------------------------------------------\n")

    def _train_step(self, board_input, criterion, team, att_max_len=data.BOARD_TENSOR_MAX_LENGTH, print_turn=False):

        intended_output_idx, clue_word, team_word_mask = self.spymaster.train_step(board_input, team, att_max_len)
        intended_output_idx_tensor = torch.tensor(intended_output_idx, dtype=torch.long, device=device)
        loss, guessed_card_idx = self.guesser.train_step(board_input, clue_word, intended_output_idx_tensor, criterion,
                                                         team_word_mask)
        loss.backward()

        self.spymaster_optimizer.step()
        self.guesser_optimizer.step()

        board = [(self.board_vocab.idx_to_word[idx], team) for idx, team in board_input]
        board_words = [word for word, _ in board]
        intended_output_words = set(board_words[idx] for idx in intended_output_idx)
        guessed_words = [board_words[idx] for idx in guessed_card_idx]
        if print_turn:
            TrainedModel._print_turn(team, board, clue_word, intended_output_words, guessed_words)

        return loss.item() / len(intended_output_idx), intended_output_words, guessed_words

    @staticmethod
    def _word_stats(intended, guessed):
        intended = set(intended)
        guessed = set(guessed)

        eos = '<EOS>'
        if eos in intended:
            intended.remove(eos)
        if eos in guessed:
            guessed.remove(eos)

        tp = len(intended & guessed)
        fn = len(intended - guessed)
        fp = len(guessed - intended)
        return tp, fp, fn

    @staticmethod
    def _f1_score(scores, eps=1e-8):
        tp, fp, fn = scores
        precision = tp / (tp + fp + eps)
        recall = tp / (tp + fn + eps)
        f1_score = 2 * precision * recall / (precision + recall + eps)
        return f1_score

    def train_steps(self, n_steps, print_every=1, plot_every=1, save_every=0, print_turn_every=0):
        assert save_every >= 0
        start = time.time()
        plot_losses = []
        plot_f1_scores = []
        print_loss_total = 0  # Reset every print_every
        plot_loss_total = 0  # Reset every plot_every
        print_word_stats_total = np.array((0, 0, 0))
        plot_word_stats_total = np.array((0, 0, 0))

        data.generate_board(self.board_vocab)
        criterion = nn.NLLLoss()

        start_step = self.step + 1
        for step in range(start_step, start_step + n_steps + 1):
            board = data.generate_board(self.board_vocab)
            training_input = data.tensors_from_board(self.board_vocab, board, device)

            # Choose team
            team = data.TEAM_IDX['BLUE'] if random.random() < 0.5 else data.TEAM_IDX['RED']

            print_turn = print_turn_every and (step % print_turn_every == 0)
            self.loss, intended, guessed = self._train_step(training_input, criterion, team, print_turn=print_turn)
            print_loss_total += self.loss
            plot_loss_total += self.loss
            cur_word_stats = TrainedModel._word_stats(intended, guessed)
            print_word_stats_total += cur_word_stats
            plot_word_stats_total += cur_word_stats

            if step % print_every == 0:
                print_loss_avg = print_loss_total / print_every
                print_loss_total = 0
                printf('%s (%d %d%%) %.4f' % (util.time_since(start, step / n_steps), step, step / n_steps * 100, print_loss_avg))

                printf("F1 score: {} ({})".format(TrainedModel._f1_score(print_word_stats_total), print_word_stats_total))
                print_word_stats_total = np.array((0, 0, 0))

            if step % plot_every == 0:
                plot_loss_avg = plot_loss_total / plot_every
                plot_losses.append((step, plot_loss_avg))
                plot_loss_total = 0
                util.show_plot(plot_losses, fname='data_out/loss.png')

                plot_f1_scores.append((step, TrainedModel._f1_score(plot_word_stats_total)))
                plot_word_stats_total = np.array((0, 0, 0))
                util.show_plot(plot_f1_scores, fname='data_out/f1_scores.png')

            if save_every and step % save_every == 0:
                self._save_model()

            self.step = step

def main():
    parser = argparse.ArgumentParser()
    parser.add_argument("--board_words", help="Path to file with board words. Each word on a separate line.")
    parser.add_argument("--clue_words", help="Path to file with clue words. Each word on a separate line.")
    parser.add_argument("--embedding_path", default=None, help="Path to pre-trained embeddings.")
    parser.add_argument("--num_iterations", default=50000, type=int, help="Number of iterations to run training for.")
    parser.add_argument("--print_every", default=500, type=int, help="After how many iterations to log.")
    parser.add_argument("--save_every", default=500, type=int, help="After how many iterations to save the model.")
    parser.add_argument("--print_turn_every", default=0, type=int, help="After how many iterations to print the board.")
    parser.add_argument("--learning_rate", default=1e-3, type=float, help="Learning rate of the optimizers.")
    parser.add_argument("--load_path", default=None, help="Load model from path.")
    parser.add_argument("--save_path", default="./data_out/model.pt", help="Save model to path.")
    parser.add_argument("--eval", default=False, type=bool, help="Eval mode.")
    parser.add_argument("--hidden_size", default=10, type=int, help="Hidden size variable in the model.")
    parser.add_argument("--step", default=0, type=int, help="Step to start counting from.")
    parser.add_argument("--batch_size", default=1, type=int, help="Batch size.")  # TODO(oskopek): Support other batch sizes.
    args = parser.parse_args()
    assert args.board_words and args.clue_words

    # TODO(vsomnath): Add the part to get embedded tokens
    # TODO(oskopek): Enable pre-trained embeddings.
    board_vocab = data.Vocab.load_from_file(args.board_words)
    clue_vocab = data.Vocab.load_from_file(args.clue_words)
    board_embed, _ = embeddings.setup_embeddings({
        'embedding_path': args.embedding_path,
        'num_embeddings': len(board_vocab),
        'embedding_dim': args.hidden_size,
        'device': device,
    })
    clue_embed, _ = embeddings.setup_embeddings({
        'embedding_path': args.embedding_path,
        'num_embeddings': len(clue_vocab),
        'embedding_dim': args.hidden_size,
        'device': device,
    })

    model = TrainedModel(args, board_vocab, board_embed, clue_vocab, clue_embed)
    if args.eval:
        printf("Evaluating...")
        model.eval()
        # TODO(oskopek): Eval.
    else:
        printf("Training...")
        model.train()
        model.train_steps(
            args.num_iterations,
            print_every=args.print_every,
            save_every=args.save_every,
            plot_every=args.print_every,
            print_turn_every=args.print_turn_every)

if __name__ == '__main__':
    main()


import numpy as np
import matplotlib.pylab as plt

class Activation_function:

	def __init__(self):
		self.x = np.arange(-5.0,5.0,0.1)

	def step_function(self):
		y = np.where(self.x > 0, 1, 0)
		plt.plot(self.x, y)
		plt.ylim(-0.1, 1.1)
		plt.title("Step Function")
		plt.show()

	def sigmoid_function(self):
		y = 1 / (1 + np.exp(-self.x))
		plt.plot(self.x, y)
		plt.ylim(-0.1, 1.1)
		plt.title("Sigmoid Function")
		plt.show()

	def relu_function(self):
		y = np.where(self.x < 0, 0, self.x)
		plt.plot(self.x, y)
		plt.ylim(-0.1, 6)
		plt.title("ReLU Function")
		plt.show()


#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Author  : Mike
# @Contact : 597290963@qq.com
# @Time    : 2021/8/28 16:32
# @File    : MergeTwoLists.py

# Definition for singly-linked list.

class ListNode:

    def __init__(self, val=0, next=None):
        self.val = val
        self.next = next

class Solution:
    def mergeTwoLists(self, l1: ListNode, l2: ListNode) -> ListNode:
        new_node = ListNode()

        cur_node = new_node
        while l1 and l2:
            if l1.val <= l2.val:
                cur_node.next = l1
                l1 = l1.next
            else:
                cur_node.next = l2
                l2 = l2.next
            cur_node = cur_node.next

        while l1:
            cur_node.next = l1
            l1 = l1.next
            cur_node = cur_node.next

        while l2:
            cur_node.next = l2
            l2 = l2.next
            cur_node = cur_node.next

        return new_node.next

    def mergeTwoLists1(self, l1: ListNode, l2: ListNode) -> ListNode:
        """
        优化遍历
        :param l1:
        :param l2:
        :return:
        """
        dummy_node = ListNode()
        pre_node = dummy_node

        while l1 or l2:
            if l1 and l2:
                if l1.val <= l2.val:
                    pre_node.next = l1
                    l1 = l1.next
                else:
                    pre_node.next = l2
                    l2 = l2.next
            elif l1:
                pre_node.next = l1
                l1 = l1.next
            else:
                pre_node.next = l2
                l2 = l2.next

            pre_node = pre_node.next

        return dummy_node.next

    def mergeTwoLists2(self, l1: ListNode, l2: ListNode) -> ListNode:
        """
        迭代写法
        :param l1:
        :param l2:
        :return:
        """
        if not l1:
            return l2

        if not l2:
            return l1

        if l1.val <= l2.val:
            l1.next = self.mergeTwoLists2(l1.next, l2)
            return l1
        else:
            l2.next = self.mergeTwoLists2(l1, l2.next)
            return l2


# encoding: utf-8
import unittest

import responses

from jenkinsx import Jenkins
from jenkinsx.exceptions import ItemNotFoundError, \
    AuthenticationError, BadRequestError
from jenkinsx.item import snake
from jenkinsx.job import Folder
from jenkinsx.user import ApiToken
from .help import mock_get, load_test_json, \
    mock_post, remove_get, replace_get, JENKINS_URL

# logging.basicConfig(level=logging.DEBUG)
class TestJenkins(unittest.TestCase):

    @classmethod
    def setUpClass(cls):
        cls.jenkins_json = load_test_json('jenkins/jenkins.json')
        cls.folder_json = load_test_json('job/folder.json')
        cls.crumb = load_test_json('jenkins/crumb.json')

    def setUp(self):
        mock_get(f'{JENKINS_URL}crumbIssuer/api/json',
                 json=self.crumb)
        mock_get(f'{JENKINS_URL}api/json', json=self.jenkins_json)
        mock_get(f'{JENKINS_URL}job/Level1_Folder1/api/json',
                 json=self.folder_json)
        self.jx = Jenkins(f'{JENKINS_URL}', auth=('admin', 'admin'))

    @responses.activate
    def test_init_with_invalid_auth(self):
        remove_get(f'{JENKINS_URL}crumbIssuer/api/json')
        mock_get(f'{JENKINS_URL}crumbIssuer/api/json', status=401)
        jx = Jenkins(f'{JENKINS_URL}', auth=('admin', 'admin'))
        with self.assertRaises(AuthenticationError):
            jx.api_json()

    def test_init_with_password(self):
        self.assertIsInstance(self.jx, Jenkins)
        self.assertEqual(str(self.jx), f'<Jenkins: {JENKINS_URL}>')
        self.assertEqual(self.jx.url, JENKINS_URL)
        self.assertIsNone(self.jx._crumb)
        self.assertIsNone(self.jx._token)

    @responses.activate
    def test_init_with_token(self):
        data = {'tokenName': 'mock-token-name',
                'tokenValue': 'mock-token-value',
                'tokenUuid': 'mock-token-uuid'}
        token = ApiToken(data['tokenName'],
                         data['tokenUuid'], data['tokenValue'])
        mock_post(f'{JENKINS_URL}user/admin/'
                  'descriptorByName/jenkins.security.ApiTokenProperty/'
                  'generateNewToken?newTokenName=',
                  json={'data': data})
        mock_get(JENKINS_URL)
        with unittest.mock.patch('weakref.finalize') as mock_fin:
            mock_fin.side_effect = lambda *args: None
            jx = Jenkins(JENKINS_URL,
                         auth=('admin', 'admin'), token=True)
        self.assertTrue(jx.exists())
        self.assertEqual(jx.url, JENKINS_URL)
        self.assertEqual(jx._crumb, self.crumb)
        self.assertEqual(jx._token, token)

    @responses.activate
    def test_dynamic_attributes(self):
        dynamic_attrs = {snake(k): v for k, v in self.jenkins_json.items()
                         if isinstance(v, (int, str, bool))}
        self.assertEqual(sorted(self.jx.attrs),
                         sorted(dynamic_attrs.keys()))
        for key, value in dynamic_attrs.items():
            with self.subTest(value=value):
                self.assertEqual(getattr(self.jx, key), value)

    @responses.activate
    def test_get_job_when_not_found(self):
        not_found = self.jx.get_job('Level1_Folder1/notfound')
        self.assertIsNone(not_found)

    @responses.activate
    def test_get_job(self):
        level1_folder1 = self.jx.get_job('Level1_Folder1')
        self.assertEqual(self.jx._crumb, self.crumb)
        self.assertIsNone(self.jx._token)
        self.assertIsInstance(level1_folder1, Folder)
        self.assertEqual(str(level1_folder1),
                         f'<Folder: {JENKINS_URL}job/Level1_Folder1/>')
        level2_folder1 = self.jx.get_job('Level1_Folder1/Level2_Folder1')
        self.assertIsInstance(level2_folder1, Folder)
        self.assertEqual(str(level2_folder1),
                         f'<Folder: {JENKINS_URL}job/Level1_Folder1/'
                         'job/Level2_Folder1/>')

    @responses.activate
    def test_iter_jobs(self):
        replace_get(f'{JENKINS_URL}api/json',
                    json=load_test_json('jenkins/jenkins_all_jobs.json'))
        jobs = list(self.jx.iter_jobs())
        self.assertEqual(len(jobs), 6)

    @responses.activate
    def test_create_job_when_exists(self):
        mock_post(
            f'{JENKINS_URL}job/Level1_Folder1/createItem',
            headers={
                'X-Error': "A job already exists with"
                " the name 'Level2_Folder1'"},
            status=400)
        with self.assertRaises(BadRequestError):
            self.jx.create_job('Level1_Folder1/Level2_Folder1', '')

    @responses.activate
    def test_create_job_when_name_illegal(self):
        mock_post(
            f'{JENKINS_URL}job/Level1_Folder1/createItem',
            headers={'X-Error': '@  is an unsafe character'},
            status=400)
        with self.assertRaisesRegex(BadRequestError,
                                    '@  is an unsafe character'):
            self.jx.create_job('Level1_Folder1/Level2@new', '')

    @responses.activate
    def test_create_job(self):
        mock_post(
            f'{JENKINS_URL}job/Level1_Folder1/createItem?name=Levevl2_new',
            match_querystring=True)
        self.jx.create_job('Level1_Folder1/Levevl2_new', '')

    @responses.activate
    def test_delete_job(self):
        mock_post(f'{JENKINS_URL}job/Level1_Folder1/'
                  'job/Level2_Folder1/doDelete',
                  match_querystring=True)
        self.jx.delete_job('Level1_Folder1/Level2_Folder1')

    @responses.activate
    def test_build_job_when_not_found(self):
        with self.assertRaisesRegex(ItemNotFoundError,
                                    'No such job: '
                                    'Level1_Folder1/Level2_notFound'):
            self.jx.build_job('Level1_Folder1/Level2_notFound')

    @responses.activate
    def test_build_job_when_job_is_unbuildable(self):
        with self.assertRaisesRegex(AttributeError,
                                    "'Folder' object has no attribute 'build'"):
            self.jx.build_job('Level1_Folder1')

    def test_url2full_name(self):
        with self.assertRaises(ValueError):
            self.jx.url2path('http://0.0.0.1/job/folder1/')
        full_name = self.jx.url2path(f'{JENKINS_URL}job/job/')
        self.assertEqual(full_name, '/job/')
        full_name = self.jx.url2path(
            f'{JENKINS_URL}job/job/job/job/')
        self.assertEqual(full_name, '/job/job/')
        full_name = self.jx.url2path(f'{JENKINS_URL}job/job/job/job')
        self.assertEqual(full_name, '/job/job')

    def test_full_name2url(self):
        self.assertEqual(self.jx.path2url(''), self.jx.url)
        for name in ['/job/', 'job/', '/job', 'job']:
            with self.subTest(name=name):
                self.assertEqual(self.jx.path2url(name),
                                 f'{JENKINS_URL}job/job/')
        for name in ['/job/job/', 'job/job/', '/job/job', 'job/job']:
            with self.subTest(name=name):
                self.assertEqual(self.jx.path2url(name),
                                 f'{JENKINS_URL}job/job/job/job/')

    @responses.activate
    def test_api_json(self):
        json = self.jx.api_json()
        self.assertEqual(json, self.jenkins_json)

    @responses.activate
    def test_exists(self):
        for status in [401, 403]:
            remove_get(JENKINS_URL)
            mock_get(JENKINS_URL, status=status)
            with self.subTest(status=status):
                self.assertTrue(self.jx.exists())

        for status in [404, 503]:
            remove_get(JENKINS_URL)
            mock_get(JENKINS_URL, status=status)
            with self.subTest(status=status):
                self.assertFalse(self.jx.exists())

    @responses.activate
    def test_handle_req(self):
        json = self.jx.handle_req('GET', 'api/json').json()
        self.assertEqual(json, self.jenkins_json)


import pandas as pd

from pathlib import Path
import csv
import numpy as np
import matplotlib.pyplot as plt

results = [Path('result_batch_1').glob('*/'),
           Path('result_batch_2').glob('*/'),
           Path('result_batch_3').glob('*/'),
           Path('result_batch_4').glob('*/'),
           Path('result_batch_5').glob('*/')]
batch_results = []
for pathlist in results:
    batch_result = []
    for path in pathlist:
        path_in_str = str(path)

        df = pd.read_csv(path_in_str, sep=' |:|<|>|', engine='python', usecols=[1,4,5,6], header=None)
        # df = pd.read_csv(path_in_str, sep=' |:|<|>|\\\\|', engine='python', usecols=[1,6,7,8], header=None)
        tracker_name =  df[df.columns[0]][0]
        dataset_name = df[df.columns[1]]
        tracker_fps = df[df.columns[2]]
        tracker_iou = df[df.columns[3]]
        avg_tracker_time = 1/ tracker_fps.sum()

        avg_tracker_iou = tracker_iou.sum() / 95
        batch_result.append(list([tracker_name , str(avg_tracker_time) , str(avg_tracker_iou)]))
    batch_results.append(batch_result)

batch_results_df = pd.DataFrame()
counter = 0
for batch_result in batch_results:
    if batch_results_df.empty == True:

        batch_results_df = pd.DataFrame(batch_result)
        batch_results_df.columns = [str('name'), str('f_sec_' + str(counter)), str('iou_' + str(counter))]
    else:

        batch_result_df = pd.DataFrame(batch_result)
        batch_result_df.columns = [str('name'), str('f_sec_' + str(counter)), str('iou_' + str(counter))]
        batch_results_df = pd.concat([batch_results_df, batch_result_df], axis=1, sort=False)
    counter = counter + 1

iou_df = batch_results_df[['iou_0','iou_1','iou_2','iou_3','iou_4']].copy().astype(float)
f_sec_df = batch_results_df[['f_sec_0','f_sec_1','f_sec_2','f_sec_3','f_sec_4']].copy().astype(float)

iou_mean = iou_df[['iou_0','iou_1','iou_2','iou_3','iou_4']].mean(axis=1)
f_sec_mean = f_sec_df[['f_sec_0','f_sec_1','f_sec_2','f_sec_3','f_sec_4']].mean(axis=1)

iou_std = iou_df[['iou_0','iou_1','iou_2','iou_3','iou_4']].std(axis=1)
f_sec_std = f_sec_df[['f_sec_0','f_sec_1','f_sec_2','f_sec_3','f_sec_4']].std(axis=1)

print(iou_mean)
print(f_sec_mean)
print(iou_std)
print(f_sec_std)

# plot error bars for IOU
trackers = ['Boosting', 'CSRT', 'KCF', 'MedianFlow', 'MIL', 'MOSSE', 'TLD']
IOU_x_pos = np.arange(len(trackers))
IOU = list(iou_mean)
IOU_error = list(iou_std)
fig, ax = plt.subplots(figsize=(10,10))

ax.bar(IOU_x_pos, IOU, yerr=IOU_error, align='center', alpha=0.5, ecolor='black', capsize=10)
ax.set_ylabel('Intersection of Union')
ax.set_xticks(IOU_x_pos)
ax.set_xticklabels(trackers)
ax.set_title('IOU performance for Trackers')
ax.yaxis.grid(True)

# Save the figure and show
plt.tight_layout()
plt.show()

f_sec_x_pos = np.arange(len(trackers))
f_sec = list(f_sec_mean)
f_sec_error = list(f_sec_std)
fig, ax = plt.subplots(figsize=(10,10))

ax.bar(f_sec_x_pos, f_sec, yerr=f_sec_error, align='center', alpha=0.5, ecolor='black', capsize=10)
ax.set_ylabel('Frame Time (s)')
ax.set_xticks(f_sec_x_pos)
ax.set_xticklabels(trackers)
ax.set_title('Frame Time For Trackers')
ax.yaxis.grid(True)

# Save the figure and show
plt.tight_layout()
plt.show()


#!/usr/bin/env python
"""
Watches pending jobs and starts or creates EC2 instances if required
"""
import re
import time
import random
from collections import defaultdict

try:
    import simplejson as json
    assert json
except ImportError:
    import json

import boto.ec2
from boto.exception import BotoServerError
from boto.ec2.networkinterface import NetworkInterfaceCollection, \
    NetworkInterfaceSpecification
from boto.ec2.blockdevicemapping import BlockDeviceMapping, BlockDeviceType
import sqlalchemy as sa
from sqlalchemy.engine.reflection import Inspector

import requests
import os
import logging
from bid import decide as get_spot_choices

log = logging.getLogger()

def find_pending(db):
    inspector = Inspector(db)
    # Newer buildbot has a "buildrequest_claims" table
    if "buildrequest_claims" in inspector.get_table_names():
        query = sa.text("""
        SELECT buildername, id FROM
               buildrequests WHERE
               complete=0 AND
               submitted_at > :yesterday AND
               submitted_at < :toonew AND
               (select count(brid) from buildrequest_claims
                       where brid=id) = 0""")
    # Older buildbot doesn't
    else:
        query = sa.text("""
        SELECT buildername, id FROM
               buildrequests WHERE
               complete=0 AND
               claimed_at=0 AND
               submitted_at > :yesterday AND
               submitted_at < :toonew""")

    result = db.execute(
        query,
        yesterday=time.time() - 86400,
        toonew=time.time() - 10
    )
    retval = result.fetchall()
    return retval

def find_retries(db, brid):
    """Returns the number of previous builds for this build request id"""
    q = sa.text("SELECT count(*) from builds where brid=:brid")
    return db.execute(q, brid=brid).fetchone()[0]

# Used by aws_connect_to_region to cache connection objects per region
_aws_cached_connections = {}

def aws_connect_to_region(region, secrets):
    """Connect to an EC2 region. Caches connection objects"""
    if region in _aws_cached_connections:
        return _aws_cached_connections[region]
    conn = boto.ec2.connect_to_region(
        region,
        aws_access_key_id=secrets['aws_access_key_id'],
        aws_secret_access_key=secrets['aws_secret_access_key']
    )
    _aws_cached_connections[region] = conn
    return conn

def aws_get_spot_requests(region, secrets, moz_instance_type):
    """retruns a list of all open and active spot requests"""
    conn = aws_connect_to_region(region, secrets)
    filters = {"tag:moz-type": moz_instance_type}
    req = conn.get_all_spot_instance_requests(filters=filters)
    return [r for r in req if r.state in ("open", "active")]

def aws_get_all_instances(regions, secrets):
    """
    Returns a list of all instances in the given regions
    """
    log.debug("fetching all instances for %s", regions)
    retval = []
    for region in regions:
        conn = aws_connect_to_region(region, secrets)
        reservations = conn.get_all_instances()
        for r in reservations:
            retval.extend(r.instances)
    return retval

def aws_filter_instances(all_instances, state=None, tags=None):
    retval = []
    for i in all_instances:
        matched = True
        if state and i.state != state:
            matched = False
            continue
        if tags:
            for k, v in tags.items():
                if i.tags.get(k) != v:
                    matched = False
                    continue
        if i.tags.get("moz-loaned-to"):
            # Skip loaned instances
            matched = False
            continue
        if matched:
            retval.append(i)
    return retval

def aws_get_reservations(regions, secrets):
    """
    Return a mapping of (availability zone, ec2 instance type) -> count
    """
    log.debug("getting reservations for %s", regions)
    retval = {}
    for region in regions:
        conn = aws_connect_to_region(region, secrets)
        reservations = conn.get_all_reserved_instances(filters={
            'state': 'active',
        })
        for r in reservations:
            az = r.availability_zone
            ec2_instance_type = r.instance_type
            if (az, ec2_instance_type) not in retval:
                retval[az, ec2_instance_type] = 0
            retval[az, ec2_instance_type] += r.instance_count
    return retval

def aws_filter_reservations(reservations, running_instances):
    """
    Filters reservations by reducing the count for reservations by the number
    of running instances of the appropriate type. Removes entries for
    reservations that are fully used.

    Modifies reservations in place
    """
    # Subtract running instances from our reservations
    for i in running_instances:
        if (i.placement, i.instance_type) in reservations:
            reservations[i.placement, i.instance_type] -= 1
    log.debug("available reservations: %s", reservations)

    # Remove reservations that are used up
    for k, count in reservations.items():
        if count <= 0:
            log.debug("all reservations for %s are used; removing", k)
            del reservations[k]

def aws_resume_instances(moz_instance_type, start_count, regions, secrets,
                         region_priorities, instance_type_changes, dryrun):
    """Resume up to `start_count` stopped instances of the given type in the
    given regions"""
    # Fetch all our instance information
    all_instances = aws_get_all_instances(regions, secrets)
    # We'll filter by these tags in general
    tags = {'moz-state': 'ready', 'moz-type': moz_instance_type}

    # If our instance config specifies a maximum number of running instances,
    # apply that now. This may mean that we reduce start_count, or return early
    # if we're already running >= max_running
    instance_config = json.load(open("configs/%s" % moz_instance_type))
    max_running = instance_config.get('max_running')
    if max_running is not None:
        running = len(aws_filter_instances(all_instances, state='running',
                                           tags=tags))
        if running + start_count > max_running:
            start_count = max_running - running
            if start_count <= 0:
                log.info("max_running limit hit (%s - %i)",
                         moz_instance_type, max_running)
                return 0

    # Get our list of stopped instances, sorted by region priority, then
    # launch_time. Higher region priorities mean we'll prefer to start those
    # instances first
    def _instance_sort_key(i):
        # Region is (usually?) the placement with the last character dropped
        r = i.placement[:-1]
        if r not in region_priorities:
            log.warning("No region priority for %s; az=%s; "
                        "region_priorities=%s", r, i.placement,
                        region_priorities)
        p = region_priorities.get(r, 0)
        return (p, i.launch_time)
    stopped_instances = list(reversed(sorted(
        aws_filter_instances(all_instances, state='stopped', tags=tags),
        key=_instance_sort_key)))
    log.debug("stopped_instances: %s", stopped_instances)

    # Get our current reservations
    reservations = aws_get_reservations(regions, secrets)
    log.debug("current reservations: %s", reservations)

    # Get our currently running instances
    running_instances = aws_filter_instances(all_instances, state='running')

    # Filter the reservations
    aws_filter_reservations(reservations, running_instances)
    log.debug("filtered reservations: %s", reservations)

    # List of (instance, is_reserved) tuples
    to_start = []

    # While we still have reservations, start instances that can use those
    # reservations first
    for i in stopped_instances[:]:
        k = (i.placement, i.instance_type)
        if k not in reservations:
            continue
        stopped_instances.remove(i)
        to_start.append((i, True))
        reservations[k] -= 1
        if reservations[k] <= 0:
            del reservations[k]

    # Add the rest of the stopped instances
    to_start.extend((i, False) for i in stopped_instances)

    # Limit ourselves to start only start_count instances
    log.debug("starting up to %i instances", start_count)
    log.debug("to_start: %s", to_start)

    started = 0
    for i, is_reserved in to_start:
        r = "reserved instance" if is_reserved else "instance"
        if not dryrun:
            log.debug("%s - %s - starting %s", i.placement, i.tags['Name'], r)
            try:
                # Check if the instance type needs to be changed. See
                # watch_pending.cfg.example's instance_type_changes entry.
                new_instance_type = instance_type_changes.get(
                    i.region.name, {}).get(moz_instance_type)
                if new_instance_type and new_instance_type != i.instance_type:
                    log.warn("Changing %s (%s) instance type from %s to %s",
                             i.tags['Name'], i.id, i.instance_type,
                             new_instance_type)
                    i.connection.modify_instance_attribute(
                        i.id, "instanceType", new_instance_type)
                i.start()
                started += 1
            except BotoServerError:
                log.debug("Cannot start %s", i.tags['Name'], exc_info=True)
                log.warning("Cannot start %s", i.tags['Name'])
        else:
            log.info("%s - %s - would start %s", i.placement, i.tags['Name'],
                     r)
            started += 1
        if started >= start_count:
            log.debug("Started %s instaces, breaking early", started)
            break

    return started

def request_spot_instances(moz_instance_type, start_count, regions, secrets,
                           region_priorities, spot_config, dryrun,
                           cached_cert_dir):
    started = 0
    spot_rules = spot_config.get("rules", {}).get(moz_instance_type)
    if not spot_rules:
        log.warn("No spot rules found for %s", moz_instance_type)
        return 0

    instance_config = json.load(open("configs/%s" % moz_instance_type))
    connections = []
    for region in regions:
        connections.append(aws_connect_to_region(region, secrets))
    spot_choices = get_spot_choices(connections, spot_rules)
    if not spot_choices:
        log.warn("No spot choices for %s", moz_instance_type)
        return 0

    to_start = {}
    for region in regions:
        # Check if spots are enabled in this region for this type
        region_limit = spot_config.get("limits", {}).get(region, {}).get(
            moz_instance_type)
        if not region_limit:
            log.debug("No spot limits defined for %s in %s, skipping...",
                      moz_instance_type, region)
            continue

        # check the limits
        active_count = len(aws_get_spot_requests(
            region=region, secrets=secrets,
            moz_instance_type=moz_instance_type))
        can_be_started = region_limit - active_count
        if can_be_started < 1:
            log.debug("Not starting. Active spot request count in %s region "
                      "hit limit of %s. Active count: %s", region,
                      region_limit, active_count)
            continue

        to_be_started = min(can_be_started, start_count - started)
        ami = get_ami(region=region, secrets=secrets,
                      moz_instance_type=moz_instance_type)
        to_start[region] = {"ami": ami, "instances": to_be_started}

    if not to_start:
        log.debug("Nothing to start for %s", moz_instance_type)
        return 0

    for choice in spot_choices:
        region = choice.region
        if region not in to_start:
            log.debug("Skipping %s for %s", choice, region)
            continue
        need = min(to_start[region]["instances"], start_count - started)
        log.debug("Need %s of %s in %s", need, moz_instance_type,
                  choice.availability_zone)

        log.debug("Using %s", choice)
        launched = do_request_spot_instances(
            amount=need,
            region=region, secrets=secrets,
            moz_instance_type=moz_instance_type,
            ami=to_start[region]["ami"],
            instance_config=instance_config, dryrun=dryrun,
            cached_cert_dir=cached_cert_dir,
            spot_choice=choice)
        started += launched

        if started >= start_count:
            break

    return started

def get_puppet_certs(ip, secrets, cached_cert_dir):
    """ reuse or generate certificates"""
    cert_file = os.path.join(cached_cert_dir, ip)
    if os.path.exists(cert_file):
        return open(cert_file).read()

    puppet_server = secrets["getcert_server"]
    url = "https://%s/deploy/getcert.cgi?%s" % (puppet_server, ip)
    auth = (secrets["deploy_username"], secrets["deploy_password"])
    req = requests.get(url, auth=auth, verify=False)
    req.raise_for_status()
    cert_data = req.content
    with open(cert_file, "wb") as f:
        f.write(cert_data)
    return cert_data

def do_request_spot_instances(amount, region, secrets, moz_instance_type, ami,
                              instance_config, cached_cert_dir, spot_choice,
                              dryrun):
    started = 0
    for _ in range(amount):
        try:
            do_request_spot_instance(
                region=region, secrets=secrets,
                moz_instance_type=moz_instance_type,
                price=spot_choice.bid_price,
                availability_zone=spot_choice.availability_zone,
                ami=ami, instance_config=instance_config,
                cached_cert_dir=cached_cert_dir,
                instance_type=spot_choice.instance_type, dryrun=dryrun)
            started += 1
        except (RuntimeError):
            log.warn("Cannot start", exc_info=True)
    return started

def do_request_spot_instance(region, secrets, moz_instance_type, price, ami,
                             instance_config, cached_cert_dir, instance_type,
                             availability_zone, dryrun):
    conn = aws_connect_to_region(region, secrets)
    interface = get_available_interface(
        conn=conn, moz_instance_type=moz_instance_type,
        availability_zone=availability_zone)
    if not interface:
        raise RuntimeError("No free network interfaces left in %s" % region)

    # TODO: check DNS
    fqdn = interface.tags.get("FQDN")
    if not fqdn:
        raise RuntimeError("Skipping %s without FQDN" % interface)

    log.debug("Spot request for %s (%s)", fqdn, price)

    if dryrun:
        log.info("Dry run. skipping")
        return

    spec = NetworkInterfaceSpecification(
        network_interface_id=interface.id)
    nc = NetworkInterfaceCollection(spec)
    ip = interface.private_ip_address
    certs = get_puppet_certs(ip, secrets, cached_cert_dir)
    user_data = """
FQDN="%(fqdn)s"
cd /var/lib/puppet/ssl || exit 1
%(certs)s
cd -
""" % dict(fqdn=fqdn, certs=certs)
    if instance_config[region].get("lvm"):
        user_data += """
mkdir -p /etc/lvm-init/
cat <<EOF > /etc/lvm-init/lvm-init.json
%s
EOF
/sbin/lvm-init
""" % json.dumps(instance_config[region])

    bdm = BlockDeviceMapping()
    for device, device_info in instance_config[region]['device_map'].items():
        bd = BlockDeviceType()
        if device_info.get('size'):
            bd.size = device_info['size']
        if ami.root_device_name == device:
            ami_size = ami.block_device_mapping[device].size
            if ami.virtualization_type == "hvm":
                # Overwrite root device size for HVM instances, since they
                # cannot be resized online
                bd.size = ami_size
            elif device_info.get('size'):
                # make sure that size is enough for this AMI
                assert ami_size <= device_info['size'], \
                    "Instance root device size cannot be smaller than AMI " \
                    "root device"
        if device_info.get("delete_on_termination") is not False:
            bd.delete_on_termination = True
        if device_info.get("ephemeral_name"):
            bd.ephemeral_name = device_info["ephemeral_name"]

        bdm[device] = bd

    sir = conn.request_spot_instances(
        price=str(price),
        image_id=ami.id,
        count=1,
        instance_type=instance_type,
        key_name=instance_config[region]["ssh_key"],
        user_data=user_data,
        block_device_map=bdm,
        network_interfaces=nc,
        instance_profile_name=instance_config[region].get("instance_profile_name"),
    )
    sir[0].add_tag("moz-type", moz_instance_type)

_cached_interfaces = {}

def get_available_interface(conn, moz_instance_type, availability_zone):
    global _cached_interfaces
    if not _cached_interfaces.get(availability_zone):
        _cached_interfaces[availability_zone] = {}
    if _cached_interfaces[availability_zone].get(moz_instance_type) is None:
        filters = {
            "status": "available",
            "tag:moz-type": moz_instance_type,
            "availability-zone": availability_zone,
        }
        avail_ifs = conn.get_all_network_interfaces(filters=filters)
        if avail_ifs:
            random.shuffle(avail_ifs)
        _cached_interfaces[availability_zone][moz_instance_type] = avail_ifs

    log.debug("%s interfaces in %s",
              len(_cached_interfaces[availability_zone][moz_instance_type]),
              availability_zone)
    if _cached_interfaces[availability_zone][moz_instance_type]:
        return _cached_interfaces[availability_zone][moz_instance_type].pop()
    else:
        return None

def get_ami(region, secrets, moz_instance_type):
    conn = aws_connect_to_region(region, secrets)
    avail_amis = conn.get_all_images(
        owners=["self"],
        filters={"tag:moz-type": moz_instance_type})
    last_ami = sorted(avail_amis,
                      key=lambda ami: ami.tags.get("moz-created"))[-1]
    return last_ami

def aws_watch_pending(dburl, regions, secrets, builder_map, region_priorities,
                      spot_config, dryrun, cached_cert_dir,
                      instance_type_changes):
    # First find pending jobs in the db
    db = sa.create_engine(dburl)
    pending = find_pending(db)

    # Mapping of instance types to # of instances we want to creates
    to_create_ondemand = defaultdict(int)
    to_create_spot = defaultdict(int)
    # Then match them to the builder_map
    for pending_buildername, brid in pending:
        for buildername_exp, instance_type in builder_map.items():
            if re.match(buildername_exp, pending_buildername):
                if find_retries(db, brid) == 0:
                    to_create_spot[instance_type] += 1
                else:
                    to_create_ondemand[instance_type] += 1
                break
        else:
            log.debug("%s has pending jobs, but no instance types defined",
                      pending_buildername)

    for instance_type, count in to_create_spot.items():
        log.debug("need %i spot %s", count, instance_type)
        started = request_spot_instances(
            moz_instance_type=instance_type, start_count=count,
            regions=regions, secrets=secrets,
            region_priorities=region_priorities, spot_config=spot_config,
            dryrun=dryrun, cached_cert_dir=cached_cert_dir)
        count -= started
        log.info("%s - started %i spot instances; need %i",
                 instance_type, started, count)

        # Add leftover to ondemand
        to_create_ondemand[instance_type] += count

    for instance_type, count in to_create_ondemand.items():
        log.debug("need %i ondemand %s", count, instance_type)
        if count < 1:
            continue

        # Check for stopped instances in the given regions and start them if
        # there are any
        started = aws_resume_instances(instance_type, count, regions, secrets,
                                       region_priorities,
                                       instance_type_changes, dryrun)
        count -= started
        log.info("%s - started %i instances; need %i",
                 instance_type, started, count)

if __name__ == '__main__':
    import argparse
    parser = argparse.ArgumentParser()
    parser.add_argument("-r", "--region", action="append", dest="regions",
                        required=True)
    parser.add_argument("-k", "--secrets", type=argparse.FileType('r'),
                        required=True)
    parser.add_argument("-c", "--config", type=argparse.FileType('r'),
                        required=True)
    parser.add_argument("-v", "--verbose", action="store_const",
                        dest="loglevel", const=logging.DEBUG,
                        default=logging.INFO)
    parser.add_argument("--cached-cert-dir", default="certs",
                        help="Directory for cached puppet certificates")
    parser.add_argument("-n", "--dryrun", dest="dryrun", action="store_true",
                        help="don't actually do anything")

    args = parser.parse_args()

    logging.basicConfig(level=args.loglevel,
                        format="%(asctime)s - %(message)s")
    logging.getLogger("boto").setLevel(logging.INFO)
    logging.getLogger("requests").setLevel(logging.WARN)

    config = json.load(args.config)
    secrets = json.load(args.secrets)

    aws_watch_pending(
        dburl=secrets['db'],
        regions=args.regions,
        secrets=secrets,
        builder_map=config['buildermap'],
        region_priorities=config['region_priorities'],
        dryrun=args.dryrun,
        spot_config=config.get("spot"),
        cached_cert_dir=args.cached_cert_dir,
        instance_type_changes=config.get("instance_type_changes", {})
    )


import sys
import os
import subprocess
import time
import json

import logging
logger = logging.getLogger('slideatlas')

from . import MongoUploader
from . import WrapperReader

__all__ = ('MongoUploaderWrapper', )

class MongoUploaderWrapper(MongoUploader):
    """
    Class for uploading using image_uploader wrapper
    """
    def __init__(self, args):
        super(MongoUploaderWrapper, self).__init__(args)

    def make_reader(self):
        """
        Creates a ptif reader
        """

        try:
            reader = WrapperReader({"fname": self.args["input"], 'bindir': self.args["bindir"]})
            # Introspect
            logger.info('Dimensions: (%d, %d)', reader.width, reader.height)
        except:
            logger.error('Unable to read input file %s', self.args['input'])
            sys.exit(0)

        return reader

    def upload_base(self):
        """
        Does not depend on the reader, instead wraps the image_uploader utility
        Expects the reader and the imagestore to be setup before
        """

        if self.args["dry_run"]:
            logger.info('Dry run .. not uploading base')
            return

        istore = self.imagestore

        if os.name == 'nt':
            args = [self.args["bindir"] + "image_uploader.exe", "-m", istore.host.split(",")[0], "-d", istore.dbname, "-c", str(self.imageid), self.args["input"]]
            if len(istore.username) > 0:
                args = args + ["-u", istore.username, "-p", istore.password]
        else:
            args = [self.args["bindir"] + "/image_uploader", "-m", istore.host.split(",")[0], "-d", istore.dbname, "-c", str(self.imageid), self.args["input"]]
            if len(istore.username) > 0:
                args = args + ["-u", istore.username, "-p", istore.password]

            # args = " ".join(args)

        logger.info('Params: %s', str(args))
        # Get the information in json

        proc = subprocess.Popen(args, stdout=subprocess.PIPE, cwd=self.args["bindir"], shell=False)

        while True:
            time.sleep(0)

            result = proc.poll()

            if not (result is None):
                # Process died
                if not result == 0:
                    logger.error('Process died without any output')
                    sys.exit(1)

            output = proc.stdout.readline()
            #print output

            try:
                js = json.loads(output)
            except:
                logger.error('Invalid json output from image_uploader: "%s"', output)
                sys.exit(1)

            if "error" in js:
                logger.error('image_uploader says: %s', js['error'])
                sys.exit(1)

            if "information" in js:
                logger.info('Information available')

            if "progress_percent" in js:
                logger.info('Progress : %f' % js['progress_percent'])

            if "success" in js:
                logger.info('DONE')
                break


import os

for filename in ['training_spikes.csv', 'testing_spikes.csv']:
    newfile = filename[0:-4]+'.mem'
    if(os.path.isfile(newfile)):
        os.remove(newfile)
    with open(filename, 'r') as f, open(newfile, 'w') as g:
        count = 0
        newline = ''
        for line in f.readlines():
            num = int(line[0:-2])
            if num == -1:
                #print('1111')
                newline += '1111'
            else:
                #print('{0:04b}'.format(num))
                newline += '{0:04b}'.format(num)
            if count == 7:
                g.write(newline+'\n')
                count = 0
                newline = ''
            else:
                count += 1


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

import events
from events.eventTypes import *
from events.naoEvent import *

from safePrint import sPrint

import threading
import Queue

##
#	Classe redéfinissant un thread pour lui apporter des méthodes de gestion d'événements.
#	Ce thread peut être défini pour boucler ou pour être exécuté pas a pas.
#	Cette option est modifiable à tout moment de son exécution.
#	Chaque NaoThread possède sa propre liste d'événements reçus.
#	Il peut s'exécuter lorsqu'un événement est disponible ou non, par exemple pour implémenter
#	des modules bouclant en permanence pour la récupération d'informations.
#	De tels modules ne reçoivent pas des événements d'autres threads en permanence mais doivent
#	quand même être exécutés.
#
class NaoThread(threading.Thread):

	##
	#	Création d'un nouveau NaoThread.
	#	@param name Nom du thread (pour l'affichage console)
	#	@param loop Indique si le thread doit boucler en appelant la méthode step ou
	#				seulement effectuer un seul appel à la méthode NaoThread#step lors du réveil.
	#
	def __init__(self, name, loop):
		# initialisation du thread
		threading.Thread.__init__(self, None, None, name)
		# evenement permettant de reveiller le module ou de l'endormir (independant de naoEvent)
		self.event = threading.Event()
		# permet de faire boucler le module si defini
		self.loop = loop
		# si le module doit boucler, l'evenement est active car le thread ne l'attendra pas
		if loop:
			self.event.set()
		# indique si le module doit s'executer ou s'arreter
		self.running = True
		# indique une demande d'arret (pour le cas ou le module doit finir de traiter les evenements avant l'arret)
		self.stopRequest = False
		# indique la reception d'un nouvel evenement
		self.newEvent = False
		# file d'evenements sans limite de taille
		self.eventQueue = Queue.Queue(0)
		# condition permettant d'executer des methodes en section critique
		# et permettant a d'autres thread d'attendre le traitement d'un evenement
		self.cond = threading.Condition()
		# indique la reception d'une requete de reveil
		self.wakeUpRequest = False

	##
	#	Définit un gestionnaire d'événements pour le thread.
	#	Ce gestionnaire permet la communication avec les autres threads via l'envoi d'événements.
	#
	def set_manager(self, manager):
		self.manager = manager

	##
	#	Permet de récupérer le gestionnaire d'événements du thread pour poster des événements
	#	ou accéder à l'état actuel de l'automate du programme.
	#
	def get_manager(self):
		return self.manager

	##
	# Boucle du thread.
	# Si le thread doit boucler (loop défini a True par NaoThread#set_loop) il ne s'endort pas
	# et appelle la méthode NaoThread#step en boucle.
	# Sinon il est endormi après chaque pas de boucle en attente de réveil par la methode NaoThread#wake_up.
	#
	def run(self):
		# endort le thread au lancement si loop n'est pas defini, et qu'une requete d'arret n'a pas ete envoyee
		if self.running or not self.stopRequest:
			self.event.wait()
		# reinitialisation de la notification de reveil
		self.cond.acquire()
		self.wakeUpRequest = False
		self.cond.release()
		# boucle du thread, tant que stop n'est pas appele
		# si stop est appele avec l'option immediate, le thread s'arrete immediatement sinon il attend de traiter tous les evenements
		while self.running and not (self.stopRequest and self.eventQueue.empty()):
			# traitement d'evenement, redefini selon le module
			event = None
			# si la liste d'evenements n'est pas vide, recuperation d'un evenement
			# sinon creation d'un evenement indiquant qu'il n'y en a pas
			if not self.eventQueue.empty():
				event = self.eventQueue.get()
			else:
				event = NaoEvent(EventTypes.NO_EVENT)
			# pas d'execution du thread, redefini par les sous classes
			self.step(event)
			# notifie d'eventuels threads attendant le traitement d'un evenement
			self.notify_followers()
			# entree en section critique pour l'acces a l'evenement selon les requetes effectuees
			self.cond.acquire()
			# si le thread ne boucle pas et ne doit pas se reveiller, on reinitialise l'evenement pour l'endormir
			if not self.loop and not self.wakeUpRequest:
				self.event.clear()
			# reinitialisation de la requete de reveil (en section critique)
			# elle vaut vrai ici si un thread a demander a reveiller celui-ci alors qu'il etait deja reveille
			self.wakeUpRequest = False
			# relachement de section critique avant d'endormir le thread
			self.cond.release()
			# endort le thread en attendant un post_event ou loop
			if self.running and not self.stopRequest:
				self.event.wait()
			# reinitialisation de la requete de reveil en section critique
			self.cond.acquire()
			self.wakeUpRequest = False
			self.cond.release()

		# indication de l'arret du thread en section critique
		self.cond.acquire()
		self.running = False
		self.cond.release()
		# reveil des threads encore en attente
		self.notify_followers()
		sPrint(self.name, " stopping")
		# methode redefinie par les sous classes, appelee lors de la terminaison du thread
		self.on_end()

	##
	#	Ajout d'un événement dans la liste de ceux à traiter par le thread.
	#
	def post_event(self, naoEvent):
		self.eventQueue.put(naoEvent)

	##
	#	Réveille le thread, qui appelera une seule fois NaoThread#step ou bouclera suivant la valeur de loop.
	# 	Cette valeur est définie lors de l'appel du constructeur ou par la methode NaoThread#set_loop.
	#
	def wake_up(self):
		self.cond.acquire()
		self.wakeUpRequest = True
		self.event.set()
		self.cond.release()

	##
	# 	Endort le thread, qui peut être réveillé par la suite grâce à la méthode NaoThread#wake_up.
	#
	def pause(self):
		self.event.clear()

	##
	#	Demande la terminaison du thread.
	#	Si immediate vaut false, le thread traite tous les événements en attente
	#	avant de se terminer.
	#	S'il vaut true (valeur par defaut), le thread termine immediatement.
	#	La methode NaoThread#on_end (à redéfinir dans les sous classes) est appelée lors de la terminaison du thread.
	#
	def stop(self, immediate = True):
		if immediate:
			self.running = False
		else:
			self.stopRequest = True
		self.event.set()

	##
	#	Modifie l'option de bouclage du thread.
	# 	Si value vaut True, active le bouclage du thread, qui exécutera la méthode NaoThread#step en boucle.
	#	Sinon, la méthode NaoThread#step ne sera appelé qu'une fois à chaque réveil par NaoThread#wake_up.
	#
	def set_loop(self, value):
		self.loop = value

	##
	#	Méthode bloquante permettant à un thread externe d'attendre le traitement du prochain événement.
	#	Le thread appelant sera réveillé après le traitement de l'événement.
	#	Si un événement est déjà en cours de traitement, le thread appelant sera réveillé après son traitement.
	#	Le nombre de threads pouvant attendre le traitement n'est pas limité.
	#
	def wait_treating(self):
		self.cond.acquire()
		if self.running and self.event.isSet():
			self.cond.wait()
		self.cond.release()

	##
	#	Méthode interne.
	#	Réveille les threads qui attendent le traitement d'un événement.
	#
	def notify_followers(self):
		self.cond.acquire()
		self.cond.notifyAll()
		self.cond.release()

	##
	#	Méthode a redéfinir dans les sous classes, appelée lors de la terminaison du thread.
	#
	def on_end(self):
		None

	##
	#	Méthode à redéfinir dans les sous classes, appelée à chaque pas d'exécution du thread.
	#  	Si loop a été défini à true (constructeur ou méthode NaoThread#set_loop), cette méthode est appelée constamment.
	#	Sinon elle est appelée une seule fois par appel à NaoThread#wake_up.
	#	Si aucun événement n'est disponible lors de l'appel, elle est appelée avec un événement de type NO_EVENT.
	#	Sinon, elle est appelée avec le plus ancien événement reçu.
	#
	def step(self, naoEvent):
		None