import warnings; warnings.filterwarnings("ignore")
import time
start_time = time.time()

import pandas as pd
import os

from sklearn import pipeline, grid_search
from sklearn.ensemble import RandomForestRegressor
from sklearn.base import BaseEstimator, TransformerMixin
from sklearn.pipeline import FeatureUnion
from sklearn.decomposition import TruncatedSVD
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics import mean_squared_error, make_scorer

def fmean_squared_error(ground_truth, predictions):
    fmean_squared_error_ = mean_squared_error(ground_truth, predictions)**0.5
    return fmean_squared_error_

class cust_regression_vals(BaseEstimator, TransformerMixin):
    def fit(self, x, y=None):
        return self
    def transform(self, hd_searches):
        d_col_drops=['id','relevance','search_term','product_title','product_description','product_info','attr','brand']
        hd_searches = hd_searches.drop(d_col_drops,axis=1).values
        return hd_searches
class cust_txt_col(BaseEstimator, TransformerMixin):
    def __init__(self, key):
        self.key = key
    def fit(self, x, y=None):
        return self
    def transform(self, data_dict):
        return data_dict[self.key].apply(str)

RMSE  = make_scorer(fmean_squared_error, greater_is_better=False)

df_all = pd.read_csv(os.path.expanduser('~/Desktop/Home Depot/Features/feature_array.csv'))
feature_cols = [col for col in df_all.columns if col not in ['Unnamed: 0']]
df_all = df_all[feature_cols]

df_train = pd.read_csv('~/Desktop/Home Depot/Data/train.csv', encoding="ISO-8859-1")#[:1000]
num_train = df_train.shape[0]

df_train = df_all[:num_train]
df_test = df_all[num_train:]

y_train = df_train['relevance']
id_test = df_test['id']
X_train = df_train[:]
X_test = df_test[:]

if __name__ == '__main__':

    rfr = RandomForestRegressor(n_estimators = 2000, n_jobs = -1, random_state = 2016, verbose = 1)
    tfidf = TfidfVectorizer(ngram_range=(1, 1), stop_words='english')
    tsvd = TruncatedSVD(n_components=10, random_state = 2016)
    clf = pipeline.Pipeline([
            ('union', FeatureUnion(
                        transformer_list = [
                            ('cst',  cust_regression_vals()),
                            ('txt1', pipeline.Pipeline([('s1', cust_txt_col(key='search_term')), ('tfidf1', tfidf), ('tsvd1', tsvd)])),
                            ('txt2', pipeline.Pipeline([('s2', cust_txt_col(key='product_title')), ('tfidf2', tfidf), ('tsvd2', tsvd)])),
                            ('txt3', pipeline.Pipeline([('s3', cust_txt_col(key='product_description')), ('tfidf3', tfidf), ('tsvd3', tsvd)])),
                            ('txt4', pipeline.Pipeline([('s4', cust_txt_col(key='brand')), ('tfidf4', tfidf), ('tsvd4', tsvd)])),
                            ],
                        transformer_weights = {
                            'cst': 1.0,
                            'txt1': 0.5,
                            'txt2': 0.25,
                            'txt3': 0.0,
                            'txt4': 0.5,

                            },
                    n_jobs = -1
                    )),
            ('rfr', rfr)])
    param_grid = {'rfr__max_features': [10], 'rfr__max_depth': [20]}
    model = grid_search.GridSearchCV(estimator = clf, param_grid = param_grid, n_jobs = -1, cv = 2, verbose = 20, scoring=RMSE)
    model.fit(X_train, y_train)
    y_pred = model.predict(X_test)

    print("Best parameters found by grid search:")
    print(model.best_params_)
    print("Best CV score:")
    print(model.best_score_)
    print(model.best_score_ + 0.47003199274)

    pd.DataFrame({"id": id_test, "relevance": y_pred}).to_csv(os.path.expanduser('~/Desktop/Home Depot/Output/rf_submission.csv'),index=False)
    print("--- Training & Testing: %s minutes ---" % round(((time.time() - start_time)/60),2))


import joblib

def lambda_handler(event, context):
    # Load the model from disk
    model = joblib.load('/var/task/model.pkl')

    # Run the model on the input data
    data = event['data'] # or however you want to retrieve the input data
    output = model.predict(data)

    # Return the output
    return {
        'statusCode': 200,
        'body': output.tolist() # or however you want to format the output
    }


"""
URL configuration for github_analytics_dashboard project.

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/4.2/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  path('', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  path('', Home.as_view(), name='home')
Including another URLconf
    1. Import the include() function: from django.urls import include, path
    2. Add a URL to urlpatterns:  path('blog/', include('blog.urls'))
"""
from django.contrib import admin
from django.contrib.auth import views as auth_views
from django.urls import path, include
from github_analytics import views

urlpatterns = [
    path('admin/', admin.site.urls),
    path('accounts/', include('allauth.urls')),
    path('fetch_github_data/', views.fetch_github_data, name='fetch_github_data'),
    path('', views.home, name='home'),
    path('logout', auth_views.LogoutView.as_view(), name='logout'),
    path('social-auth/', include('social_django.urls', namespace='social')),
    path('test/', views.test, name='test'),
    path('commit_frequency/<int:repo_id>', views.commit_frequency, name='commit_frequency'),
    path('visualize_pull_requests/<int:repo_id>', views.visualize_pull_requests, name='visualize_pull_requests'),
    path('visualize_contributors/<int:repo_id>', views.visualize_contributors, name='visualize_contributors'),
    path('visualize_repositories/', views.visualize_repositories, name='visualize_repositories'),
    path('all_repos_avg_resolution_time/', views.visualize_all_repos_avg_resolution_time, name='visualize_all_repos_avg_resolution_time'),
]


from string import ascii_uppercase
from z3 import *
import time

MAX_PROCS = 25
proc_list = []
user_input = []

class proc:
	def __init__(self, count):
		self.mode = 0
		self.proc_class = 0
		self.count = count
		self.negate_next = 0
		self.result_counter = 0
		self.finished = 0

	def _init_class(self):
		cur_group = (0xCCCCCCCCCCCCCCCD * (self.count - 1) >> 64) >> 2
		v21 = self.count - 1 - 5 * cur_group
		if ( cur_group <= v21 ):
			if ( cur_group >= v21 ):
				self.proc_class = -1
			else:
				self.proc_class = 1
		else:
			self.proc_class = 0

	def _set_next(self, next_value, next_mode):
		self.value = next_value
		self.mode = next_mode

	def _mode_zero(self, traced_p):
		self._init_class()

		if self.count == 25:
			self._set_next(user_input[0] ^ (user_input[1] << 8), 1)
		else:
			self._set_next(0, 0)

	def _mode_one(self, traced_p):
		value = traced_p.value

		value_byte0 = value & 0xff
		value_byte1 = (value >> 8) & 0xff
		class_indicator = (value >> 16) & 0xff
		input_index = (value >> 24) & 0xff
		negated_previous = (value >> 32) & 0xff

		if value_byte0 == self.count:
			if value_byte1 != 0:
				if match_check(value_byte0, value_byte1) and class_indicator == self.proc_class:
					self.proc_class = -1
				else:
					self.negate_next = -1 & 0xff

				value_byte0 = value_byte1
				value_byte1 = 0

				next_value = (self.negate_next << 32) ^ (input_index << 24) ^ (class_indicator << 16) ^ (value_byte0)

				self._set_next(next_value, 1)
			else:
				if negated_previous != -1 & 0xff and self.proc_class == -1:
					self.proc_class = class_indicator
					self.result_counter = self.result_counter + 1
				else:
					self.negate_next = -1 & 0xff

				input_index = input_index + 1
				if user_input[input_index * 2] != 26 or user_input[input_index * 2 + 1] != 26:
					value_byte0 = user_input[input_index * 2]
					value_byte1 = user_input[input_index * 2 + 1]

					next_value = (self.negate_next << 32) ^ (input_index << 24) ^ ((class_indicator ^ 1) << 16) ^ (value_byte1 << 8) ^ (value_byte0)
					self._set_next(next_value, 1)
				else:
					print_debug(input_index * 2, class_indicator ^ 1)
					self._set_next(0, 2)
		else:
			self._set_next(value, 1)

	def _mode_two(self, traced_p):
		if self.count == 25:
			result_holder = self.result_counter

			if self.proc_class != -1:
				result_holder = result_holder | 0x8000000000000000

			self._set_next(result_holder, 3)
		else:
			self._set_next(0, 2)

	def _mode_three(self, traced_p):
		value = traced_p.value
		result_holder = self.result_counter + value

		if self.count == 1:
			if self.proc_class != -1:
				result_holder = result_holder | 0x8000000000000000

			self._set_next(result_holder, 4)
		else:
			cur_group = (0xCCCCCCCCCCCCCCCD * (self.count - 1) >> 64) >> 2;
			v21 = self.count - 1 - 5 * cur_group;
			if ( cur_group >= v21 ):
				if ( cur_group <= v21 ):
					if self.proc_class != -1:
						result_holder = result_holder | 0x8400000000000000
				else:
					if self.proc_class != 1:
						result_holder = result_holder | 0x8200000000000000
			else:
				if self.proc_class != 0:
					result_holder = result_holder | 0x8100000000000000

			self._set_next(result_holder, 3)

	def _mode_four(self, traced_p):
		value = traced_p.value

		self.finished = 1

		if self.count == 1:
			self.result = value
			print("finished: %s" % hex(value))

		else:
			self._set_next(value, 4)

	def control_next(self, traced_p):
		mode = traced_p.mode

		[self._mode_zero, self._mode_one, self._mode_two, self._mode_three, self._mode_four][mode](traced_p)

def setup(proc_list):
	for i in range(MAX_PROCS):
		proc_list.append(proc(i + 1))

def do_control(proc_list, current):
	traced_p = proc_list[current]
	controlling_p = proc_list[(current - 1) % MAX_PROCS]

	controlling_p.control_next(traced_p)

def find_matches(count):
	result = ''
	for i in range(1, 26):
		if i != count and match_check(i, count) == 1:
			result = result + chr(i + ord('@'))

	return result

def print_debug(position, next):
	#return
	print('\n' + ' ' * position + 'v')
	print(''.join(chr(i + ord('@')) for i in user_input))
	print("next: %d" % next)
	for i in proc_list:
		cur_group = (0xCCCCCCCCCCCCCCCD * (i.count - 1) >> 64) >> 2
		v21 = i.count - 1 - 5 * cur_group
		if ( cur_group <= v21 ):
			if ( cur_group >= v21 ):
				proc_class = -1
				need = -1
			else:
				proc_class = 1
				need = 0
		else:
			proc_class = 0
			need = 1

		isgood = "NO "
		if proc_class == -1 and proc_class == i.proc_class:
			isgood = "YES"
		elif (proc_class == 1 or proc_class == 0) and proc_class == 1 - i.proc_class:
			isgood = "YES"

		possibilities = ''.join(["%s %d, " % (i, proc_list[ord(i) - ord('@') - 1].proc_class) for i in find_matches(i.count)])[:-2]
		print("%s : %02d | %s | %02d | %s" % (chr(i.count + ord('@')), i.proc_class, isgood, need, possibilities))

def match_check(rdi0, rdi1):
	v4 = rdi0 - 1;
	v3 = rdi1 - 1;
	if ( rdi0 - 1 == rdi1 - 1 ):
		return 0;
	v6 = v4 % 5;
	v5 = v3 % 5;
	if ( abs(int(v4 / 5) - int(v3 / 5)) == 1 and abs(v6 - v5) == 2 ):
		return 1;
	if ( abs(int(v4 / 5) - int(v3 / 5)) != 2 or abs(v6 - v5) != 1 ):
		return 0;
	return 1;

def start_with_input(trial_input):
	if len(trial_input) % 2 == 0 and all(i in user_input_range for i in trial_input):
		trial_input = trial_input + "ZZ"
		user_input = [ord(i) - ord('@') for i in trial_input]

		proc_list = []
		setup(proc_list)
		current = MAX_PROCS - 1

		while(proc_list[0].finished != 1):
			do_control(proc_list, current)
			current = (current - 1) % MAX_PROCS

		result = proc_list[0].result
		if result == 32:
			print("Well done!")
		else:
			print("nope")

	else:
		print("Error: wrong input.")

	return [proc_list, result]

def main():
	global user_input
	global proc_list

	user_input_range = ascii_uppercase[:-1]
	trial_input = input('input: ')

	#DEBUG
	__import__('os').system('echo|set /p="%s"| clip' % trial_input)

	if len(trial_input) % 2 == 0 and all(i in user_input_range for i in trial_input):
		trial_input = trial_input + "ZZ"
		user_input = [ord(i) - ord('@') for i in trial_input]

		proc_list = []
		setup(proc_list)
		current = MAX_PROCS - 1

		while(proc_list[0].finished != 1):
			do_control(proc_list, current)
			current = (current - 1) % MAX_PROCS

		final_board = [i.proc_class for i in proc_list]
		print(final_board)
		print("result: %d" % sum([i == j for i, j in zip(final_board, desired)]))

		result = proc_list[0].result
		if result == 32:
			print("Well done!")
		else:
			print("nope")

	else:
		print("Error: wrong input.")

starting_board = [-1, 1, 1, 1, 1, 0, -1, 1, 1, 1, 0, 0, -1, 1, 1, 0, 0, 0, -1, 1, 0, 0, 0, 0, -1]
desired = [[1, 0, -1][i] for i in starting_board]
user_input_range = ascii_uppercase[:-1]

def match_check_minimax(rdi0, rdi1):
	v4 = rdi0
	v3 = rdi1
	if ( rdi0 - 1 == rdi1 - 1 ):
		return 0;
	v6 = v4 % 5;
	v5 = v3 % 5;
	if ( abs(int(v4 / 5) - int(v3 / 5)) == 1 and abs(v6 - v5) == 2 ):
		return 1;
	if ( abs(int(v4 / 5) - int(v3 / 5)) != 2 or abs(v6 - v5) != 1 ):
		return 0;
	return 1;

mycount = 0
def do_min_max(board, depth, max_depth):
	global mycount
	mycount = mycount + 1

	current_score = sum([i == j for i, j in zip(board, desired)])
	if depth == max_depth:
		if board[4] != desired[4] or board[20] != desired[20]:
			return [-1, '']
		return [current_score, '']

	#if current_score < int(depth):
#		return [-1, '']

	my_children = []
	my_inputs = []

	for fst in range(0, 25):
		for scd in range(0, 25):
			parity = depth % 2

			if board[scd] != -1 or board[fst] != parity or not match_check_minimax(fst, scd):
				continue

			cur_board = board.copy()
			cur_board[fst], cur_board[scd] = board[scd], board[fst]

			result = do_min_max(cur_board, depth + 1, max_depth)
			my_children.append(result[0])
			my_inputs.append(chr(fst + 64 + 1) + chr(scd + 64 + 1) + result[1])

	if not len(my_children):
		print("board: " + repr(board))
		print("parity: %d" % parity)
		print("depth: %d" % depth)
		return [-1, '']

	max_val = max(my_children)
	max_input = my_inputs[my_children.index(max_val)]
	return [max_val, max_input]

def BitVecVector(prefix, sz, N):
	  """Create a vector with N Bit-Vectors of size sz"""
	  return [ BitVec('%s__%s' % (prefix, i), sz) for i in range(N) ]

def IntVector(prefix, N):
	  """Create a vector with N Bit-Vectors of size sz"""
	  return [ Int('%s__%s' % (prefix, i)) for i in range(N) ]

def BoolVector(prefix, N):
	  """Create a vector with N Bit-Vectors of size sz"""
	  return [ Bool('%s__%s' % (prefix, i)) for i in range(N) ]

z3_abs = lambda x: If(x >= 0,x,-x)

findintcount = 0
def findIntIdx(arr, findidx, solver):
	global findintcount
	answer = Int("find%d" % findintcount)
	findintcount = findintcount + 1
	for idx, val in enumerate(arr):
		solver.add(answer == If(idx == findidx, val, answer))

	return answer

def z3_simplified():
	s = Solver()
	board = starting_board.copy()
	board = [2 if i == -1 else i for i in board]

	desired_board = desired.copy()
	desired_board = [2 if i == -1 else i for i in desired_board]

	sol_len = 32
	find_first = 25

	IntVecBoard = [IntVector("board%d" % i, 25) for i in range(int(sol_len / 2) + 1)]

	for i, j in zip(board, IntVecBoard[0]):
		s.add(j == i)

	sol = IntVector("sol", sol_len)
	for i in sol:
		s.add(i < 25)
		s.add(i >= 0)

	for i in range(0, len(sol), 2):
		fst = sol[i]
		scd = sol[i + 1]

		last_board = IntVecBoard[int(i / 2)]
		cur_board = IntVecBoard[int(i / 2) + 1]

		s.add(fst != scd)
		s.add(Or(And(z3_abs(fst / 5 - scd / 5) == 1, z3_abs((fst % 5) - (scd % 5)) == 2), And(z3_abs(fst / 5 - scd / 5) == 2, z3_abs((fst % 5) - (scd % 5)) == 1)))

		parity = (i / 2) % 2

		for idx, val in enumerate(last_board):
			s.add(val == If(fst == idx, parity, If(scd == idx, 2, val)))

		for idx, val in enumerate(cur_board):
			s.add(val == If(fst == idx, 2, If(scd == idx, answer, last_board[idx])))

	for i, j in zip(desired_board, IntVecBoard[-1]):
		s.add(j == i)

	#print(s)

	if s.check() == sat:
		print(s.model())
		result = s.model()
		print([result[i] for i in sol])
		return [result[i].as_long() for i in sol]

	else:
		print("not found")
		return []

def z3_trial():
	s = Solver()
	board = starting_board.copy()
	board = [2 if i == -1 else i for i in board]

	desired_board = desired.copy()
	desired_board = [2 if i == -1 else i for i in desired_board]

	A = Array('A',IntSort(),IntSort())

	#boardIntArray = IntVector("board", 25)
	#for i, j in zip(boardIntArray, board):
	#	s.add(i == j)

	for i in range(25):
		A = Store(A, i, board[i])

	sol_len = 64
	sol = IntVector("sol", sol_len)
	for i in sol:
		s.add(i < 25)
		s.add(i >= 0)

	for i in range(0, len(sol), 2):
		fst = sol[i]
		scd = sol[i + 1]

		s.add(fst != scd)
		s.add(Or(And(z3_abs(fst / 5 - scd / 5) == 1, z3_abs((fst % 5) - (scd % 5)) == 2), And(z3_abs(fst / 5 - scd / 5) == 2, z3_abs((fst % 5) - (scd % 5)) == 1)))

		parity = (i / 2) % 2
		s.add(Select(A, fst) == parity)
		s.add(Select(A, scd) == 2)

		A = Store(A, fst, 2)
		A = Store(A, scd, parity)

	for i in range(4):
		s.add(Select(A, i) == desired_board[i])

	#print(s)

	if s.check() == sat:
		print(s.model())
		result = s.model()
		print([result[i] for i in sol])
		return [result[i].as_long() for i in sol]

	else:
		print("not found")
		return []

def z3_trial_fixed():
	s = Solver()
	board = starting_board.copy()
	board = [2 if i == -1 else i for i in board]

	desired_board = desired.copy()
	desired_board = [2 if i == -1 else i for i in desired_board]

	A = Array('A',IntSort(),IntSort())

	#boardIntArray = IntVector("board", 25)
	#for i, j in zip(boardIntArray, board):
	#	s.add(i == j)

	for i in range(25):
		A = Store(A, i, board[i])

	sol_len = 64
	sol = IntVector("sol", sol_len)
	for i in sol:
		s.add(i < 25)
		s.add(i >= 0)

	parity_table = IntVector("parity", int(sol_len/2))
	patch_table = IntVector("patch", int(sol_len / 2))
	extra_table = BoolVector("extra", int(sol_len / 2) + 1)
	s.add(extra_table[0] == False)

	for i in patch_table:
		s.add(i < 25)
		s.add(i >= 0)

	for i in range(0, len(sol), 2):
		fst = sol[i]
		scd = sol[i + 1]

		s.add(fst != scd)
		s.add(Or(And(z3_abs(fst / 5 - scd / 5) == 1, z3_abs((fst % 5) - (scd % 5)) == 2), And(z3_abs(fst / 5 - scd / 5) == 2, z3_abs((fst % 5) - (scd % 5)) == 1)))

		parity = (i / 2) % 2
		parity_bool = (i/2)%2 == 1
		s.add(Select(A, fst) != 2)
		s.add(Select(A, scd) == 2)

		one = Select(A, fst)

		actual_parity = Xor(parity_bool, extra_table[int(i/2)])
		s.add(If(one != If(actual_parity, 1, 0), extra_table[int(i/2)] != extra_table[int(i/2) + 1], extra_table[int(i/2)] == extra_table[int(i/2) + 1]))
		for char in sol[i:]:
			s.add(If(one != If(actual_parity, 1, 0), patch_table[int(i/2)] != char, True))

		s.add(parity_table[int(i/2)] == Select(A, fst))
		A = Store(A, fst, 2)
		A = Store(A, scd, one)

	for i in range(4):
		s.add(Select(A, i) == desired_board[i])

	#print(s.sexpr())

	print("starting to solve...")
	if s.check() == sat:
		print(s.model())
		result = s.model()
		print("result: %s" % [result[i] for i in sol])
		patch_result = [result[i].as_long() for i in patch_table]
		print("patch: %s" % patch_result)
		print("extra z3: %s" % [result[i] for i in extra_table])

		extra = 0
		final_parity_table = []
		for idx, val in enumerate([result[i].as_long() for j, i in enumerate(parity_table)]):
			parity = (idx + extra) % 2
			if val == parity:
				final_parity_table.append(True)
			else:
				final_parity_table.append(False)
				extra = extra + 1

		return [[result[i].as_long() for i in sol], final_parity_table, patch_result]

	else:
		print("not found")
		return [[], []]

def fix_parity(input, parity_table):
	input = [input[i:i+2] for i in range(0, len(input), 2)]
	print(input)

	extra = 0

	for i in range(len(input)):
		parity = (i + extra) % 2
		if parity_table[i] != parity:
			for char in "ABCDEFGHIJKLMNOPQRSTUVWXYZ":
				if char == 'Z': print("not actually found")
				if all([char not in hurdle for hurdle in input[i + 1:]]):
					input[i] = char * 2 + input[i]
					extra = extra + 1
					break

	return ''.join(input)

if __name__ == "__main__":
	start = time.time()
	result = z3_trial_fixed()
	#result = z3_simplified()
	result_input = result[0]
	parity_table = result[1]
	patch_table = result[2]
	result_string = [chr(result_input[i] + 65) + chr(result_input[i+1] + 65) for i in range(0, len(result_input), 2)]
	print("input: %s" % ''.join([chr(i + 65) for i in result_input]))
	print("parity: %s" % parity_table)
	patched_input = ''.join([chr(patch_table[j] + 65) * 2 + val if not parity_table[j] else val for j, val in enumerate(result_string)])
	print(patched_input)
	#print("fixed input: %s" % fix_parity(result_string, parity_table))
	#print(parity_table)
	print("that took %f secs" % (time.time() - start))
	#already_found = "LAHSQHILRINQURENHELUAHBMIBCLFCMFRINGWNORVMTWMTSVHSJMXOMX"
	#board = [-1, 0, 0, 1, 0, 1, 1, -1, 0, -1, 0, 1, -1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, -1]
	#result = [0, '']
	#result = do_min_max(board, 28, 34)
	#print("score: %s" % repr(result[0]))
	#print("input: %s" % already_found + result[1])
	#print("count: %d" % mycount)
	#
	#main()


import asyncio
import json
import re
from datetime import datetime, timedelta
from typing import Union

import discord
from discord.ext.commands import command

class Moderation:
    def __init__(self, bot):
        self.bot = bot
        self.log_chan = bot.get_channel(413010299776532490)
        self.spamguard_blacklist = bot._spamguard_blacklist
        self.msg_num = 0
        self.embed_colors = {
            "kick": 0xffa500,
            "ban": 0xff0000,
            "warn": 0xffff00,
            "mute": 0xa52a2a,
            "unmute": 0x73dcff
        }
        self.converter = {
            "kick": "ed",
            "mute": "d",
            "ban": "ned",
            "warn": "ed",
            "unmute": "d"
        }

    async def __local_check(self, ctx):
        perms = ctx.author.guild_permissions
        return (perms.kick_members and perms.ban_members) or ctx.author.id == 111158853839654912

    async def log_action(self, ctx, action, *, member, reason=None, mod=None, minutes=None):
        _action = action
        if action in ('gag', 'sleep'):
            action = 'mute'
        embed = discord.Embed(title=f"Member {action}", description=reason)
        embed.color = self.embed_colors[action]
        embed.timestamp = datetime.now()

        embed.add_field(name="Moderator", value=mod)
        if minutes is not None:
            embed.add_field(name="Unmute in", value=str(minutes) + " minutes")
        embed.set_author(name=f"{member} / {member.id}", icon_url=member.avatar_url)
        embed.set_footer(text="Invoked in #" + ctx.channel.name)
        if ctx.guild.id == 391483719803994113:
            await self.log_chan.send(embed=embed)
        if self.bot.config[ctx.guild.id]['echo_mod_actions']:
            if _action == "sleep":
                await ctx.send(f"`{member}` has been put to sleep by {mod}.")
            else:
                action += self.converter[action]
                await ctx.send(f"`{member}` has been {action} by {mod}.")

    async def on_guild_channel_create(self, channel):
        if channel.guild.id in self.bot.muted_roles:
            r_id = self.bot.muted_roles[channel.guild.id]
            role = channel.guild.get_role(r_id)
            await channel.set_permissions(role, send_messages=False)

    async def handle_spamguard(self, ctx):
        if ctx.channel.id in self.spamguard_blacklist:
            return

        if ctx.message.attachments:
            past = datetime.utcnow() - timedelta(minutes=0.5)  # search back for half a min
            c = 0
            async for m in ctx.history(after=past):
                if m.attachments and m.author == ctx.author:
                    c += 1
                if c >= 4:  # too many images, max is 3
                    ctx.author = ctx.guild.me
                    state = self.bot.muted_members.get(ctx.author.id)
                    if state and state['muted']:
                        return
                    await ctx.invoke(self.bot.get_command("mute"), ctx.message.author,
                                     body=("Image / file spamming", 5))
                    return

    async def handle_scrambler(self, ctx):  # im not proud
        if ctx.channel.id != 391483720244264961:
            return
        self.msg_num += 1
        if self.msg_num >= 5000:
            self.msg_num = 0
            await ctx.invoke(self.bot.get_command("scramble"))

    async def on_message(self, message):
        if message.author.bot:
            return
        ctx = await self.bot.get_context(message)
        await self.handle_spamguard(ctx)
        await self.handle_scrambler(ctx)

    @command()  # this is actually horrid
    async def config(self, ctx):
        """Allows configuration of options for the server."""

        fmt = "Enter config number to toggle the value, or `x` to cancel:"
        config_index = {}
        try:
            config = self.bot.config[ctx.guild.id]
        except KeyError:
            query = """
                INSERT INTO config VALUES ($1, $2 ,$3)
                RETURNING *
            """
            r = await self.bot.pool.fetchrow(query, ctx.guild.id, False, False)
            r = dict(r)
            self.bot.config[r.pop('guild_id')] = r
            config = self.bot.config[ctx.guild.id]

        fmt += "```"
        for i, key in enumerate(config):
            fmt += f"\n{i+1}. [{key}] : {config[key]}"
            config_index[i + 1] = key
        fmt += "```"
        await ctx.send(fmt)
        try:
            def check(m):
                return (m.author == ctx.author) and (m.channel == ctx.channel)

            msg = await self.bot.wait_for("message", check=check, timeout=30)
        except asyncio.TimeoutError:
            return await ctx.send("Timeout.")
        if msg.content.lower() != 'x':
            config[config_index[int(msg.content)]] = not config[config_index[int(msg.content)]]
            query = """
                UPDATE config
                SET {} = {} WHERE guild_id = {}
            """.format(config_index[int(msg.content)], config[config_index[int(msg.content)]], ctx.guild.id)
            await self.bot.pool.execute(query)
            await ctx.send(config_index[int(msg.content)] + " toggled.")

    def _answer(arg):
        ret = None
        if arg.lower() in ['y', 'yes', 'true', 'on', 'enable']:
            ret = True
        elif arg.lower() in ['n', 'no', 'false', 'off', 'disable', 'stop']:
            ret = False
        return arg, ret

    @command()
    async def spamguard(self, ctx, state: _answer, channel: discord.TextChannel = None):
        """Sets the state of the spamguard for a channel.

        If no channel specified, defaults to current channel.
        """

        answer, state = state
        channel = channel or ctx.channel
        if state is None:
            return await ctx.send(f"❗`{answer}` is not a valid argument! "
                                  "Try something like: yes, no, true, false, on, off.`")

        elif state:  # ENABLE
            msg = f"Successfully enabled the spamguard in {channel.mention}."
            if channel.id not in self.spamguard_blacklist:
                return await ctx.send(msg)

            query = """
                DELETE FROM spamguard_blacklist WHERE channel_id = $1
            """
            await self.bot.pool.execute(query, channel.id)
            self.spamguard_blacklist.remove(channel.id)
            await ctx.send(msg)

        else:  # DISABLE
            msg = f"Successfully disabled the spamguard in {channel.mention}."
            if channel.id in self.spamguard_blacklist:
                return await ctx.send(msg)

            query = """
                INSERT INTO spamguard_blacklist (channel_id) VALUES ($1)
            """
            await self.bot.pool.execute(query, channel.id)
            self.spamguard_blacklist.append(channel.id)
            await ctx.send(msg)

    @command()
    async def lock(self, ctx):
        """Locks down the current channel."""

        await ctx.message.delete()
        msg = await ctx.send("This channel is now under lockdown!")
        perms = ctx.channel.overwrites_for(ctx.guild.default_role)

        query = """
            INSERT INTO lockdown (channel_id, message_id, perms) VALUES ($1, $2, $3)
        """
        await self.bot.pool.execute(query, ctx.channel.id, msg.id, json.dumps(perms._values))

        perms.send_messages = False
        perms.add_reactions = False
        await ctx.channel.set_permissions(ctx.guild.default_role, overwrite=perms)

    @command()
    async def unlock(self, ctx):
        """Releases the current channel from lockdown."""

        await ctx.message.delete()
        query = """
            DELETE FROM lockdown WHERE channel_id=$1 RETURNING *
        """
        recs = await self.bot.pool.fetchrow(query, ctx.channel.id)
        if not recs:
            return

        channel_id, msg_id, perms = recs
        msg = await self.bot.get_channel(channel_id).get_message(msg_id)
        await msg.delete()

        perms = discord.PermissionOverwrite(**json.loads(perms))
        await ctx.channel.set_permissions(ctx.guild.default_role, overwrite=perms)
        await ctx.send("This channel is no longer under lockdown.", delete_after=10)

    @command()
    async def kick(self, ctx, target: discord.Member, *, reason=None):
        """Kicks a member."""

        await ctx.message.delete()
        await target.kick(reason=f"{ctx.author.name}: {reason}")

        query = """
            INSERT INTO kicks (guild_id, member_id, channel_id, moderator_id, reason, action_time)
            VALUES ($1, $2, $3, $4, $5, $6)
        """
        await self.bot.pool.execute(query, ctx.guild.id, target.id, ctx.channel.id,
                                    ctx.author.id, reason, datetime.utcnow())

        await self.log_action(ctx, "kick", member=target, reason=reason, mod=ctx.author)

    @command(aliases=['dab'])
    async def ban(self, ctx, target: discord.Member, *, reason=None):
        """Bans a member."""

        await ctx.message.delete()
        await target.ban(reason=f"{ctx.author.name}: {reason}", delete_message_days=0)

        query = """
            INSERT INTO bans (guild_id, member_id, channel_id, moderator_id, reason, action_time)
            VALUES ($1, $2, $3, $4, $5, $6)
        """
        await self.bot.pool.execute(query, ctx.guild.id, target.id, ctx.channel.id,
                                    ctx.author.id, reason, datetime.utcnow())

        await self.log_action(ctx, "ban", member=target, reason=reason, mod=ctx.author)

    def parse_mute(arg):
        if arg is None:
            return None, None
        if len(arg.split(' ', 1)) == 1:
            maybe_time = arg.split(' ', 1)[0]
            reason = None
        else:
            maybe_time, reason = arg.split(' ', 1)
        pattern = r"(?:(?P<hours>\d+)h)?(?P<minutes>\d+)m"
        m = re.match(pattern, maybe_time)
        if m is None:
            return arg, None
        minutes, hours = m.group('minutes', 'hours')
        if hours is None:
            return reason, int(minutes)
        return reason, int(minutes) + int(hours) * 60

    @command(aliases=['gag', 'sleep'], usage="<target> [time] [reason]")
    async def mute(self, ctx, target: discord.Member, *, body: parse_mute = None):
        """Mutes a member. The reason will be sent as a notice to said member in a DM."""

        if body is None:
            reason, minutes = None, None
        else:
            reason, minutes = body
        await ctx.message.delete()
        r_id = self.bot.muted_roles.get(ctx.guild.id)
        if not r_id:
            role = await ctx.guild.create_role(name="Muted")
            r_id = role.id
            self.bot.muted_roles[ctx.guild.id] = r_id
            for c in ctx.guild.text_channels:
                await c.set_permissions(role, send_messages=False)

            query = """
                INSERT INTO mute_roles (guild_id, role_id) VALUES ($1, $2)
            """
            await self.bot.pool.execute(query, ctx.guild.id, role.id)

        role = ctx.guild.get_role(r_id)
        await target.add_roles(role)

        timeout = datetime.utcnow() + timedelta(minutes=minutes) if minutes else None
        log_query = """
            INSERT INTO mutes (guild_id, member_id, channel_id, moderator_id, reason, action_time)
            VALUES ($1, $2, $3, $4, $5, $6)
        """
        await self.bot.pool.execute(log_query, ctx.guild.id, target.id, ctx.channel.id,
                                    ctx.author.id, reason, datetime.utcnow())

        query = """
            INSERT INTO mute_states (member_id, guild_id, muted, mute_timeout, muter_id)
            VALUES ($1, $2, true, $3, $4)
            ON CONFLICT (guild_id, member_id) DO UPDATE
                SET muted = true,
                    mute_timeout = $3,
                    muter_id = $4
            RETURNING *
        """
        rec = await self.bot.pool.fetchrow(query, target.id, ctx.guild.id, timeout, ctx.author.id)

        self.bot.muted_members[target.id] = dict(rec)
        self.bot.loop.create_task(self.bot.ensure_unmute(target.id, self.bot.muted_members[target.id]))

        fmt = f"You've been muted by {ctx.author}!"
        if minutes is not None:
            fmt += f"\nMute duration: {minutes} minute(s)"
        if reason:
            fmt += f"\nReason: \"{reason}\""

        try:
            await target.send(fmt)
        except:  # noqa
            try:
                await ctx.author.send(f"Could not send mute notice to `{target}`.\n"
                                      "They may have DMs disabled, or have blocked me.\n\n"
                                      f"Mute Reason:\n{reason}")
            except:  # noqa
                pass
        await self.log_action(ctx, ctx.invoked_with, member=target, reason=reason, mod=ctx.author, minutes=minutes)

    async def _do_unmute(self, target, *, reason, mod, guild):
        r_id = self.bot.muted_roles[guild.id]
        if r_id:
            role = guild.get_role(r_id)
            if role:
                if role not in target.roles:
                    return
                await target.remove_roles(role)
                query = """
                    UPDATE mute_states
                        SET muted = false,
                            mute_timeout = NULL,
                            muter_id = NULL
                        WHERE guild_id = $1 AND member_id = $2
                    RETURNING *
                """
                rec = await self.bot.pool.fetchrow(query, guild.id, target.id)
                self.bot.muted_members[target.id] = dict(rec)

        fmt = f"You've been unmuted by {mod}!"
        if reason:
            fmt += f"\nReason: \"{reason}\""

        try:
            await target.send(fmt)
        except:  # noqa
            try:
                await mod.send(f"Could not send unmute notice to `{target}`.\n"
                               "They may have DMs disabled, or have blocked me.\n\n"
                               f"Unmute Reason:\n{reason}")
            except:  # noqa
                pass

    @command(aliases=['ungag'])
    async def unmute(self, ctx, target: discord.Member, *, reason=None):
        """Unmutes a member. The reason will be sent as a notice to said member in a DM."""
        try:
            await ctx.message.delete()
        except:  # noqa
            pass
        await self._do_unmute(target, reason=reason, mod=ctx.author, guild=ctx.guild)
        await self.log_action(ctx, "unmute", member=target, reason=reason, mod=ctx.author)

    @command()
    async def warn(self, ctx, target: discord.Member, *, warning=None):
        """Warns a member. The warning will be sent to said member in a DM."""

        await ctx.message.delete()
        try:
            if warning is None:
                await target.send(f"You've received a warning from {ctx.author}!")
            else:
                await target.send(f"You've received a warning from {ctx.author}:\n \"{warning}\"")
        except:  # noqa
            try:
                await ctx.author.send(f"Could not send a warning to `{target}`.\n"
                                      "They may have DMs disabled, or have blocked me.\n\n"
                                      f"Warning text was:\n{warning}")
            except:  # noqa
                pass

        query = """
            INSERT INTO warnings (guild_id, member_id, reason, moderator_id, action_time, channel_id)
            VALUES ($1, $2, $3, $4, $5, $6)
        """
        await self.bot.pool.execute(query, ctx.guild.id, target.id, warning,
                                    ctx.author.id, datetime.utcnow(), ctx.channel.id)

        await self.log_action(ctx, "warn", member=target, reason=warning, mod=ctx.author)

    @command(aliases=['prune', 'p'])
    async def purge(self, ctx, count: int, *users: discord.Member):
        """Deletes messages en masse."""

        await ctx.message.delete()
        if count > 100:
            await ctx.send(f"You are about to purge {count}. Are you sure you want to purge these many messages? (y/n)")

            def check(m):
                (m.content.lower() == 'y' or m.content.lower() == 'n') and m.author == ctx.message.author
            try:
                reply = await self.bot.wait_for("message", check=check, timeout=10)
            except asyncio.TimeoutError:
                return await ctx.send("Cancelled purge.")
            if not reply or reply.content.lower().strip() == 'n':
                return await ctx.send("Cancelled purge.")
            else:
                await ctx.message.delete()
        try:
            await ctx.channel.purge(limit=count, check=lambda message: message.author in users if users else True)
        except discord.HTTPException:
            await ctx.send("Something went wrong! Could not purge.")

    @command()
    async def check(self, ctx, target: Union[discord.Member, int], action_type="overall"):
        """Shows the list of previous warnings a member has been given."""

        if action_type == "overall":
            return await self.overall_check(ctx, target)

        types = {
            'warnings': 'warnings',
            'warning': 'warnings',
            'warn': 'warnings',
            'bans': 'bans',
            'ban': 'bans',
            'kicks': 'kicks',
            'kick': 'kicks',
            'mutes': 'mutes',
            'mute': 'mutes'
        }
        if action_type not in types.keys():
            return await ctx.send(f"Couldnt find that action type! I log: {', '.join(set(types.values()))}.\n"
                                  "You may also omit the type, and I'll show you overall info about the member.")

        query = f"""
            SELECT * FROM {types[action_type]}
            WHERE guild_id = $1 AND member_id = $2
        """
        t_id = target if isinstance(target, int) else target.id
        recs = await self.bot.pool.fetch(query, ctx.guild.id, t_id)
        txt = types[action_type] + " list:\n"
        for r in recs:
            mod = ctx.guild.get_member(r['moderator_id'])
            channel = ctx.guild.get_channel(r['channel_id'])
            warning = r['reason']
            timestamp = r['action_time']
            time_fmt = datetime.strftime(timestamp, r"%H:%M %h %d %Y")
            fmt = f"**MOD**: {mod}\n**TARGET**: {target}\n**REASON**: {warning}\n**AT**: {time_fmt}\n**IN**: {'#' + channel.name if channel else 'NULL'}\n{'-' * 10}\n"  # noqa: E226, E501
            txt += fmt
        if txt:
            if len(txt) >= 2000:
                haste = await self.bot.make_haste(txt, raw=True)
                return await ctx.send(haste)
            await ctx.send(txt)
        else:
            await ctx.send("No warnings for " + str(target))

    async def overall_check(self, ctx, target):
        query = """
            SELECT
            (
                SELECT count(*) FROM mutes
                WHERE member_id = $1
            ) AS mute_count,
            (
                SELECT count(*) FROM bans
                WHERE member_id = $1
            ) AS ban_count,
            (
                SELECT count(*) FROM kicks
                WHERE member_id = $1
            ) AS kick_count,
            (
                SELECT count(*) FROM warnings
                WHERE member_id = $1
            ) AS warning_count
        """
        t_id = target if isinstance(target, int) else target.id
        rec = await self.bot.pool.fetchrow(query, t_id)
        mutes = rec['mute_count']
        bans = rec['ban_count']
        kicks = rec['kick_count']
        warnings = rec['warning_count']
        description = 'For more info on each field, do `>check Target#1234 field`.\n' \
                      f'For example, `>check {target} bans`'
        embed = discord.Embed(title=f"Moderation stats", description=description) \
            .add_field(name="Total Warnings", value=warnings, inline=False) \
            .add_field(name="Total Mutes", value=mutes, inline=False) \
            .add_field(name="Total Kicks", value=kicks, inline=False) \
            .add_field(name="Total Bans", value=bans, inline=False) \
            .set_author(name=f"{target} / {t_id}")
        if not isinstance(target, int):
            embed.author.icon_url = target.avatar_url
        await ctx.send(embed=embed)

    @command()
    async def lookup(self, ctx, member: discord.Member):
        """Show a list of a member's previous usernames."""
        query = """
            SELECT usernames FROM usernames WHERE member_id = $1
        """
        r = await self.bot.pool.fetchrow(query, member.id)
        to_send = "Known Usernames:\n"
        if r is None:
            await ctx.send(to_send + member.name)
        else:
            fmt = ""
            for name in r['usernames']:
                fmt += name + "\n"
            if len(fmt) >= 2000:
                url = await self.bot.make_haste(fmt)
                await ctx.send(to_send + url)
            else:
                await ctx.send(to_send + fmt)

    @command()
    async def remove(self, ctx, member: discord.Member, role: discord.Role):
        await ctx.message.delete()
        await member.remove_roles(role)
        if self.bot.config[ctx.guild.id]['echo_mod_actions']:
            await ctx.send(f"Role `{role}` has been removed from `{member}` by `{ctx.author}`.")

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


def tablaMultiplicar(numero): #Definimos la funcion que recibira como parametro el numero de la tabla a realizar
    for i in range(11): #Bucle que recorrera del 0 al 10 (se pone 11 ya que el valor que se pone solo se toma hasta el anterior)
        resultado = i * numero #Multiplicamos el ietrador por el numero de tabla y lo guardamos en resultado
        print("{} x {} = {}".format(numero,i,resultado)) #Mostramos el resultado

#Pedimos el numero de la tabla
numeroTabla = int(input("Ingrese la tabla de multiplicar a conocer: "))

#Llamamos a la funcion y le pasamos como argumento el numero de tabla que ingreso el usuario
tablaMultiplicar(numeroTabla)


import matplotlib.pyplot as plt
import torch
import torch.nn as nn
from utils import *

if torch.cuda.is_available():
    device = torch.device('cuda')
else:
    device = torch.device('cpu')
print('Using PyTorch version:', torch.__version__, ' Device:', device)

from LSTM_rewrite import mylstm
hidden_size=128
rnn=mylstm()
criterion = nn.NLLLoss()
learning_rate = 0.05

def train(category_tensor, line_tensor):
    # 初始全零的隐藏向量
    hidden = rnn.init_hidden()
    rnn.zero_grad()
    for i in range(line_tensor.size()[0]):
        # 对于name中的每一个字母
        output,hc= rnn(line_tensor[i],hidden)

    loss = criterion(output, category_tensor)
    loss.backward()

    # Add parameters' gradients to their values, multiplied by learning rate
    for p in rnn.parameters():
        p.data.add_(p.grad.data, alpha=-learning_rate)

    return output, loss.item()

def validate():
    correct = 0
    all = 0
    for key, value in category_lines.items():
        for name in value:
            line_tensor = lineToTensor(name)
            hidden = rnn.init_hidden()
            for i in range(line_tensor.size()[0]):
                output, hidden = rnn(line_tensor[i], hidden)
            # 得到结果向量output
            guess, guess_i = categoryFromOutput(output)
            if guess == key:
                correct += 1
        all += len(value)
    print('Accuract is {}/{}'.format(correct, all))

def evaluate(line_tensor):
    hidden = rnn.init_hidden()
    for i in range(line_tensor.size()[0]):
        output ,hidden= rnn(line_tensor[i],hidden)
    return output

n_iters = 200000
print_every = 5000
plot_every = 1000

current_loss = 0
all_losses = []

# begin to train
start = time.time()
for iter in range(1, n_iters + 1):
    category, line, category_tensor, line_tensor = randomTrainingExample()
    output, loss = train(category_tensor, line_tensor)
    current_loss += loss

    # Print iter number, loss, name and guess
    if iter % print_every == 0:
        guess, guess_i = categoryFromOutput(output)
        correct = '✓' if guess == category else '✗ (%s)' % category
        print('%d %d%% (%s) %.4f %s / %s %s' % (iter, iter / n_iters * 100, timeSince(start), loss, line, guess, correct))

    # Add current loss avg to list of losses
    if iter % plot_every == 0:
        all_losses.append(current_loss / plot_every)
        current_loss = 0
# begin to test
validate()

plt.figure()
plt.plot(all_losses)
plt.savefig('./loss.png')
plt.clf()

# 准备混淆矩阵
confusion = torch.zeros(n_categories, n_categories)
n_confusion = 10000
for i in range(n_confusion):
    category, line, category_tensor, line_tensor = randomTrainingExample()
    output = evaluate(line_tensor)
    guess, guess_i = categoryFromOutput(output)
    category_i = all_categories.index(category)
    confusion[category_i][guess_i] += 1

# Normalize by dividing every row by its sum
for i in range(n_categories):
    confusion[i] = confusion[i] / confusion[i].sum()

# Set up plot
fig = plt.figure()
ax = fig.add_subplot(111)
cax = ax.matshow(confusion.numpy())
fig.colorbar(cax)
# Set up axes

ax.set_xticklabels([''] + all_categories, rotation=90)
ax.set_yticklabels([''] + all_categories)

# Force label at every tick
ax.xaxis.set_major_locator(ticker.MultipleLocator(1))
ax.yaxis.set_major_locator(ticker.MultipleLocator(1))
plt.savefig('./matrix.png')
plt.clf()


from __future__ import unicode_literals
from jsonfield import JSONField
import pytz

from django.db import models
from django.utils import timezone
from django.utils.encoding import python_2_unicode_compatible

from health_monitor import utils

@python_2_unicode_compatible
class Health(models.Model):
    uid = models.IntegerField(primary_key=True, db_index=True)
    state = JSONField(default={}, blank=True, null=True)
    severity = JSONField(default={}, blank=True, null=True)
    history = JSONField(default={}, blank=True, null=True)

    def __str__(self):
        return str(self.uid)

    def _calculate_severity(self, group):
        """Return a severity calculation.

        The severity is the highest score in state dict of a group.

        Arguments:
        g -- group
        """
        test_scores = [1, ]
        for t in self.state[group].keys():
            if self.state[group][t]['score']:
                test_scores.append(self.state[group][t]['score'])

        return max(test_scores)

    @classmethod
    def get_or_create(cls, *args, **kwargs):
        try:
            return cls.objects.get(**kwargs)
        except Exception:
            return cls.objects.create(**kwargs)

    def update_score(self, test, score):
        """Update the health state, health severity, and health history.

        These are updated based on the test name and score.

        Arguments:
        test  -- test
        score -- score
        """

        # update state and severity
        for group in HealthTest._get_groups(test):
            if test in HealthTest._get_tests(group):
                if group not in self.state.keys():
                    self.state[group] = {}
                self.state[group] = utils.init_score_dict(
                    self.state[group], test)
                self.state[group][test] = utils.update_score_dict(
                    self.state[group][test], score)
                self.severity = utils.init_score_dict(self.severity, group)
                self.severity[group] = utils.update_score_dict(
                    self.severity[group], self._calculate_severity(group))

        # update history
        if test not in self.history.keys():
            self.history[test] = [score]
        else:
            self.history[test] = utils.push_pop_deque(
                score, self.history[test])

        self.save()

    def delete_test(self, test):
        """Delete a test from all groups.

        Deleting a test results in recalculations of all health states per
        group and the health severity.
        """
        for group in self.state.keys():
            if test in self.state[group].keys():
                del(self.state[group][test])
                self.severity[group] = utils.update_score_dict(
                    self.severity[group], self._calculate_severity(group))
        self.save()

    def delete_group(self, group):
        """Delete group from health state and severity."""
        del(self.state[group])
        del(self.severity[group])
        self.save()

    def delete_group_test(self, group, test):
        """Delete test entry from specified group's health state.

        This also results in an updated severity.
        """
        if test in self.state[group].keys():
            del(self.state[group][test])
            self.severity[group] = utils.update_score_dict(
                self.severity[group], self._calculate_severity(group))
        self.save()

    def get_latest_scores(self, test, repetition):
        """Get latest x scores from HealthTest historical records.

        Where x is the number of repetitions.
        """
        test_model = HealthTest._get_model(test)
        return [
            x.get_score() for x in test_model.objects.filter(
                uid=self.uid).order_by('-time')[:repetition]
        ]

    def get_history(self, test, repetition):
        """Return the cached x test scores or retrieve from historical records.

        Where x is the number of repetitions.
        """
        try:
            if not len(self.history[test]) >= repetition:
                raise Exception
        except Exception:
            self.history[test] = self.get_latest_scores(test, repetition)
            self.save()
        return self.history[test][0:repetition]

    class Meta(object):
        abstract = True

class HealthAlarm(object):
    @classmethod
    def _get_associated_healths(cls, group, test):
        """Return a subset of healths

        That contain the nested group and test key.
        """
        healths = []
        for health in cls.health_model.objects.all():
            if group in health.state.keys():
                if test in health.state[group].keys():
                    healths.append(health)

        return healths

    @classmethod
    def calculate_alarms(
        cls, group, test, score, aggregate_percent=0, repetition=1,
        repetition_percent=100, **kwargs
    ):
        """Return a list of asset uids based off of filtering criteria.

        Arguments:
        group              -- group name
        test               -- test name
        score              -- minimum score to tigger an alarm
        aggregate_percent  -- minimum percentage of test failures to trigger an
            alarm
        repetition         -- minimum number of test failures in a row to
            trigger an alarm
        repetition_percent -- minimum percentage of failures within repetition
            to trigger an alarm
        """
        healths = cls._get_associated_healths(group, test)

        # step 1: filter failing assets by score, if repetition_percent is less
        # than 100%, all healths must be checked
        if repetition_percent == 100:
            failing_healths_by_score = [
                x for x in healths if x.state[group][test]['score'] >= score]
        else:
            failing_healths_by_score = healths

        # step 2: filter failing assets by repetition criteria
        failing_healths = []
        for health in failing_healths_by_score:
            score_history = health.get_history(test, repetition)
            failing_count = len([x for x in score_history if x >= score])
            if 100 * failing_count / len(score_history) >= repetition_percent:
                failing_healths.append(health)

        # step 3: return empty array if percentage of failing assets is below
        # aggregate_percent
        if (len(failing_healths) / len(healths)) < (aggregate_percent / 100):
            return []
        else:
            return [x.uid for x in failing_healths]

class HealthTest(models.Model):
    uid = models.IntegerField(db_index=True)
    time = models.DateTimeField()

    test = None
    groups = []
    health_model = Health

    def __str__(self):
        return str(self.uid)

    @classmethod
    def create(cls, uid, **kwargs):
        health_test = cls(uid=uid, time=timezone.now(), **kwargs)
        health_test.save()

        h = cls.health_model.get_or_create(uid=uid)
        h.update_score(test=cls.test, score=cls.calculate_score(**kwargs))

        return health_test

    @classmethod
    def calculate_score(cls, **kwargs):
        """Returns the score.

        This is calculated from derived class' score() method and inputted
        kwargs.
        """
        score = cls.score(**kwargs)
        if type(score) != int:
            raise TypeError('score method should return an integer')
        elif score < 0:
            raise ValueError('score method should return a positive integer')
        else:
            return score

    def get_score(self):
        """Returns the score.

        This is calculated using self.calculate_score() and instance attributes
        (db columns).
        """
        kwargs = {
            x.name: getattr(self, x.name) for x in type(self)._meta.fields}
        return type(self).calculate_score(**kwargs)

    @classmethod
    def get_history(
        cls, uids=None,
        start_time=timezone.datetime.min.replace(tzinfo=pytz.UTC),
        end_time=timezone.datetime.max.replace(tzinfo=pytz.UTC)
    ):
        """Returns historical test results.

        Arguments:
        uids       -- a list of uids
        start_time -- a datetime object
        end_time   -- a datetime object
        """
        if uids:
            return cls.objects.filter(
                uid__in=uids, **{'time__range': (start_time, end_time)})
        else:
            return cls.objects.filter(
                **{'time__range': (start_time, end_time)})

    @staticmethod
    def _get_tests(group=None):
        """Return list of test names associated with a group."""
        if not group:
            return [t.test for t in HealthTest.__subclasses__()]
        return [
            t.test for t in HealthTest.__subclasses__() if group in t.groups]

    @classmethod
    def _get_groups(cls, test=None):
        """Return a list of group names.

        These are associated with a test or all groups if no test is passed.
        """
        if not test:
            return utils.merge_to_uniques(
                [x.groups for x in cls.__subclasses__()])
        for t in HealthTest.__subclasses__():
            if test == t.test:
                return t.groups
        return []

    @staticmethod
    def _get_model(test):
        """Return the model associated with a test."""
        for t in HealthTest.__subclasses__():
            if test == t.test:
                return t
        raise TypeError('test {} does not exist'.format(test))

    class Meta(object):
        abstract = True


from csv import reader

from model.hotel_struct_input import InputHotelStruct

class CSVParser:

    def __init__(self,input_file_path):
        self.input_file_path=input_file_path
        self.hotel_list=[]
        self.start_reading()

    def start_reading(self):
        with open(self.input_file_path, 'r') as read_obj:
            csv_reader = reader(read_obj)
            header = next(csv_reader)
            if header != None:
                for row in csv_reader:
                    hotel_id,hotel_name,hotel_city,hotel_address=row
                    hotel=InputHotelStruct(hotel_id=hotel_id,hotel_name=hotel_name,hotel_city=hotel_city,hotel_address=hotel_address)
                    self.hotel_list.append(hotel)

    def get_hotel_at(self,index):
        return self.hotel_list[index]

    def is_found(self,index):
        if len(self.hotel_list) > index:
            return True
        return False


from pprint import pprint

names = [

    ['first', 'First'],
    ['Second', 'second'],
    ['Tree', 'tree', 'treeee'],
]

numbers = [2, 22, 444,55,666]

import itertools

# print(list(ite1rtools.product(*names)))
# print(list(itertools.combinations([names[0][0], names[1][0], names[2][0]], 3)))

def generate():

    final = []

    for line1 in names[0]:
        for line2 in names[1]:
            for line3 in names[2]:
                for line4 in numbers:

                    for i in range(1, 4):
                        # print(i, line1, line2, line3, line4)

                        mutant = list(itertools.permutations([line1, line2, line3], i))

                        final = final + mutant

                        for m in mutant:

                            final.append(m + tuple([str(line4)]))

    return list(set(final))

if __name__ == "__main__":

    final = generate()

    pprint(final)

    print(len(final))

    with open('passwords.txt', 'w') as f:
        for item in final:
            comb_str = ''.join(list(item))
            if len(comb_str)<8:
                # print('skip small', comb_str)
                continue
            f.write("%s\n" % comb_str)