<commit_before>
import discord
from discord.ext import commands, menus

from enum import IntEnum
import io
import random
import sys

from utilities import checks
from utilities.menu import Menu

def setup(bot):
	bot.add_cog(MazeCog(bot))

class Direction(IntEnum):
	UP = 0
	RIGHT = 1
	DOWN = 2
	LEFT = 3

class Maze:

	def __init__(self, columns, rows, random_start = False, random_end = False):
		self.columns = 2 if columns < 2 else 80 if columns > 80 else columns
		self.rows = 2 if rows < 2 else 80 if rows > 80 else rows
		# TODO: optimize generation algorithm?, previous upper limit of 100x100
		self.random_start = random_start
		self.random_end = random_end
		self.move_counter = 0

		self.directions = [[[False] * 4 for r in range(self.rows)] for c in range(self.columns)]
		self.generate_visited = [[False for r in range(self.rows)] for c in range(self.columns)]
		self.generate_connection(random.randint(0, self.columns - 1), random.randint(0, self.rows - 1))

		# self.visited = [[False for r in range(self.rows)] for c in range(self.columns)]
		if not self.random_start:
			self.column = 0
			self.row = 0
		else:
			self.column = random.randint(0, self.columns - 1)
			self.row = random.randint(0, self.rows - 1)
		# self.visited[self.column][self.row] = True
		if self.random_end:
			self.e_column = random.randint(0, self.columns - 1)
			self.e_row = random.randint(0, self.rows - 1)

		self.maze_string = ""
		for r in range(self.rows):
			for c in range(self.columns):
				if self.directions[c][r][0]:
					self.maze_string += "+   "
				else:
					self.maze_string += "+---"
			self.maze_string += "+\n"
			for c in range(self.columns):
				if self.directions[c][r][3]:
					self.maze_string += "    "
				else:
					self.maze_string += "|   "
			self.maze_string += "|\n"
		self.maze_string += "+---" * self.columns + "+\n"
		self.maze_string_array = self.maze_string.split('\n')

		self.visible = [None] * (2 * self.rows + 1)
		self.visible[::2] = ["+---" * self.columns + "+"] * (self.rows + 1)
		self.visible[1::2] = ["| X " * self.columns + "|"] * self.rows
		if not self.random_start:
			for r in range(3):
				self.visible[r] = self.maze_string_array[r][:5] + self.visible[r][5:]
			self.visible[1] = self.visible[1][:2] + 'I' + self.visible[1][3:]
		else:
			for r in range(2 * self.row, 2 * self.row + 3):
				self.visible[r] = self.visible[r][:self.column * 4] + self.maze_string_array[r][self.column * 4:self.column * 4 + 5] + self.visible[r][self.column * 4 + 5:]
			self.visible[2 * self.row + 1] = self.visible[2 * self.row + 1][:self.column * 4 + 2] + 'I' + self.visible[2 * self.row + 1][4 * self.column + 3:]
		if not self.random_end:
			self.visible[2 * self.rows - 1] = self.visible[2 * self.rows - 1][:4 * self.columns - 2] + 'E' + self.visible[2 * self.rows - 1][4 * self.columns - 1:]
		else:
			self.visible[2 * self.e_row + 1] = self.visible[2 * self.e_row + 1][:self.e_column * 4 + 2] + 'E' + self.visible[2 * self.e_row + 1][4 * self.e_column + 3:]

	def __repr__(self):
		return self.maze_string

	def __str__(self):
		if self.rows <= 10 and self.columns <= 10:
			return '\n'.join(self.visible)
		start_row = self.row - self.row % 10
		start_column = self.column - self.column % 10
		visible = self.visible[2 * start_row:2 * start_row + 21]
		for row_number, row in enumerate(visible):
			visible[row_number] = row[4 * start_column:4 * start_column + 41]
		return '\n'.join(visible)

	'''
	def test_print(self):
		maze_print = [["" for r in range(self.rows)] for c in range(self.columns)]
		for c in range(self.columns):
			for r in range(self.rows):
				if self.directions[c][r][0]:
					maze_print[c][r] += "N"
				if self.directions[c][r][1]:
					maze_print[c][r] += "E"
				if self.directions[c][r][2]:
					maze_print[c][r] += "S"
				if self.directions[c][r][3]:
					maze_print[c][r] += "W"
		return zip(*maze_print)
	'''

	def move(self, direction):
		'''Move inside the maze'''
		if not isinstance(direction, Direction) or not self.directions[self.column][self.row][direction]:
			return False

		self.visible[2 * self.row + 1] = self.visible[2 * self.row + 1][:4 * self.column + 2] + " " + self.visible[2 * self.row + 1][4 * self.column + 3:]
		if direction is Direction.UP:
			self.row -= 1
		elif direction is Direction.RIGHT:
			self.column += 1
		elif direction is direction.DOWN:
			self.row += 1
		elif direction is direction.LEFT:
			self.column -= 1

		# self.visited[self.column][self.row] = True
		self.move_counter += 1
		for r in range(3):
			self.visible[2 * self.row + r] = self.visible[2 * self.row + r][:4 * self.column] + self.maze_string_array[2 * self.row + r][4 * self.column:4 * self.column + 5] + self.visible[2 * self.row + r][4 * self.column + 5:]
		self.visible[2 * self.row + 1] = self.visible[2 * self.row + 1][:4 * self.column + 2] + "I" + self.visible[2 * self.row + 1][4 * self.column + 3:]
		return True

	def reached_end(self):
		if not self.random_end:
			return (self.column == self.columns - 1 and self.row == self.rows - 1)
		else:
			return self.column == self.e_column and self.row == self.e_row

	def generate_connection(self, c, r):
		'''Generate connections for the maze'''
		self.generate_visited[c][r] = True
		for horizontal, vertical in random.sample(((-1, 0), (0, -1), (0, 1), (1, 0)), 4):
			if not (0 <= c + horizontal < self.columns and 0 <= r + vertical < self.rows):
				continue
			if self.generate_visited[c + horizontal][r + vertical]:
				continue
			if horizontal == 0 and vertical == -1:
				self.directions[c][r][Direction.UP] = True
				self.directions[c][r - 1][Direction.DOWN] = True
			elif horizontal == 1 and vertical == 0:
				self.directions[c][r][Direction.RIGHT] = True
				self.directions[c + 1][r][Direction.LEFT] = True
			elif horizontal == 0 and vertical == 1:
				self.directions[c][r][Direction.DOWN] = True
				self.directions[c][r + 1][Direction.UP] = True
			elif horizontal == -1 and vertical == 0:
				self.directions[c][r][Direction.LEFT] = True
				self.directions[c - 1][r][Direction.RIGHT] = True
			self.generate_connection(c + horizontal, r + vertical)

class MazeCog(commands.Cog, name = "Maze"):

	def __init__(self, bot):
		self.bot = bot
		self.mazes = {}

		# Necessary for maze generation
		sys.setrecursionlimit(5000)

	async def cog_check(self, ctx):
		return await checks.not_forbidden().predicate(ctx)

	@commands.group(invoke_without_command = True, case_insensitive = True)
	async def maze(self, ctx):
		'''
		Maze game
		[w, a, s, d] to move
		'''
		await ctx.send_help(ctx.command)

	# TODO: Use max concurrency
	@maze.command(aliases = ["begin"])
	async def start(self, ctx, width: int = 5, height: int = 5, random_start: bool = False, random_end: bool = False):
		'''
		Start a maze game
		width: 2 - 80
		height: 2 - 80
		'''
		if ctx.channel.id in self.mazes:
			return await ctx.embed_reply(":no_entry: There's already a maze game going on")
		self.mazes[ctx.channel.id] = Maze(width, height, random_start = random_start, random_end = random_end)
		maze_instance = self.mazes[ctx.channel.id]
		maze_message = await ctx.embed_reply(ctx.bot.CODE_BLOCK.format(str(maze_instance)))
		'''
		maze_print = ""
		for r in maze_instance.test_print():
			row_print = ""
			for cell in r:
				row_print += cell + ' '
			maze_print += row_print + "\n"
		await ctx.reply(ctx.bot.CODE_BLOCK.format(maze_print))
		'''
		# await ctx.reply(ctx.bot.CODE_BLOCK.format(repr(maze_instance)))
		convert_move = {'w' : Direction.UP, 'a' : Direction.LEFT, 's' : Direction.DOWN, 'd' : Direction.RIGHT}
		while not maze_instance.reached_end():
			move = await self.bot.wait_for("message", check = lambda message: message.content.lower() in ['w', 'a', 's', 'd'] and message.channel == ctx.channel)
			# author = ctx.author
			# TODO: Add option to restrict to command invoker
			moved = maze_instance.move(convert_move[move.content.lower()])
			response = ctx.bot.CODE_BLOCK.format(str(maze_instance))
			if not moved:
				response += "\n:no_entry: You can't go that way"
			new_maze_message = await ctx.embed_reply(response)
			await self.bot.attempt_delete_message(move)
			await self.bot.attempt_delete_message(maze_message)
			maze_message = new_maze_message
		await ctx.embed_reply(f"Congratulations! You reached the end of the maze in {maze_instance.move_counter} moves")
		del self.mazes[ctx.channel.id]

	@maze.command()
	async def current(self, ctx):
		'''Current maze game'''
		if ctx.channel.id in self.mazes:
			await ctx.embed_reply(ctx.bot.CODE_BLOCK.format(str(self.mazes[ctx.channel.id])))
		else:
			await ctx.embed_reply(":no_entry: There's no maze game currently going on")

	@maze.command(aliases = ['m', "menus", 'r', "reaction", "reactions"])
	async def menu(self, ctx, width: int = 5, height: int = 5, random_start: bool = False, random_end: bool = False):
		'''
		Maze game menu
		width: 2 - 80
		height: 2 - 80
		React with an arrow key to move
		'''
		await MazeMenu(width, height, random_start, random_end).start(ctx)

	# TODO: maze print, position?, stats

class MazeMenu(Menu):

	def __init__(self, width, height, random_start, random_end):
		super().__init__(timeout = None, clear_reactions_after = True, check_embeds = True)
		self.maze = Maze(width, height, random_start, random_end)
		self.arrows = {'\N{LEFTWARDS BLACK ARROW}': Direction.LEFT, '\N{UPWARDS BLACK ARROW}': Direction.UP, '\N{DOWNWARDS BLACK ARROW}': Direction.DOWN, '\N{BLACK RIGHTWARDS ARROW}': Direction.RIGHT}
		for number, emoji in enumerate(self.arrows.keys(), start = 1):
			self.add_button(menus.Button(emoji, self.on_direction, position = number))

	async def send_initial_message(self, ctx, channel):
		return await ctx.embed_reply(ctx.bot.CODE_BLOCK.format(str(self.maze)),
										footer_text = f"Your current position: {self.maze.column + 1}, {self.maze.row + 1}")

	async def on_direction(self, payload):
		embed = self.message.embeds[0]
		if not self.maze.move(self.arrows[str(payload.emoji)]):
			embed.description = (self.bot.CODE_BLOCK.format(str(self.maze))
									+ "\n:no_entry: You can't go that way")
		elif self.maze.reached_end():
			embed.description = (self.bot.CODE_BLOCK.format(str(self.maze))
									+ f"\nCongratulations! You reached the end of the maze in {self.maze.move_counter} moves")
			self.stop()
		else:
			embed.description = self.bot.CODE_BLOCK.format(str(self.maze))
		embed.set_footer(text = f"Your current position: {self.maze.column + 1}, {self.maze.row + 1}")
		await self.message.edit(embed = embed)

	@menus.button("\N{PRINTER}", position = 5, lock = False)
	async def on_printer(self, payload):
		await self.message.channel.send(content = f"{self.ctx.author.display_name}:\n"
													"Your maze is attached",
										file = discord.File(io.BytesIO(('\n'.join(self.maze.visible)).encode()),
															filename = "maze.txt"))

<commit_msg>[Discord] Improve comments in Maze and Maze cog<commit_after>
import discord
from discord.ext import commands, menus

from enum import IntEnum
import io
import random
import sys

from utilities import checks
from utilities.menu import Menu

def setup(bot):
	bot.add_cog(MazeCog(bot))

class Direction(IntEnum):
	UP = 0
	RIGHT = 1
	DOWN = 2
	LEFT = 3

class Maze:

	def __init__(self, columns, rows, random_start = False, random_end = False):
		self.columns = 2 if columns < 2 else 80 if columns > 80 else columns
		self.rows = 2 if rows < 2 else 80 if rows > 80 else rows
		# TODO: optimize generation algorithm?, previous upper limit of 100x100
		self.random_start = random_start
		self.random_end = random_end
		self.move_counter = 0

		self.directions = [[[False] * 4 for r in range(self.rows)] for c in range(self.columns)]
		self.generate_visited = [[False for r in range(self.rows)] for c in range(self.columns)]
		self.generate_connection(random.randint(0, self.columns - 1), random.randint(0, self.rows - 1))

		# self.visited = [[False for r in range(self.rows)] for c in range(self.columns)]
		if not self.random_start:
			self.column = 0
			self.row = 0
		else:
			self.column = random.randint(0, self.columns - 1)
			self.row = random.randint(0, self.rows - 1)
		# self.visited[self.column][self.row] = True
		if self.random_end:
			self.e_column = random.randint(0, self.columns - 1)
			self.e_row = random.randint(0, self.rows - 1)

		self.maze_string = ""
		for r in range(self.rows):
			for c in range(self.columns):
				if self.directions[c][r][0]:
					self.maze_string += "+   "
				else:
					self.maze_string += "+---"
			self.maze_string += "+\n"
			for c in range(self.columns):
				if self.directions[c][r][3]:
					self.maze_string += "    "
				else:
					self.maze_string += "|   "
			self.maze_string += "|\n"
		self.maze_string += "+---" * self.columns + "+\n"
		self.maze_string_array = self.maze_string.split('\n')

		self.visible = [None] * (2 * self.rows + 1)
		self.visible[::2] = ["+---" * self.columns + "+"] * (self.rows + 1)
		self.visible[1::2] = ["| X " * self.columns + "|"] * self.rows
		if not self.random_start:
			for r in range(3):
				self.visible[r] = self.maze_string_array[r][:5] + self.visible[r][5:]
			self.visible[1] = self.visible[1][:2] + 'I' + self.visible[1][3:]
		else:
			for r in range(2 * self.row, 2 * self.row + 3):
				self.visible[r] = self.visible[r][:self.column * 4] + self.maze_string_array[r][self.column * 4:self.column * 4 + 5] + self.visible[r][self.column * 4 + 5:]
			self.visible[2 * self.row + 1] = self.visible[2 * self.row + 1][:self.column * 4 + 2] + 'I' + self.visible[2 * self.row + 1][4 * self.column + 3:]
		if not self.random_end:
			self.visible[2 * self.rows - 1] = self.visible[2 * self.rows - 1][:4 * self.columns - 2] + 'E' + self.visible[2 * self.rows - 1][4 * self.columns - 1:]
		else:
			self.visible[2 * self.e_row + 1] = self.visible[2 * self.e_row + 1][:self.e_column * 4 + 2] + 'E' + self.visible[2 * self.e_row + 1][4 * self.e_column + 3:]

	def __repr__(self):
		return self.maze_string
		# Tuple of connection directions for each cell:
		# return str(
		# 	tuple(
		# 		tuple(
		# 			tuple(
		# 				filter(
		# 					None, (
		# 						direction.name if self.directions[column][row][direction] else None
		# 						for direction in Direction
		# 					)
		# 				)
		# 			) for column in range(self.columns)
		# 		) for row in range(self.rows)
		# 	)
		# )
		# Grid of first letter of connection directions:
		# return (
		# 	'\n'.join(
		# 		"".join(
		# 			"".join(
		# 				direction.name[0] if self.directions[column][row][direction] else ""
		# 				for direction in Direction
		# 			).ljust(5, ' ') for column in range(self.columns)
		# 		) for row in range(self.rows)
		# 	)
		# )

	def __str__(self):
		if self.rows <= 10 and self.columns <= 10:
			return '\n'.join(self.visible)
		start_row = self.row - self.row % 10
		start_column = self.column - self.column % 10
		visible = self.visible[2 * start_row:2 * start_row + 21]
		for row_number, row in enumerate(visible):
			visible[row_number] = row[4 * start_column:4 * start_column + 41]
		return '\n'.join(visible)

	def move(self, direction):
		'''Move inside the maze'''
		if not isinstance(direction, Direction) or not self.directions[self.column][self.row][direction]:
			return False

		self.visible[2 * self.row + 1] = self.visible[2 * self.row + 1][:4 * self.column + 2] + " " + self.visible[2 * self.row + 1][4 * self.column + 3:]
		if direction is Direction.UP:
			self.row -= 1
		elif direction is Direction.RIGHT:
			self.column += 1
		elif direction is direction.DOWN:
			self.row += 1
		elif direction is direction.LEFT:
			self.column -= 1

		# self.visited[self.column][self.row] = True
		self.move_counter += 1
		for r in range(3):
			self.visible[2 * self.row + r] = self.visible[2 * self.row + r][:4 * self.column] + self.maze_string_array[2 * self.row + r][4 * self.column:4 * self.column + 5] + self.visible[2 * self.row + r][4 * self.column + 5:]
		self.visible[2 * self.row + 1] = self.visible[2 * self.row + 1][:4 * self.column + 2] + "I" + self.visible[2 * self.row + 1][4 * self.column + 3:]
		return True

	def reached_end(self):
		if not self.random_end:
			return (self.column == self.columns - 1 and self.row == self.rows - 1)
		else:
			return self.column == self.e_column and self.row == self.e_row

	def generate_connection(self, c, r):
		'''Generate connections for the maze'''
		self.generate_visited[c][r] = True
		for horizontal, vertical in random.sample(((-1, 0), (0, -1), (0, 1), (1, 0)), 4):
			if not (0 <= c + horizontal < self.columns and 0 <= r + vertical < self.rows):
				continue
			if self.generate_visited[c + horizontal][r + vertical]:
				continue
			if horizontal == 0 and vertical == -1:
				self.directions[c][r][Direction.UP] = True
				self.directions[c][r - 1][Direction.DOWN] = True
			elif horizontal == 1 and vertical == 0:
				self.directions[c][r][Direction.RIGHT] = True
				self.directions[c + 1][r][Direction.LEFT] = True
			elif horizontal == 0 and vertical == 1:
				self.directions[c][r][Direction.DOWN] = True
				self.directions[c][r + 1][Direction.UP] = True
			elif horizontal == -1 and vertical == 0:
				self.directions[c][r][Direction.LEFT] = True
				self.directions[c - 1][r][Direction.RIGHT] = True
			self.generate_connection(c + horizontal, r + vertical)

class MazeCog(commands.Cog, name = "Maze"):

	def __init__(self, bot):
		self.bot = bot
		self.mazes = {}

		# Necessary for maze generation
		sys.setrecursionlimit(5000)

	async def cog_check(self, ctx):
		return await checks.not_forbidden().predicate(ctx)

	@commands.group(invoke_without_command = True, case_insensitive = True)
	async def maze(self, ctx):
		'''
		Maze game
		[w, a, s, d] to move
		'''
		await ctx.send_help(ctx.command)

	# TODO: Use max concurrency
	@maze.command(aliases = ["begin"])
	async def start(self, ctx, width: int = 5, height: int = 5, random_start: bool = False, random_end: bool = False):
		'''
		Start a maze game
		width: 2 - 80
		height: 2 - 80
		'''
		# TODO: Add option to restrict to command invoker
		if ctx.channel.id in self.mazes:
			return await ctx.embed_reply(":no_entry: There's already a maze game going on")
		self.mazes[ctx.channel.id] = Maze(width, height, random_start = random_start, random_end = random_end)
		maze_instance = self.mazes[ctx.channel.id]
		maze_message = await ctx.embed_reply(ctx.bot.CODE_BLOCK.format(str(maze_instance)))
		convert_move = {'w' : Direction.UP, 'a' : Direction.LEFT, 's' : Direction.DOWN, 'd' : Direction.RIGHT}
		while not maze_instance.reached_end():
			move = await self.bot.wait_for("message", check = lambda message: message.content.lower() in ['w', 'a', 's', 'd'] and message.channel == ctx.channel)
			# author = ctx.author
			moved = maze_instance.move(convert_move[move.content.lower()])
			response = ctx.bot.CODE_BLOCK.format(str(maze_instance))
			if not moved:
				response += "\n:no_entry: You can't go that way"
			new_maze_message = await ctx.embed_reply(response)
			await self.bot.attempt_delete_message(move)
			await self.bot.attempt_delete_message(maze_message)
			maze_message = new_maze_message
		await ctx.embed_reply(f"Congratulations! You reached the end of the maze in {maze_instance.move_counter} moves")
		del self.mazes[ctx.channel.id]

	@maze.command()
	async def current(self, ctx):
		'''Current maze game'''
		if ctx.channel.id in self.mazes:
			await ctx.embed_reply(ctx.bot.CODE_BLOCK.format(str(self.mazes[ctx.channel.id])))
		else:
			await ctx.embed_reply(":no_entry: There's no maze game currently going on")

	@maze.command(aliases = ['m', "menus", 'r', "reaction", "reactions"])
	async def menu(self, ctx, width: int = 5, height: int = 5, random_start: bool = False, random_end: bool = False):
		'''
		Maze game menu
		width: 2 - 80
		height: 2 - 80
		React with an arrow key to move
		'''
		await MazeMenu(width, height, random_start, random_end).start(ctx)

	# TODO: maze print, position?, stats

class MazeMenu(Menu):

	def __init__(self, width, height, random_start, random_end):
		super().__init__(timeout = None, clear_reactions_after = True, check_embeds = True)
		self.maze = Maze(width, height, random_start, random_end)
		self.arrows = {'\N{LEFTWARDS BLACK ARROW}': Direction.LEFT, '\N{UPWARDS BLACK ARROW}': Direction.UP, '\N{DOWNWARDS BLACK ARROW}': Direction.DOWN, '\N{BLACK RIGHTWARDS ARROW}': Direction.RIGHT}
		for number, emoji in enumerate(self.arrows.keys(), start = 1):
			self.add_button(menus.Button(emoji, self.on_direction, position = number))

	async def send_initial_message(self, ctx, channel):
		return await ctx.embed_reply(ctx.bot.CODE_BLOCK.format(str(self.maze)),
										footer_text = f"Your current position: {self.maze.column + 1}, {self.maze.row + 1}")

	async def on_direction(self, payload):
		embed = self.message.embeds[0]
		if not self.maze.move(self.arrows[str(payload.emoji)]):
			embed.description = (self.bot.CODE_BLOCK.format(str(self.maze))
									+ "\n:no_entry: You can't go that way")
		elif self.maze.reached_end():
			embed.description = (self.bot.CODE_BLOCK.format(str(self.maze))
									+ f"\nCongratulations! You reached the end of the maze in {self.maze.move_counter} moves")
			self.stop()
		else:
			embed.description = self.bot.CODE_BLOCK.format(str(self.maze))
		embed.set_footer(text = f"Your current position: {self.maze.column + 1}, {self.maze.row + 1}")
		await self.message.edit(embed = embed)

	@menus.button("\N{PRINTER}", position = 5, lock = False)
	async def on_printer(self, payload):
		await self.message.channel.send(content = f"{self.ctx.author.display_name}:\n"
													"Your maze is attached",
										file = discord.File(io.BytesIO(('\n'.join(self.maze.visible)).encode()),
															filename = "maze.txt"))

<|endoftext|>


<commit_before>
from discord.ext import commands

import datetime

from utilities import checks

def setup(bot):
	bot.add_cog(WoWS(bot))

class WoWS(commands.Cog):

	def __init__(self, bot):
		self.bot = bot
		self.api_urls = {"asia": "https://api.worldofwarships.asia/wows/",
						"eu": "https://api.worldofwarships.eu/wows/",
						"na": "https://api.worldofwarships.com/wows/",
						"ru": "https://api.worldofwarships.ru/wows/"}

	@commands.group(aliases = ["worldofwarships", "world_of_warships"],
					invoke_without_command = True, case_insensitive = True)
	@checks.not_forbidden()
	async def wows(self, ctx):
		'''
		World of Warships
		Realms/Regions: Asia, EU, NA, RU (Default: NA)
		'''
		await ctx.send_help(ctx.command)

	@wows.group(invoke_without_command = True, case_insensitive = True)
	@checks.not_forbidden()
	async def player(self, ctx, player : str, region : str = "NA"):
		'''Player details'''
		api_url = self.api_urls.get(region.lower(), "na")
		params = {"application_id": ctx.bot.WARGAMING_APPLICATION_ID, "search": player, "limit": 1}
		async with ctx.bot.aiohttp_session.get(api_url + "account/list/", params = params) as resp:
			data = await resp.json()
		if data["status"] == "error":
			return await ctx.embed_reply(f":no_entry: Error: {data['error']['message']}")
		if data["status"] != "ok":
			return await ctx.embed_reply(":no_entry: Error")
		if not data["meta"]["count"]:
			return await ctx.embed_reply(":no_entry: Error: Player not found")
		account_id = data["data"][0]["account_id"]
		params = {"application_id": ctx.bot.WARGAMING_APPLICATION_ID, "account_id": account_id}
		async with ctx.bot.aiohttp_session.get(api_url + "account/info/", params = params) as resp:
			data = await resp.json()
		if data["status"] == "error":
			return await ctx.embed_reply(f":no_entry: Error: {data['error']['message']}")
		if data["status"] != "ok":
			return await ctx.embed_reply(":no_entry: Error")
		data = data["data"][str(account_id)]
		# TODO: handle hidden profile?
		fields = [("ID", account_id), ("Account Level", data["leveling_tier"])]
		fields.append(("Account XP", f"{data['leveling_points']:,}"))
		fields.append(("Battles Fought", data["statistics"]["battles"]))
		fields.append(("Miles Travelled", data["statistics"]["distance"]))
		created_at = datetime.datetime.utcfromtimestamp(data["created_at"])
		await ctx.embed_reply(title = data["nickname"], fields = fields,
								footer_text = "Account Created", timestamp = created_at)

<commit_msg>[Discord] Normalize wows cog initialization formatting<commit_after>
from discord.ext import commands

import datetime

from utilities import checks

def setup(bot):
	bot.add_cog(WoWS(bot))

class WoWS(commands.Cog):

	def __init__(self, bot):
		self.bot = bot
		self.api_urls = {"asia": "https://api.worldofwarships.asia/wows/",
							"eu": "https://api.worldofwarships.eu/wows/",
							"na": "https://api.worldofwarships.com/wows/",
							"ru": "https://api.worldofwarships.ru/wows/"}

	@commands.group(aliases = ["worldofwarships", "world_of_warships"],
					invoke_without_command = True, case_insensitive = True)
	@checks.not_forbidden()
	async def wows(self, ctx):
		'''
		World of Warships
		Realms/Regions: Asia, EU, NA, RU (Default: NA)
		'''
		await ctx.send_help(ctx.command)

	@wows.group(invoke_without_command = True, case_insensitive = True)
	@checks.not_forbidden()
	async def player(self, ctx, player : str, region : str = "NA"):
		'''Player details'''
		api_url = self.api_urls.get(region.lower(), "na")
		params = {"application_id": ctx.bot.WARGAMING_APPLICATION_ID, "search": player, "limit": 1}
		async with ctx.bot.aiohttp_session.get(api_url + "account/list/", params = params) as resp:
			data = await resp.json()
		if data["status"] == "error":
			return await ctx.embed_reply(f":no_entry: Error: {data['error']['message']}")
		if data["status"] != "ok":
			return await ctx.embed_reply(":no_entry: Error")
		if not data["meta"]["count"]:
			return await ctx.embed_reply(":no_entry: Error: Player not found")
		account_id = data["data"][0]["account_id"]
		params = {"application_id": ctx.bot.WARGAMING_APPLICATION_ID, "account_id": account_id}
		async with ctx.bot.aiohttp_session.get(api_url + "account/info/", params = params) as resp:
			data = await resp.json()
		if data["status"] == "error":
			return await ctx.embed_reply(f":no_entry: Error: {data['error']['message']}")
		if data["status"] != "ok":
			return await ctx.embed_reply(":no_entry: Error")
		data = data["data"][str(account_id)]
		# TODO: handle hidden profile?
		fields = [("ID", account_id), ("Account Level", data["leveling_tier"])]
		fields.append(("Account XP", f"{data['leveling_points']:,}"))
		fields.append(("Battles Fought", data["statistics"]["battles"]))
		fields.append(("Miles Travelled", data["statistics"]["distance"]))
		created_at = datetime.datetime.utcfromtimestamp(data["created_at"])
		await ctx.embed_reply(title = data["nickname"], fields = fields,
								footer_text = "Account Created", timestamp = created_at)

<|endoftext|>


<commit_before>"""
Django settings for onestack project.

Generated by 'django-admin startproject' using Django 1.11.3.

For more information on this file, see
https://docs.djangoproject.com/en/1.11/topics/settings/

For the full list of settings and their values, see
https://docs.djangoproject.com/en/1.11/ref/settings/
"""

import os
import sys

# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

# set apps dir
sys.path.insert(0, os.path.join(BASE_DIR, 'apps'))

# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/1.11/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'a4&=g1ak$7mw9vc!^6#)5@*1r4l!=4wms*rh@9^)-n(cy534u2'

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True

LOGIN_URL = '/login/'

ALLOWED_HOSTS = []

# Application definition

INSTALLED_APPS = [
    # 'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'jumpserver',
    'audits',
    'assets',
    'deploy',
    'monitor',
    'wiki',
    'account',
    'common',
    'debug_toolbar',
    'task',
    'api',
    'rest_framework',
]

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    'debug_toolbar.middleware.DebugToolbarMiddleware',
]

ROOT_URLCONF = 'onestack.urls'

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, 'templates')],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

WSGI_APPLICATION = 'onestack.wsgi.application'

# Database
# https://docs.djangoproject.com/en/1.11/ref/settings/#databases

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        'NAME': 'onestack',
        'USER': 'one',
        'PASSWORD': '',
        'HOST': '127.0.0.1',
        'PORT': 5432,
    }
}

# Password validation
# https://docs.djangoproject.com/en/1.11/ref/settings/#auth-password-validators

AUTH_PASSWORD_VALIDATORS = [
    {
        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
    },
]

# Internationalization
# https://docs.djangoproject.com/en/1.11/topics/i18n/

LANGUAGE_CODE = 'en-us'

TIME_ZONE = 'UTC'

USE_I18N = True

USE_L10N = True

USE_TZ = True

# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.11/howto/static-files/

STATIC_URL = '/static/'

MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')

# 当运行 python manage.py collectstatic 的时候
# STATIC_ROOT 文件夹 是用来将所有 STATICFILES_DIRS 中所有文件夹中的文件，以及各 app 中 static 中的文件都复制过来
# 把这些文件放到一起是为了用 apache/nginx 等部署的时候更方便
# STATIC_ROOT = os.path.join(BASE_DIR, 'static')

STATICFILES_DIRS = (os.path.join(BASE_DIR, "static"),)

AUTH_USER_MODEL = 'account.User'

REST_FRAMEWORK = {
    'DEFAULT_PERMISSION_CLASSES': [
        # 'rest_framework.permissions.DjangoModelPermissionsOrAnonReadOnly'
        'rest_framework.authentication.BasicAuthentication',
        'rest_framework.authentication.SessionAuthentication',
    ]
}

CONFIG_DEFAULTS = {
    # Toolbar options
    'RESULTS_CACHE_SIZE': 3,
    'SHOW_COLLAPSED': True,
    # Panel options
    'SQL_WARNING_THRESHOLD': 100,   # milliseconds
}
<commit_msg>comment off<commit_after>"""
Django settings for onestack project.

Generated by 'django-admin startproject' using Django 1.11.3.

For more information on this file, see
https://docs.djangoproject.com/en/1.11/topics/settings/

For the full list of settings and their values, see
https://docs.djangoproject.com/en/1.11/ref/settings/
"""

import os
import sys

# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

# set apps dir
sys.path.insert(0, os.path.join(BASE_DIR, 'apps'))

# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/1.11/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'a4&=g1ak$7mw9vc!^6#)5@*1r4l!=4wms*rh@9^)-n(cy534u2'

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True

LOGIN_URL = '/login/'

ALLOWED_HOSTS = []

# Application definition

INSTALLED_APPS = [
    # 'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'jumpserver',
    'audits',
    'assets',
    'deploy',
    'monitor',
    'wiki',
    'account',
    'common',
    'debug_toolbar',
    'task',
    #'api',
    'rest_framework',
]

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    'debug_toolbar.middleware.DebugToolbarMiddleware',
]

ROOT_URLCONF = 'onestack.urls'

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, 'templates')],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

WSGI_APPLICATION = 'onestack.wsgi.application'

# Database
# https://docs.djangoproject.com/en/1.11/ref/settings/#databases

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        'NAME': 'onestack',
        'USER': 'one',
        'PASSWORD': '',
        'HOST': '127.0.0.1',
        'PORT': 5432,
    }
}

# Password validation
# https://docs.djangoproject.com/en/1.11/ref/settings/#auth-password-validators

AUTH_PASSWORD_VALIDATORS = [
    {
        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
    },
]

# Internationalization
# https://docs.djangoproject.com/en/1.11/topics/i18n/

LANGUAGE_CODE = 'en-us'

TIME_ZONE = 'UTC'

USE_I18N = True

USE_L10N = True

USE_TZ = True

# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.11/howto/static-files/

STATIC_URL = '/static/'

MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')

# 当运行 python manage.py collectstatic 的时候
# STATIC_ROOT 文件夹 是用来将所有 STATICFILES_DIRS 中所有文件夹中的文件，以及各 app 中 static 中的文件都复制过来
# 把这些文件放到一起是为了用 apache/nginx 等部署的时候更方便
# STATIC_ROOT = os.path.join(BASE_DIR, 'static')

STATICFILES_DIRS = (os.path.join(BASE_DIR, "static"),)

AUTH_USER_MODEL = 'account.User'

REST_FRAMEWORK = {
    'DEFAULT_PERMISSION_CLASSES': [
        # 'rest_framework.permissions.DjangoModelPermissionsOrAnonReadOnly'
        'rest_framework.authentication.BasicAuthentication',
        'rest_framework.authentication.SessionAuthentication',
    ]
}

CONFIG_DEFAULTS = {
    # Toolbar options
    'RESULTS_CACHE_SIZE': 3,
    'SHOW_COLLAPSED': True,
    # Panel options
    'SQL_WARNING_THRESHOLD': 100,   # milliseconds
}
<|endoftext|>


<commit_before>import re

from django.apps import apps
from django.conf import settings
from django.contrib.auth import get_user_model
from django.core.urlresolvers import reverse_lazy
from django.db.models import Count
from django.shortcuts import redirect
from django.views.generic.base import TemplateView, View
from django.views.generic.edit import DeleteView

from oauth2_provider.models import (
    get_application_model as get_oauth2_application_model)

from common.mixins import LargePanelMixin, NeverCacheMixin, PrivateMixin
from common.utils import (app_label_to_user_data_model, get_source_labels,
                          get_source_labels_and_configs,
                          querydict_from_dict)
from common.views import BaseOAuth2AuthorizationView

from data_import.models import DataFile
from public_data.models import PublicDataAccess
from private_sharing.models import DataRequestProject, DataRequestProjectMember

from .mixins import SourcesContextMixin
from .models import Member

User = get_user_model()

class SourceDataFilesDeleteView(PrivateMixin, DeleteView):
    """
    Let the user delete all datafiles for a source. Note that DeleteView was
    written with a single object in mind but will happily delete a QuerySet due
    to duck-typing.
    """
    template_name = 'member/my-member-source-data-files-delete.html'
    success_url = reverse_lazy('my-member-research-data')

    def get_object(self, queryset=None):
        source = self.kwargs['source']

        return DataFile.objects.filter(user=self.request.user, source=source)

    def get_context_data(self, **kwargs):
        """
        Add the source to the request context.
        """
        context = super(SourceDataFilesDeleteView, self).get_context_data(
            **kwargs)

        context.update({
            'source': self.kwargs['source'],
        })

        return context

class ExceptionView(View):
    """
    Raises an exception for testing purposes.
    """
    @staticmethod
    def get(request):  # pylint: disable=unused-argument
        raise Exception('A test exception.')

class OAuth2LoginView(LargePanelMixin, TemplateView):
    """
    Give people authorizing with us the ability to easily sign up or log in.
    """
    template_name = 'account/login-oauth2.html'

    def get_context_data(self, **kwargs):
        next_querystring = querydict_from_dict({
            'next': self.request.GET.get('next')
        }).urlencode()

        kwargs.update({
            'next_querystring': next_querystring,
            'connection': self.request.GET.get('connection'),
        })

        return super(OAuth2LoginView, self).get_context_data(**kwargs)

class AuthorizationView(BaseOAuth2AuthorizationView):
    """
    Add checks for study apps to the OAuth2 authorization view.
    """

    is_study_app = False

    @staticmethod
    def _check_study_app_request(context):
        """
        Return true if this OAuth2 request matches a study app
        """
        # NOTE: This assumes 'scopes' was overwritten by get_context_data.
        scopes = [x[0] for x in context['scopes']]

        try:
            scopes.remove('read')
            scopes.remove('write')
        except ValueError:
            return False

        if len(scopes) != 1:
            return False

        app_label = re.sub('-', '_', scopes[0])
        app = apps.get_app_config(app_label)

        if app and app.verbose_name == context['application'].name:
            return app_label

        return False

    def get_context_data(self, **kwargs):
        context = super(AuthorizationView, self).get_context_data(**kwargs)

        def scope_key(zipped_scope):
            scope, _ = zipped_scope

            # Sort 'write' second to last
            if scope == 'write':
                return 'zzy'

            # Sort 'read' last
            if scope == 'read':
                return 'zzz'

            # Sort all other scopes alphabetically
            return scope

        def scope_class(scope):
            if scope in ['read', 'write']:
                return 'info'

            return 'primary'

        zipped_scopes = zip(context['scopes'], context['scopes_descriptions'])
        zipped_scopes.sort(key=scope_key)

        context['scopes'] = [(scope, description, scope_class(scope))
                             for scope, description in zipped_scopes]

        # For custom display when it's for a study app connection.
        app_label = self._check_study_app_request(context)

        if app_label:
            self.is_study_app = True

            context['app'] = apps.get_app_config(app_label)
            context['app_label'] = app_label
            context['is_study_app'] = True
            context['scopes'] = [x for x in context['scopes']
                                 if x[0] != 'read' and x[0] != 'write']

        return context

    def get_template_names(self):
        if self.is_study_app:
            return ['oauth2_provider/finalize.html']

        return [self.template_name]

class ActivitiesView(NeverCacheMixin, SourcesContextMixin, TemplateView):
    """
    A simple TemplateView for the activities page that doesn't cache.
    """

    template_name = 'pages/activities.html'

LABELS = {
    'share-data': {
        'name': 'Share data',
        'class': 'label-success',
    },
    'academic-non-profit': {
        'name': 'Academic/<br>Non-profit',
        'class': 'label-info'
    },
    'study': {
        'name': 'Study',
        'class': 'label-primary'
    },
    'data-source': {
        'name': 'Data source',
        'class': 'label-warning'
    },
    'inactive': {
        'name': 'Inactive',
        'class': 'label-default',
    },
    'in-development': {
        'name': 'In development',
        'class': 'label-default',
    },
}

def get_labels(*args):
    """
    Convenience method to filter labels.
    """
    return {name: value for name, value in LABELS.items() if name in args}

class ActivitiesGridView(NeverCacheMixin, SourcesContextMixin, TemplateView):
    """
    A simple TemplateView for the activities page that doesn't cache.
    """

    template_name = 'pages/activities-grid.html'

    def get_context_data(self, *args, **kwargs):
        context = super(ActivitiesGridView, self).get_context_data(*args,
                                                                   **kwargs)
        sources = dict(get_source_labels_and_configs())
        activities = {source: {} for source in sources.keys()}

        for label, source in sources.items():
            user_data_model = app_label_to_user_data_model(label)
            is_connected = False

            if self.request.user.is_authenticated():
                if hasattr(user_data_model, 'objects'):
                    is_connected = user_data_model.objects.get(
                        user=self.request.user).is_connected
                elif hasattr(source, 'user_data'):
                    is_connected = source.user_data(
                        user=self.request.user).is_connected

            activities[label] = {
                'verbose_name': source.verbose_name,
                'badge_path': label + '/images/badge.png',
                'data_source': True,
                'labels': get_labels('data-source'),
                'leader': source.leader,
                'organization': source.organization,
                'description': source.description,
                'in_development': bool(source.in_development),
                'active': True,
                'info_url': source.href_learn,
                'add_data_text': source.connect_verb + ' data',
                'add_data_url': source.href_connect,
                'is_connected': is_connected,
            }

        for project in DataRequestProject.objects.filter(approved=True,
                                                         active=True):
            activity = {
                'verbose_name': project.name,
                'share_data': True,
                'labels': get_labels('share-data'),
                'leader': project.leader,
                'organization': project.organization,
                'description': project.long_description,
                'in_development': False,
                'active': True,
                'info_url': project.info_url,
                'add_data_text': 'share data',
            }

            if project.type == 'on-site':
                activity['join_url'] = reverse_lazy(
                    'direct-sharing:join-on-site',
                    kwargs={'slug': project.slug})
            else:
                activity['join_url'] = (
                    project.oauth2datarequestproject.enrollment_url)

            if self.request.user.is_authenticated():
                try:
                    DataRequestProjectMember.objects.get(
                        member=self.request.user.member,
                        project=project,
                        joined=True,
                        authorized=True,
                        revoked=False)

                    activity['is_connected'] = True
                except DataRequestProjectMember.DoesNotExist:
                    activity['is_connected'] = False
            else:
                activity['is_connected'] = False

            try:
                activity['badge_path'] = project.badge_image.url,
            except ValueError:
                pass

            activities[project.slug] = activity

        # TODO: move academic/non-profit to AppConfig
        for study_label in ['american_gut', 'go_viral', 'pgp', 'wildlife',
                            'mpower']:
            activities[study_label]['labels'].update(
                get_labels('academic-non-profit'))

        activities['wildlife']['active'] = False

        # add custom info for public_data_sharing, data_selfie
        activities.update({
            'public_data_sharing': {
                'verbose_name': 'Public Data Sharing',
                'active': True,
                'badge_path': 'images/public-data-sharing-badge.png',
                'share_data': True,
                'labels': get_labels('share-data', 'academic-non-profit',
                                     'study'),
                'leader': 'Madeleine Ball',
                'organization': 'PersonalGenomes.org',
                'description': 'Make your data a public resource! '
                               "If you join our study, you'll be able "
                               'to turn public sharing on (and off) for '
                               'individual data sources on your research '
                               'data page.',
                'join_url': reverse_lazy('public-data'),
                'is_connected': (
                    True if self.request.user.is_authenticated() and
                    self.request.user.member.public_data_participant.enrolled
                    else False),
            }
        })

        for _, activity in activities.items():
            if 'labels' not in activity:
                activity['labels'] = {}

            if activity['leader'] and activity['organization']:
                activity['labels'].update(get_labels('study'))

            if not activity['active']:
                activity['labels'].update(get_labels('inactive'))

            if activity.get('in_development'):
                activity['labels'].update(get_labels('in-development'))

        for _, activity in activities.items():
            classes = activity['labels'].keys()

            if activity['is_connected']:
                classes.append('connected')

            activity['classes'] = ' '.join(classes)

        activities = sorted(activities.values(),
                            key=lambda value: value['verbose_name'].lower())

        context.update({'activities': activities})

        return context

class StatisticsView(TemplateView):
    """
    A simple TemplateView for Open Humans statistics.

    @madprime 2015/12/10: Updates on how file sharing was managed per-source
    broke this. This fixed version is very slow & doesn't restore all features.
    """
    template_name = 'pages/statistics.html'

    @staticmethod
    def get_inbound_connections():
        """
        Inbound connections is currently shorthand for study connections.

        Inbound connections can be data-push integrations like PGP or hosted
        studies like Keeping Pace; "inbound" means that we host the OAuth2
        provider.
        """
        application_model = get_oauth2_application_model()

        return (application_model.objects
                .order_by('name')
                .annotate(count=Count('accesstoken__user', distinct=True)))

    def get_source_connections(self):
        source_connections = {}
        private_source_connections = {}
        public_source_connections = {}

        for source_name in get_source_labels():
            source_connections[source_name] = [
                {
                    'user': user,
                    'public_data_access': PublicDataAccess.objects.filter(
                        participant=user.member.public_data_participant,
                        data_source=source_name)
                }
                for user in User.objects.filter(member__isnull=False)
                if getattr(user, source_name).is_connected]

            private_source_connections[source_name] = [
                x for x in source_connections[source_name] if
                not x['public_data_access'] or
                not x['public_data_access'][0].is_public]

            public_source_connections[source_name] = [
                x for x in source_connections[source_name] if
                x['public_data_access'] and
                x['public_data_access'][0].is_public]

        self.source_connections = source_connections
        self.private_source_connections = private_source_connections
        self.public_source_connections = public_source_connections

    @staticmethod
    def get_two_plus_users(is_public):
        """Currently broken."""
        return None

    def get_two_plus_public(self):
        """Currently broken."""
        return None

    def get_two_plus_private(self):
        """Currently broken."""
        return None

    def get_context_data(self, **kwargs):
        context = super(StatisticsView, self).get_context_data(**kwargs)
        self.get_source_connections()

        context.update({
            'members': Member.objects.count(),
            'studies': self.get_inbound_connections(),
            'data_sources': self.source_connections,
            'private_sources': self.private_source_connections,
            'public_sources': self.public_source_connections,
            'public_two_plus': self.get_two_plus_public,
            'private_two_plus': self.get_two_plus_private,
        })

        return context

class WelcomeView(PrivateMixin, SourcesContextMixin, TemplateView):
    """
    A template view that doesn't cache, and is private.
    """
    template_name = 'welcome/index.html'

class PGPInterstitialView(PrivateMixin, TemplateView):
    """
    An interstitial view shown to PGP members with 1 or more private PGP
    datasets and no public PGP datasets.
    """
    template_name = 'pages/pgp-interstitial.html'

    def get(self, request, *args, **kwargs):
        request.user.member.seen_pgp_interstitial = True
        request.user.member.save()

        return super(PGPInterstitialView, self).get(request, *args, **kwargs)

class HomeView(TemplateView):
    """
    Redirect to the welcome page if the user is logged in.
    """
    template_name = 'pages/home.html'

    def get(self, request, *args, **kwargs):
        if not request.user.is_anonymous():
            return redirect(settings.LOGIN_REDIRECT_URL)

        return super(HomeView, self).get(request, *args, **kwargs)

class ResearchPageView(TemplateView):
    """
    Add current sources to template context.
    """

    template_name = 'pages/research.html'

    def get_context_data(self, **kwargs):
        """
        Add sources.
        """
        context = super(ResearchPageView, self).get_context_data(**kwargs)

        context.update({
            'source_list': get_source_labels_and_configs(),
        })

        return context
<commit_msg>🔧 tweak DataRequestProject display<commit_after>import re

from django.apps import apps
from django.conf import settings
from django.contrib.auth import get_user_model
from django.core.urlresolvers import reverse_lazy
from django.db.models import Count
from django.shortcuts import redirect
from django.views.generic.base import TemplateView, View
from django.views.generic.edit import DeleteView

from oauth2_provider.models import (
    get_application_model as get_oauth2_application_model)

from common.mixins import LargePanelMixin, NeverCacheMixin, PrivateMixin
from common.utils import (app_label_to_user_data_model, get_source_labels,
                          get_source_labels_and_configs,
                          querydict_from_dict)
from common.views import BaseOAuth2AuthorizationView

from data_import.models import DataFile
from public_data.models import PublicDataAccess
from private_sharing.models import DataRequestProject, DataRequestProjectMember

from .mixins import SourcesContextMixin
from .models import Member

User = get_user_model()

class SourceDataFilesDeleteView(PrivateMixin, DeleteView):
    """
    Let the user delete all datafiles for a source. Note that DeleteView was
    written with a single object in mind but will happily delete a QuerySet due
    to duck-typing.
    """
    template_name = 'member/my-member-source-data-files-delete.html'
    success_url = reverse_lazy('my-member-research-data')

    def get_object(self, queryset=None):
        source = self.kwargs['source']

        return DataFile.objects.filter(user=self.request.user, source=source)

    def get_context_data(self, **kwargs):
        """
        Add the source to the request context.
        """
        context = super(SourceDataFilesDeleteView, self).get_context_data(
            **kwargs)

        context.update({
            'source': self.kwargs['source'],
        })

        return context

class ExceptionView(View):
    """
    Raises an exception for testing purposes.
    """
    @staticmethod
    def get(request):  # pylint: disable=unused-argument
        raise Exception('A test exception.')

class OAuth2LoginView(LargePanelMixin, TemplateView):
    """
    Give people authorizing with us the ability to easily sign up or log in.
    """
    template_name = 'account/login-oauth2.html'

    def get_context_data(self, **kwargs):
        next_querystring = querydict_from_dict({
            'next': self.request.GET.get('next')
        }).urlencode()

        kwargs.update({
            'next_querystring': next_querystring,
            'connection': self.request.GET.get('connection'),
        })

        return super(OAuth2LoginView, self).get_context_data(**kwargs)

class AuthorizationView(BaseOAuth2AuthorizationView):
    """
    Add checks for study apps to the OAuth2 authorization view.
    """

    is_study_app = False

    @staticmethod
    def _check_study_app_request(context):
        """
        Return true if this OAuth2 request matches a study app
        """
        # NOTE: This assumes 'scopes' was overwritten by get_context_data.
        scopes = [x[0] for x in context['scopes']]

        try:
            scopes.remove('read')
            scopes.remove('write')
        except ValueError:
            return False

        if len(scopes) != 1:
            return False

        app_label = re.sub('-', '_', scopes[0])
        app = apps.get_app_config(app_label)

        if app and app.verbose_name == context['application'].name:
            return app_label

        return False

    def get_context_data(self, **kwargs):
        context = super(AuthorizationView, self).get_context_data(**kwargs)

        def scope_key(zipped_scope):
            scope, _ = zipped_scope

            # Sort 'write' second to last
            if scope == 'write':
                return 'zzy'

            # Sort 'read' last
            if scope == 'read':
                return 'zzz'

            # Sort all other scopes alphabetically
            return scope

        def scope_class(scope):
            if scope in ['read', 'write']:
                return 'info'

            return 'primary'

        zipped_scopes = zip(context['scopes'], context['scopes_descriptions'])
        zipped_scopes.sort(key=scope_key)

        context['scopes'] = [(scope, description, scope_class(scope))
                             for scope, description in zipped_scopes]

        # For custom display when it's for a study app connection.
        app_label = self._check_study_app_request(context)

        if app_label:
            self.is_study_app = True

            context['app'] = apps.get_app_config(app_label)
            context['app_label'] = app_label
            context['is_study_app'] = True
            context['scopes'] = [x for x in context['scopes']
                                 if x[0] != 'read' and x[0] != 'write']

        return context

    def get_template_names(self):
        if self.is_study_app:
            return ['oauth2_provider/finalize.html']

        return [self.template_name]

class ActivitiesView(NeverCacheMixin, SourcesContextMixin, TemplateView):
    """
    A simple TemplateView for the activities page that doesn't cache.
    """

    template_name = 'pages/activities.html'

LABELS = {
    'share-data': {
        'name': 'Share data',
        'class': 'label-success',
    },
    'academic-non-profit': {
        'name': 'Academic/<br>Non-profit',
        'class': 'label-info'
    },
    'study': {
        'name': 'Study',
        'class': 'label-primary'
    },
    'data-source': {
        'name': 'Data source',
        'class': 'label-warning'
    },
    'inactive': {
        'name': 'Inactive',
        'class': 'label-default',
    },
    'in-development': {
        'name': 'In development',
        'class': 'label-default',
    },
}

def get_labels(*args):
    """
    Convenience method to filter labels.
    """
    return {name: value for name, value in LABELS.items() if name in args}

class ActivitiesGridView(NeverCacheMixin, SourcesContextMixin, TemplateView):
    """
    A simple TemplateView for the activities page that doesn't cache.
    """

    template_name = 'pages/activities-grid.html'

    def get_context_data(self, *args, **kwargs):
        context = super(ActivitiesGridView, self).get_context_data(*args,
                                                                   **kwargs)
        sources = dict(get_source_labels_and_configs())
        activities = {source: {} for source in sources.keys()}

        for label, source in sources.items():
            user_data_model = app_label_to_user_data_model(label)
            is_connected = False

            if self.request.user.is_authenticated():
                if hasattr(user_data_model, 'objects'):
                    is_connected = user_data_model.objects.get(
                        user=self.request.user).is_connected
                elif hasattr(source, 'user_data'):
                    is_connected = source.user_data(
                        user=self.request.user).is_connected

            activity = {
                'verbose_name': source.verbose_name,
                'badge_path': label + '/images/badge.png',
                'data_source': True,
                'labels': get_labels('data-source'),
                'leader': source.leader,
                'organization': source.organization,
                'description': source.description,
                'in_development': bool(source.in_development),
                'active': True,
                'info_url': source.href_learn,
                'add_data_text': source.connect_verb + ' data',
                'add_data_url': source.href_connect,
                'is_connected': is_connected,
            }

            if activity['leader'] and activity['organization']:
                activity['labels'].update(get_labels('study'))

            activities[label] = activity

        for project in DataRequestProject.objects.filter(approved=True,
                                                         active=True):
            activity = {
                'verbose_name': project.name,
                'share_data': True,
                'labels': get_labels('share-data'),
                'leader': project.leader,
                'organization': project.organization,
                'description': project.short_description,
                'in_development': False,
                'active': True,
                'info_url': project.info_url,
                'add_data_text': 'share data',
            }

            if project.type == 'on-site':
                activity['join_url'] = reverse_lazy(
                    'direct-sharing:join-on-site',
                    kwargs={'slug': project.slug})
            else:
                activity['join_url'] = (
                    project.oauth2datarequestproject.enrollment_url)

            if project.is_academic_or_nonprofit:
                activity['labels'].update(get_labels('academic-non-profit'))

            if project.is_study:
                activity['labels'].update(get_labels('study'))

            if self.request.user.is_authenticated():
                try:
                    DataRequestProjectMember.objects.get(
                        member=self.request.user.member,
                        project=project,
                        joined=True,
                        authorized=True,
                        revoked=False)

                    activity['is_connected'] = True
                except DataRequestProjectMember.DoesNotExist:
                    activity['is_connected'] = False
            else:
                activity['is_connected'] = False

            try:
                activity['badge_path'] = project.badge_image.url,
            except ValueError:
                pass

            activities[project.slug] = activity

        # TODO: move academic/non-profit to AppConfig
        for study_label in ['american_gut', 'go_viral', 'pgp', 'wildlife',
                            'mpower']:
            activities[study_label]['labels'].update(
                get_labels('academic-non-profit'))

        activities['wildlife']['active'] = False

        # add custom info for public_data_sharing, data_selfie
        activities.update({
            'public_data_sharing': {
                'verbose_name': 'Public Data Sharing',
                'active': True,
                'badge_path': 'images/public-data-sharing-badge.png',
                'share_data': True,
                'labels': get_labels('share-data', 'academic-non-profit',
                                     'study'),
                'leader': 'Madeleine Ball',
                'organization': 'PersonalGenomes.org',
                'description': 'Make your data a public resource! '
                               "If you join our study, you'll be able "
                               'to turn public sharing on (and off) for '
                               'individual data sources on your research '
                               'data page.',
                'join_url': reverse_lazy('public-data'),
                'is_connected': (
                    True if self.request.user.is_authenticated() and
                    self.request.user.member.public_data_participant.enrolled
                    else False),
            }
        })

        for _, activity in activities.items():
            if 'labels' not in activity:
                activity['labels'] = {}

            if not activity['active']:
                activity['labels'].update(get_labels('inactive'))

            if activity.get('in_development'):
                activity['labels'].update(get_labels('in-development'))

        for _, activity in activities.items():
            classes = activity['labels'].keys()

            if activity['is_connected']:
                classes.append('connected')

            activity['classes'] = ' '.join(classes)

        activities = sorted(activities.values(),
                            key=lambda value: value['verbose_name'].lower())

        context.update({'activities': activities})

        return context

class StatisticsView(TemplateView):
    """
    A simple TemplateView for Open Humans statistics.

    @madprime 2015/12/10: Updates on how file sharing was managed per-source
    broke this. This fixed version is very slow & doesn't restore all features.
    """
    template_name = 'pages/statistics.html'

    @staticmethod
    def get_inbound_connections():
        """
        Inbound connections is currently shorthand for study connections.

        Inbound connections can be data-push integrations like PGP or hosted
        studies like Keeping Pace; "inbound" means that we host the OAuth2
        provider.
        """
        application_model = get_oauth2_application_model()

        return (application_model.objects
                .order_by('name')
                .annotate(count=Count('accesstoken__user', distinct=True)))

    def get_source_connections(self):
        source_connections = {}
        private_source_connections = {}
        public_source_connections = {}

        for source_name in get_source_labels():
            source_connections[source_name] = [
                {
                    'user': user,
                    'public_data_access': PublicDataAccess.objects.filter(
                        participant=user.member.public_data_participant,
                        data_source=source_name)
                }
                for user in User.objects.filter(member__isnull=False)
                if getattr(user, source_name).is_connected]

            private_source_connections[source_name] = [
                x for x in source_connections[source_name] if
                not x['public_data_access'] or
                not x['public_data_access'][0].is_public]

            public_source_connections[source_name] = [
                x for x in source_connections[source_name] if
                x['public_data_access'] and
                x['public_data_access'][0].is_public]

        self.source_connections = source_connections
        self.private_source_connections = private_source_connections
        self.public_source_connections = public_source_connections

    @staticmethod
    def get_two_plus_users(is_public):
        """Currently broken."""
        return None

    def get_two_plus_public(self):
        """Currently broken."""
        return None

    def get_two_plus_private(self):
        """Currently broken."""
        return None

    def get_context_data(self, **kwargs):
        context = super(StatisticsView, self).get_context_data(**kwargs)
        self.get_source_connections()

        context.update({
            'members': Member.objects.count(),
            'studies': self.get_inbound_connections(),
            'data_sources': self.source_connections,
            'private_sources': self.private_source_connections,
            'public_sources': self.public_source_connections,
            'public_two_plus': self.get_two_plus_public,
            'private_two_plus': self.get_two_plus_private,
        })

        return context

class WelcomeView(PrivateMixin, SourcesContextMixin, TemplateView):
    """
    A template view that doesn't cache, and is private.
    """
    template_name = 'welcome/index.html'

class PGPInterstitialView(PrivateMixin, TemplateView):
    """
    An interstitial view shown to PGP members with 1 or more private PGP
    datasets and no public PGP datasets.
    """
    template_name = 'pages/pgp-interstitial.html'

    def get(self, request, *args, **kwargs):
        request.user.member.seen_pgp_interstitial = True
        request.user.member.save()

        return super(PGPInterstitialView, self).get(request, *args, **kwargs)

class HomeView(TemplateView):
    """
    Redirect to the welcome page if the user is logged in.
    """
    template_name = 'pages/home.html'

    def get(self, request, *args, **kwargs):
        if not request.user.is_anonymous():
            return redirect(settings.LOGIN_REDIRECT_URL)

        return super(HomeView, self).get(request, *args, **kwargs)

class ResearchPageView(TemplateView):
    """
    Add current sources to template context.
    """

    template_name = 'pages/research.html'

    def get_context_data(self, **kwargs):
        """
        Add sources.
        """
        context = super(ResearchPageView, self).get_context_data(**kwargs)

        context.update({
            'source_list': get_source_labels_and_configs(),
        })

        return context
<|endoftext|>


<commit_before>from django import VERSION as DJANGO_VERSION
from django import template
from django.conf import settings
if DJANGO_VERSION[0] == 1 and DJANGO_VERSION[1] <= 9:
    from django.core.urlresolvers import reverse
else:
    from django.urls import reverse

register = template.Library()

@register.simple_tag(takes_context=True)
def active_link(context, viewname, css_class=None, strict=None):
    """
    Renders the given CSS class if the request path matches the path of the view.
    :param context: The context where the tag was called. Used to access the request object.
    :param viewname: The name of the view (include namespaces if any).
    :param css_class: The CSS class to render.
    :param strict: If True, the tag will perform an exact match with the request path.
    :return:
    """
    if css_class is None:
        css_class = getattr(settings, 'ACTIVE_LINK_CSS_CLASS', 'active')

    if strict is None:
        strict = getattr(settings, 'ACTIVE_LINK_STRICT', False)

    request = context.get('request')
    if request is None:
        # Can't work without the request object.
        return ''
    path = reverse(viewname)
    if strict:
        active = request.path == path
    else:
        active = path in request.path
    if active:
        return css_class
    return ''
<commit_msg>Improve how the active link is checked<commit_after>from django import VERSION as DJANGO_VERSION
from django import template
from django.conf import settings
if DJANGO_VERSION[0] == 1 and DJANGO_VERSION[1] <= 9:
    from django.core.urlresolvers import reverse
else:
    from django.urls import reverse

register = template.Library()

@register.simple_tag(takes_context=True)
def active_link(context, viewname, css_class=None, strict=None):
    """
    Renders the given CSS class if the request path matches the path of the view.
    :param context: The context where the tag was called. Used to access the request object.
    :param viewname: The name of the view (include namespaces if any).
    :param css_class: The CSS class to render.
    :param strict: If True, the tag will perform an exact match with the request path.
    :return:
    """
    if css_class is None:
        css_class = getattr(settings, 'ACTIVE_LINK_CSS_CLASS', 'active')

    if strict is None:
        strict = getattr(settings, 'ACTIVE_LINK_STRICT', False)

    request = context.get('request')
    if request is None:
        # Can't work without the request object.
        return ''
    path = reverse(viewname)
    if strict:
        active = request.path == path
    else:
        active = request.path.find(path) == 0
    if active:
        return css_class
    return ''
<|endoftext|>


<commit_before>import cv2 as cv
import argparse
import sys
import numpy as np

backends = (cv.dnn.DNN_BACKEND_DEFAULT, cv.dnn.DNN_BACKEND_HALIDE, cv.dnn.DNN_BACKEND_INFERENCE_ENGINE, cv.dnn.DNN_BACKEND_OPENCV)
targets = (cv.dnn.DNN_TARGET_CPU, cv.dnn.DNN_TARGET_OPENCL, cv.dnn.DNN_TARGET_OPENCL_FP16, cv.dnn.DNN_TARGET_MYRIAD)

parser = argparse.ArgumentParser(description='Use this script to run object detection deep learning networks using OpenCV.')
parser.add_argument('--input', help='Path to input image or video file. Skip this argument to capture frames from a camera.')
parser.add_argument('--model', required=True,
                    help='Path to a binary file of model contains trained weights. '
                         'It could be a file with extensions .caffemodel (Caffe), '
                         '.pb (TensorFlow), .t7 or .net (Torch), .weights (Darknet)')
parser.add_argument('--config',
                    help='Path to a text file of model contains network configuration. '
                         'It could be a file with extensions .prototxt (Caffe), .pbtxt (TensorFlow), .cfg (Darknet)')
parser.add_argument('--framework', choices=['caffe', 'tensorflow', 'torch', 'darknet'],
                    help='Optional name of an origin framework of the model. '
                         'Detect it automatically if it does not set.')
parser.add_argument('--classes', help='Optional path to a text file with names of classes to label detected objects.')
parser.add_argument('--mean', nargs='+', type=float, default=[0, 0, 0],
                    help='Preprocess input image by subtracting mean values. '
                         'Mean values should be in BGR order.')
parser.add_argument('--scale', type=float, default=1.0,
                    help='Preprocess input image by multiplying on a scale factor.')
parser.add_argument('--width', type=int,
                    help='Preprocess input image by resizing to a specific width.')
parser.add_argument('--height', type=int,
                    help='Preprocess input image by resizing to a specific height.')
parser.add_argument('--rgb', action='store_true',
                    help='Indicate that model works with RGB input images instead BGR ones.')
parser.add_argument('--thr', type=float, default=0.5, help='Confidence threshold')
parser.add_argument('--nms', type=float, default=0.4, help='Non-maximum suppression threshold')
parser.add_argument('--backend', choices=backends, default=cv.dnn.DNN_BACKEND_DEFAULT, type=int,
                    help="Choose one of computation backends: "
                         "%d: automatically (by default), "
                         "%d: Halide language (http://halide-lang.org/), "
                         "%d: Intel's Deep Learning Inference Engine (https://software.intel.com/openvino-toolkit), "
                         "%d: OpenCV implementation" % backends)
parser.add_argument('--target', choices=targets, default=cv.dnn.DNN_TARGET_CPU, type=int,
                    help='Choose one of target computation devices: '
                         '%d: CPU target (by default), '
                         '%d: OpenCL, '
                         '%d: OpenCL fp16 (half-float precision), '
                         '%d: VPU' % targets)
args = parser.parse_args()

# Load names of classes
classes = None
if args.classes:
    with open(args.classes, 'rt') as f:
        classes = f.read().rstrip('\n').split('\n')

# Load a network
net = cv.dnn.readNet(args.model, args.config, args.framework)
net.setPreferableBackend(args.backend)
net.setPreferableTarget(args.target)

confThreshold = args.thr
nmsThreshold = args.nms

def getOutputsNames(net):
    layersNames = net.getLayerNames()
    return [layersNames[i[0] - 1] for i in net.getUnconnectedOutLayers()]

def postprocess(frame, outs):
    frameHeight = frame.shape[0]
    frameWidth = frame.shape[1]

    def drawPred(classId, conf, left, top, right, bottom):
        # Draw a bounding box.
        cv.rectangle(frame, (left, top), (right, bottom), (0, 255, 0))

        label = '%.2f' % conf

        # Print a label of class.
        if classes:
            assert(classId < len(classes))
            label = '%s: %s' % (classes[classId], label)

        labelSize, baseLine = cv.getTextSize(label, cv.FONT_HERSHEY_SIMPLEX, 0.5, 1)
        top = max(top, labelSize[1])
        cv.rectangle(frame, (left, top - labelSize[1]), (left + labelSize[0], top + baseLine), (255, 255, 255), cv.FILLED)
        cv.putText(frame, label, (left, top), cv.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 0))

    layerNames = net.getLayerNames()
    lastLayerId = net.getLayerId(layerNames[-1])
    lastLayer = net.getLayer(lastLayerId)

    classIds = []
    confidences = []
    boxes = []
    if net.getLayer(0).outputNameToIndex('im_info') != -1:  # Faster-RCNN or R-FCN
        # Network produces output blob with a shape 1x1xNx7 where N is a number of
        # detections and an every detection is a vector of values
        # [batchId, classId, confidence, left, top, right, bottom]
        for out in outs:
            for detection in out[0, 0]:
                confidence = detection[2]
                if confidence > confThreshold:
                    left = int(detection[3])
                    top = int(detection[4])
                    right = int(detection[5])
                    bottom = int(detection[6])
                    width = right - left + 1
                    height = bottom - top + 1
                    classIds.append(int(detection[1]) - 1)  # Skip background label
                    confidences.append(float(confidence))
                    boxes.append([left, top, width, height])
    elif lastLayer.type == 'DetectionOutput':
        # Network produces output blob with a shape 1x1xNx7 where N is a number of
        # detections and an every detection is a vector of values
        # [batchId, classId, confidence, left, top, right, bottom]
        for out in outs:
            for detection in out[0, 0]:
                confidence = detection[2]
                if confidence > confThreshold:
                    left = int(detection[3] * frameWidth)
                    top = int(detection[4] * frameHeight)
                    right = int(detection[5] * frameWidth)
                    bottom = int(detection[6] * frameHeight)
                    width = right - left + 1
                    height = bottom - top + 1
                    classIds.append(int(detection[1]) - 1)  # Skip background label
                    confidences.append(float(confidence))
                    boxes.append([left, top, width, height])
    elif lastLayer.type == 'Region':
        # Network produces output blob with a shape NxC where N is a number of
        # detected objects and C is a number of classes + 4 where the first 4
        # numbers are [center_x, center_y, width, height]
        classIds = []
        confidences = []
        boxes = []
        for out in outs:
            for detection in out:
                scores = detection[5:]
                classId = np.argmax(scores)
                confidence = scores[classId]
                if confidence > confThreshold:
                    center_x = int(detection[0] * frameWidth)
                    center_y = int(detection[1] * frameHeight)
                    width = int(detection[2] * frameWidth)
                    height = int(detection[3] * frameHeight)
                    left = center_x - width / 2
                    top = center_y - height / 2
                    classIds.append(classId)
                    confidences.append(float(confidence))
                    boxes.append([left, top, width, height])
    else:
        print('Unknown output layer type: ' + lastLayer.type)
        exit()

    indices = cv.dnn.NMSBoxes(boxes, confidences, confThreshold, nmsThreshold)
    for i in indices:
        i = i[0]
        box = boxes[i]
        left = box[0]
        top = box[1]
        width = box[2]
        height = box[3]
        drawPred(classIds[i], confidences[i], left, top, left + width, top + height)

# Process inputs
winName = 'Deep learning object detection in OpenCV'
cv.namedWindow(winName, cv.WINDOW_NORMAL)

def callback(pos):
    global confThreshold
    confThreshold = pos / 100.0

cv.createTrackbar('Confidence threshold, %', winName, int(confThreshold * 100), 99, callback)

cap = cv.VideoCapture(args.input if args.input else 0)
while cv.waitKey(1) < 0:
    hasFrame, frame = cap.read()
    if not hasFrame:
        cv.waitKey()
        break

    frameHeight = frame.shape[0]
    frameWidth = frame.shape[1]

    # Create a 4D blob from a frame.
    inpWidth = args.width if args.width else frameWidth
    inpHeight = args.height if args.height else frameHeight
    blob = cv.dnn.blobFromImage(frame, args.scale, (inpWidth, inpHeight), args.mean, args.rgb, crop=False)

    # Run a model
    net.setInput(blob)
    if net.getLayer(0).outputNameToIndex('im_info') != -1:  # Faster-RCNN or R-FCN
        frame = cv.resize(frame, (inpWidth, inpHeight))
        net.setInput(np.array([[inpHeight, inpWidth, 1.6]], dtype=np.float32), 'im_info')
    outs = net.forward(getOutputsNames(net))

    postprocess(frame, outs)

    # Put efficiency information.
    t, _ = net.getPerfProfile()
    label = 'Inference time: %.2f ms' % (t * 1000.0 / cv.getTickFrequency())
    cv.putText(frame, label, (0, 15), cv.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0))

    cv.imshow(winName, frame)
<commit_msg>Fixed that object_detection.py does not work in python3.<commit_after>import cv2 as cv
import argparse
import sys
import numpy as np

backends = (cv.dnn.DNN_BACKEND_DEFAULT, cv.dnn.DNN_BACKEND_HALIDE, cv.dnn.DNN_BACKEND_INFERENCE_ENGINE, cv.dnn.DNN_BACKEND_OPENCV)
targets = (cv.dnn.DNN_TARGET_CPU, cv.dnn.DNN_TARGET_OPENCL, cv.dnn.DNN_TARGET_OPENCL_FP16, cv.dnn.DNN_TARGET_MYRIAD)

parser = argparse.ArgumentParser(description='Use this script to run object detection deep learning networks using OpenCV.')
parser.add_argument('--input', help='Path to input image or video file. Skip this argument to capture frames from a camera.')
parser.add_argument('--model', required=True,
                    help='Path to a binary file of model contains trained weights. '
                         'It could be a file with extensions .caffemodel (Caffe), '
                         '.pb (TensorFlow), .t7 or .net (Torch), .weights (Darknet)')
parser.add_argument('--config',
                    help='Path to a text file of model contains network configuration. '
                         'It could be a file with extensions .prototxt (Caffe), .pbtxt (TensorFlow), .cfg (Darknet)')
parser.add_argument('--framework', choices=['caffe', 'tensorflow', 'torch', 'darknet'],
                    help='Optional name of an origin framework of the model. '
                         'Detect it automatically if it does not set.')
parser.add_argument('--classes', help='Optional path to a text file with names of classes to label detected objects.')
parser.add_argument('--mean', nargs='+', type=float, default=[0, 0, 0],
                    help='Preprocess input image by subtracting mean values. '
                         'Mean values should be in BGR order.')
parser.add_argument('--scale', type=float, default=1.0,
                    help='Preprocess input image by multiplying on a scale factor.')
parser.add_argument('--width', type=int,
                    help='Preprocess input image by resizing to a specific width.')
parser.add_argument('--height', type=int,
                    help='Preprocess input image by resizing to a specific height.')
parser.add_argument('--rgb', action='store_true',
                    help='Indicate that model works with RGB input images instead BGR ones.')
parser.add_argument('--thr', type=float, default=0.5, help='Confidence threshold')
parser.add_argument('--nms', type=float, default=0.4, help='Non-maximum suppression threshold')
parser.add_argument('--backend', choices=backends, default=cv.dnn.DNN_BACKEND_DEFAULT, type=int,
                    help="Choose one of computation backends: "
                         "%d: automatically (by default), "
                         "%d: Halide language (http://halide-lang.org/), "
                         "%d: Intel's Deep Learning Inference Engine (https://software.intel.com/openvino-toolkit), "
                         "%d: OpenCV implementation" % backends)
parser.add_argument('--target', choices=targets, default=cv.dnn.DNN_TARGET_CPU, type=int,
                    help='Choose one of target computation devices: '
                         '%d: CPU target (by default), '
                         '%d: OpenCL, '
                         '%d: OpenCL fp16 (half-float precision), '
                         '%d: VPU' % targets)
args = parser.parse_args()

# Load names of classes
classes = None
if args.classes:
    with open(args.classes, 'rt') as f:
        classes = f.read().rstrip('\n').split('\n')

# Load a network
net = cv.dnn.readNet(args.model, args.config, args.framework)
net.setPreferableBackend(args.backend)
net.setPreferableTarget(args.target)

confThreshold = args.thr
nmsThreshold = args.nms

def getOutputsNames(net):
    layersNames = net.getLayerNames()
    return [layersNames[i[0] - 1] for i in net.getUnconnectedOutLayers()]

def postprocess(frame, outs):
    frameHeight = frame.shape[0]
    frameWidth = frame.shape[1]

    def drawPred(classId, conf, left, top, right, bottom):
        # Draw a bounding box.
        cv.rectangle(frame, (left, top), (right, bottom), (0, 255, 0))

        label = '%.2f' % conf

        # Print a label of class.
        if classes:
            assert(classId < len(classes))
            label = '%s: %s' % (classes[classId], label)

        labelSize, baseLine = cv.getTextSize(label, cv.FONT_HERSHEY_SIMPLEX, 0.5, 1)
        top = max(top, labelSize[1])
        cv.rectangle(frame, (left, top - labelSize[1]), (left + labelSize[0], top + baseLine), (255, 255, 255), cv.FILLED)
        cv.putText(frame, label, (left, top), cv.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 0))

    layerNames = net.getLayerNames()
    lastLayerId = net.getLayerId(layerNames[-1])
    lastLayer = net.getLayer(lastLayerId)

    classIds = []
    confidences = []
    boxes = []
    if net.getLayer(0).outputNameToIndex('im_info') != -1:  # Faster-RCNN or R-FCN
        # Network produces output blob with a shape 1x1xNx7 where N is a number of
        # detections and an every detection is a vector of values
        # [batchId, classId, confidence, left, top, right, bottom]
        for out in outs:
            for detection in out[0, 0]:
                confidence = detection[2]
                if confidence > confThreshold:
                    left = int(detection[3])
                    top = int(detection[4])
                    right = int(detection[5])
                    bottom = int(detection[6])
                    width = right - left + 1
                    height = bottom - top + 1
                    classIds.append(int(detection[1]) - 1)  # Skip background label
                    confidences.append(float(confidence))
                    boxes.append([left, top, width, height])
    elif lastLayer.type == 'DetectionOutput':
        # Network produces output blob with a shape 1x1xNx7 where N is a number of
        # detections and an every detection is a vector of values
        # [batchId, classId, confidence, left, top, right, bottom]
        for out in outs:
            for detection in out[0, 0]:
                confidence = detection[2]
                if confidence > confThreshold:
                    left = int(detection[3] * frameWidth)
                    top = int(detection[4] * frameHeight)
                    right = int(detection[5] * frameWidth)
                    bottom = int(detection[6] * frameHeight)
                    width = right - left + 1
                    height = bottom - top + 1
                    classIds.append(int(detection[1]) - 1)  # Skip background label
                    confidences.append(float(confidence))
                    boxes.append([left, top, width, height])
    elif lastLayer.type == 'Region':
        # Network produces output blob with a shape NxC where N is a number of
        # detected objects and C is a number of classes + 4 where the first 4
        # numbers are [center_x, center_y, width, height]
        classIds = []
        confidences = []
        boxes = []
        for out in outs:
            for detection in out:
                scores = detection[5:]
                classId = np.argmax(scores)
                confidence = scores[classId]
                if confidence > confThreshold:
                    center_x = int(detection[0] * frameWidth)
                    center_y = int(detection[1] * frameHeight)
                    width = int(detection[2] * frameWidth)
                    height = int(detection[3] * frameHeight)
                    left = int(center_x - width / 2)
                    top = int(center_y - height / 2)
                    classIds.append(classId)
                    confidences.append(float(confidence))
                    boxes.append([left, top, width, height])
    else:
        print('Unknown output layer type: ' + lastLayer.type)
        exit()

    indices = cv.dnn.NMSBoxes(boxes, confidences, confThreshold, nmsThreshold)
    for i in indices:
        i = i[0]
        box = boxes[i]
        left = box[0]
        top = box[1]
        width = box[2]
        height = box[3]
        drawPred(classIds[i], confidences[i], left, top, left + width, top + height)

# Process inputs
winName = 'Deep learning object detection in OpenCV'
cv.namedWindow(winName, cv.WINDOW_NORMAL)

def callback(pos):
    global confThreshold
    confThreshold = pos / 100.0

cv.createTrackbar('Confidence threshold, %', winName, int(confThreshold * 100), 99, callback)

cap = cv.VideoCapture(args.input if args.input else 0)
while cv.waitKey(1) < 0:
    hasFrame, frame = cap.read()
    if not hasFrame:
        cv.waitKey()
        break

    frameHeight = frame.shape[0]
    frameWidth = frame.shape[1]

    # Create a 4D blob from a frame.
    inpWidth = args.width if args.width else frameWidth
    inpHeight = args.height if args.height else frameHeight
    blob = cv.dnn.blobFromImage(frame, args.scale, (inpWidth, inpHeight), args.mean, args.rgb, crop=False)

    # Run a model
    net.setInput(blob)
    if net.getLayer(0).outputNameToIndex('im_info') != -1:  # Faster-RCNN or R-FCN
        frame = cv.resize(frame, (inpWidth, inpHeight))
        net.setInput(np.array([[inpHeight, inpWidth, 1.6]], dtype=np.float32), 'im_info')
    outs = net.forward(getOutputsNames(net))

    postprocess(frame, outs)

    # Put efficiency information.
    t, _ = net.getPerfProfile()
    label = 'Inference time: %.2f ms' % (t * 1000.0 / cv.getTickFrequency())
    cv.putText(frame, label, (0, 15), cv.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0))

    cv.imshow(winName, frame)
<|endoftext|>


<commit_before>from test_support import verify, verbose
import sys

def check_all(modname):
    names = {}
    try:
        exec "import %s" % modname in names
    except ImportError:
        # Silent fail here seems the best route since some modules
        # may not be available in all environments.
        # Since an ImportError may leave a partial module object in
        # sys.modules, get rid of that first.  Here's what happens if
        # you don't:  importing pty fails on Windows because pty tries to
        # import FCNTL, which doesn't exist.  That raises an ImportError,
        # caught here.  It also leaves a partial pty module in sys.modules.
        # So when test_pty is called later, the import of pty succeeds,
        # but shouldn't.  As a result, test_pty crashes with an
        # AttributeError instead of an ImportError, and regrtest interprets
        # the latter as a test failure (ImportError is treated as "test
        # skipped" -- which is what test_pty should say on Windows).
        try:
            del sys.modules[modname]
        except KeyError:
            pass
        return
    verify(hasattr(sys.modules[modname], "__all__"),
           "%s has no __all__ attribute" % modname)
    names = {}
    exec "from %s import *" % modname in names
    if names.has_key("__builtins__"):
        del names["__builtins__"]
    keys = names.keys()
    keys.sort()
    all = list(sys.modules[modname].__all__) # in case it's a tuple
    all.sort()
    verify(keys==all, "%s != %s" % (keys, all))

if not sys.platform.startswith('java'):
    # In case _socket fails to build, make this test fail more gracefully
    # than an AttributeError somewhere deep in CGIHTTPServer.
    import _socket

check_all("BaseHTTPServer")
check_all("CGIHTTPServer")
check_all("ConfigParser")
check_all("Cookie")
check_all("MimeWriter")
check_all("SimpleHTTPServer")
check_all("SocketServer")
check_all("StringIO")
check_all("UserString")
check_all("aifc")
check_all("atexit")
check_all("audiodev")
check_all("base64")
check_all("bdb")
check_all("binhex")
check_all("calendar")
check_all("cgi")
check_all("cmd")
check_all("code")
check_all("codecs")
check_all("codeop")
check_all("colorsys")
check_all("commands")
check_all("compileall")
check_all("copy")
check_all("copy_reg")
check_all("dbhash")
check_all("dircache")
check_all("dis")
check_all("doctest")
check_all("dospath")
check_all("filecmp")
check_all("fileinput")
check_all("fnmatch")
check_all("fpformat")
check_all("ftplib")
check_all("getopt")
check_all("getpass")
check_all("gettext")
check_all("glob")
check_all("gopherlib")
check_all("gzip")
check_all("htmllib")
check_all("httplib")
check_all("ihooks")
check_all("imaplib")
check_all("imghdr")
check_all("imputil")
check_all("keyword")
check_all("linecache")
check_all("locale")
check_all("macpath")
check_all("macurl2path")
check_all("mailbox")
check_all("mhlib")
check_all("mimetools")
check_all("mimetypes")
check_all("mimify")
check_all("multifile")
check_all("netrc")
check_all("nntplib")
check_all("ntpath")
check_all("os")
check_all("pdb")
check_all("pickle")
check_all("pipes")
check_all("popen2")
check_all("poplib")
check_all("posixpath")
check_all("pprint")
check_all("pre")
check_all("profile")
check_all("pstats")
check_all("pty")
check_all("py_compile")
check_all("pyclbr")
check_all("quopri")
check_all("random")
check_all("re")
check_all("reconvert")
import warnings
warnings.filterwarnings("ignore", ".* regsub .*", DeprecationWarning, "regsub",
                        append=1)
check_all("regsub")
check_all("repr")
check_all("rexec")
check_all("rfc822")
check_all("rlcompleter")
check_all("robotparser")
check_all("sched")
check_all("sgmllib")
check_all("shelve")
check_all("shlex")
check_all("shutil")
check_all("smtpd")
check_all("smtplib")
check_all("sndhdr")
check_all("socket")
check_all("sre")
check_all("stat_cache")
check_all("tabnanny")
check_all("telnetlib")
check_all("tempfile")
check_all("toaiff")
check_all("tokenize")
check_all("traceback")
check_all("tty")
check_all("urllib")
check_all("urlparse")
check_all("uu")
check_all("warnings")
check_all("wave")
check_all("weakref")
check_all("webbrowser")
check_all("xdrlib")
check_all("zipfile")
<commit_msg>Ignore more deprecation warnings.<commit_after>from test_support import verify, verbose
import sys
import warnings

warnings.filterwarnings("ignore", ".* 'pre' .*", DeprecationWarning)
warnings.filterwarnings("ignore", ".* regsub .*", DeprecationWarning)
warnings.filterwarnings("ignore", ".* statcache .*", DeprecationWarning)

def check_all(modname):
    names = {}
    try:
        exec "import %s" % modname in names
    except ImportError:
        # Silent fail here seems the best route since some modules
        # may not be available in all environments.
        # Since an ImportError may leave a partial module object in
        # sys.modules, get rid of that first.  Here's what happens if
        # you don't:  importing pty fails on Windows because pty tries to
        # import FCNTL, which doesn't exist.  That raises an ImportError,
        # caught here.  It also leaves a partial pty module in sys.modules.
        # So when test_pty is called later, the import of pty succeeds,
        # but shouldn't.  As a result, test_pty crashes with an
        # AttributeError instead of an ImportError, and regrtest interprets
        # the latter as a test failure (ImportError is treated as "test
        # skipped" -- which is what test_pty should say on Windows).
        try:
            del sys.modules[modname]
        except KeyError:
            pass
        return
    verify(hasattr(sys.modules[modname], "__all__"),
           "%s has no __all__ attribute" % modname)
    names = {}
    exec "from %s import *" % modname in names
    if names.has_key("__builtins__"):
        del names["__builtins__"]
    keys = names.keys()
    keys.sort()
    all = list(sys.modules[modname].__all__) # in case it's a tuple
    all.sort()
    verify(keys==all, "%s != %s" % (keys, all))

if not sys.platform.startswith('java'):
    # In case _socket fails to build, make this test fail more gracefully
    # than an AttributeError somewhere deep in CGIHTTPServer.
    import _socket

check_all("BaseHTTPServer")
check_all("CGIHTTPServer")
check_all("ConfigParser")
check_all("Cookie")
check_all("MimeWriter")
check_all("SimpleHTTPServer")
check_all("SocketServer")
check_all("StringIO")
check_all("UserString")
check_all("aifc")
check_all("atexit")
check_all("audiodev")
check_all("base64")
check_all("bdb")
check_all("binhex")
check_all("calendar")
check_all("cgi")
check_all("cmd")
check_all("code")
check_all("codecs")
check_all("codeop")
check_all("colorsys")
check_all("commands")
check_all("compileall")
check_all("copy")
check_all("copy_reg")
check_all("dbhash")
check_all("dircache")
check_all("dis")
check_all("doctest")
check_all("dospath")
check_all("filecmp")
check_all("fileinput")
check_all("fnmatch")
check_all("fpformat")
check_all("ftplib")
check_all("getopt")
check_all("getpass")
check_all("gettext")
check_all("glob")
check_all("gopherlib")
check_all("gzip")
check_all("htmllib")
check_all("httplib")
check_all("ihooks")
check_all("imaplib")
check_all("imghdr")
check_all("imputil")
check_all("keyword")
check_all("linecache")
check_all("locale")
check_all("macpath")
check_all("macurl2path")
check_all("mailbox")
check_all("mhlib")
check_all("mimetools")
check_all("mimetypes")
check_all("mimify")
check_all("multifile")
check_all("netrc")
check_all("nntplib")
check_all("ntpath")
check_all("os")
check_all("pdb")
check_all("pickle")
check_all("pipes")
check_all("popen2")
check_all("poplib")
check_all("posixpath")
check_all("pprint")
check_all("pre")  # deprecated
check_all("profile")
check_all("pstats")
check_all("pty")
check_all("py_compile")
check_all("pyclbr")
check_all("quopri")
check_all("random")
check_all("re")
check_all("reconvert")
check_all("regsub")
check_all("repr")
check_all("rexec")
check_all("rfc822")
check_all("rlcompleter")
check_all("robotparser")
check_all("sched")
check_all("sgmllib")
check_all("shelve")
check_all("shlex")
check_all("shutil")
check_all("smtpd")
check_all("smtplib")
check_all("sndhdr")
check_all("socket")
check_all("sre")
check_all("stat_cache")
check_all("tabnanny")
check_all("telnetlib")
check_all("tempfile")
check_all("toaiff")
check_all("tokenize")
check_all("traceback")
check_all("tty")
check_all("urllib")
check_all("urlparse")
check_all("uu")
check_all("warnings")
check_all("wave")
check_all("weakref")
check_all("webbrowser")
check_all("xdrlib")
check_all("zipfile")
<|endoftext|>