#replace TOKEN with Telegram Bot API Token
#replace ADMIN_CHAT_ID with your own Chat_id
#you can find the Chat_id by using the /get_me command

from telegram.ext import Updater, CommandHandler, MessageHandler, Filters, PollAnswerHandler, PollHandler, ConversationHandler
from telegram import InputTextMessageContent, ParseMode, Poll, Update, ReplyKeyboardMarkup
import logging
import random
import json

updater = Updater(token='TOKEN', use_context=True)

jobqueue = updater.job_queue
dispatcher = updater.dispatcher

logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', level=logging.INFO)

#initiating values for conversationhandler states
ADD_WISH_ANSWER = 0
KEY_ANSWER = 1

def load_users():
	with open('users.json', 'r') as user_list:
		users = json.load(user_list)
		return users

def get_user(chat_id):
	user_list = load_users()
	for user in user_list:
		if user['user_chat_id'] == chat_id:
			return user

def write_to_user(current_user, chat_id):
	users = load_users()
	for i in range(len(users)):
		if users[i]['user_chat_id'] == chat_id:
			users[i] = current_user
			with open('users.json', 'w') as user_list:
				json.dump(users, user_list)

def load_key_list():
	with open('key_list.json', 'r') as key_list:
		key_list = json.load(key_list)
		return key_list

def write_to_key_list(data):
	with open('key_list.json', 'w') as key_list:
		json.dump(data, key_list)

def get_lang(chat_id):
	user = get_user(chat_id)
	if user['lang'] == 'eng':
		return 'eng'
	elif user['lang'] == 'ger':
		return 'ger'

def start(update, context):
	text = 	f'''_____ENGLISH VERSION BELOW_____
	Hallo {update.effective_user.mention_html()},
	Hier spricht dein persönlicher wishingwellbot. Möchtest du auf /deutsch oder auf /english fortfahren?
	\n
	Hello {update.effective_user.mention_html()},
	This is your personal wishingwellbot. Do you want to continue in /deutsch or in /english ?.'''

	context.bot.send_message(chat_id=update.effective_chat.id, text=text, parse_mode=ParseMode.HTML)

	#if user has no profile, create one an save it in the json file
	if not get_user(update.effective_chat.id):
		users = load_users()
		with open('users.json', 'w') as user_list:
			users.append({'user_chat_id': update.effective_chat.id, 'lang': None, 'partner_chat_id': None, 'wish_list': []})
			json.dump(users, user_list)

def english(update, context):
	text = 	f'''Hi {update.effective_user.mention_html()},
	let\'s start our formal introduction. You can use me to write wishes you have concerning your well-beeing and
	partnership into a wishlist.

	You should start by connecting (/connect) your profil with your partners. Once you generated a key, show that key to
	your partner. They can then enter that key after the command /key. Alternatively you can enter your partners key after the command
	/key.

	After that you can add wishes (/add_wish) to your wishlist or fulfill a wish of your partner (/grant_a_wish)

	These are the commands:
	/connect - generates a key to connect to your partner
	/key - enter the key generated by your partner here to connect
	/disconnect - deletes the connection to your partner
	/add_wish - adds a wish to your wishlist
	/show_wishlist - displays your wishlist
	/remove_wish - shows you your wishes in a poll
	/grant_a_wish - shows you two random wishes of your partner
	/spent_some_love - help my maker to make me better
	/cancel - cancels /add_wish or /key'''

	#create keyboardmarkup buttons and keyboardmarkup
	buttons = [['/connect','/key'],['/add_wish', '/remove_wish'],['/show_wishlist', '/grant_a_wish'],['/cancel', '/help'],['/settings']]
	reply_markup = ReplyKeyboardMarkup(buttons, one_time_keyboard = False)

	context.bot.send_message(update.effective_chat.id, text, reply_markup=reply_markup, parse_mode=ParseMode.HTML)

	#set language to english and save it in the user profile
	user = get_user(update.effective_chat.id)
	user['lang'] = 'eng'
	write_to_user(user, update.effective_chat.id)

def deutsch(update, context):
	#same as /english but with german text
	text = f'''Hi {update.effective_user.mention_html()},
	willkommen beim wishingwellbot. Mein Ziel ist es eure Beziehung glücklicher zu machen.
	Du kannst mich benutzen um Wünsche, die du hast in einer Liste zu speichern. Wenn du einen Wunsch erfüllen möchtest,
	zeige ich dir gern zwei zufällige Wünsche deiner Partnerin oder deines Partners an.

	Beginne damit, dich mit deiner Partnerin oder deinem Partner zu /verbinden. Dazu benötigt ihr beide den @wishingwellbot in
	eurem Telegram Account. Du erhältst einen Schlüssel (sechsstellige Zahl). Die andere Person muss diesen Schlüssel unter dem Befehl
	/schluessel eingeben. Du kannst auch selbst einen Schlüssel eingeben, wenn die andere Person bereits einen Schlüssel erstellt hat.

	Danach kann jede Person für sich selbst Wünsche zur eigenen Wunschliste hinzufügen (/wuensch_dir_was)oder sich Wünsche der anderen Person anzeigen lassen(/wunsch_erfuellen).

	Folgende Befehle gibt es:
	/verbinden - erzeugt einen Schlüssel, um dich mit einer anderen Person zu verbinden
	/schluessel - gib hier den Schlüssel ein, um die Verbindung herzustellen
	/trenne_dich - löscht die Verbindung zur anderen Person
	/wuensch_dir_was - füge einen Wunsch zu deiner Wunschliste hinzu
	/wunschliste - zeigt dir deine Wunschliste
	/wunsch_loeschen - löscht die Wünsche deiner Wahl von deiner Wunschliste
	/wunsch_erfuellen -  erfülle einen Wunsch der anderen Person, es werden dir zwei zufällig angezeigt
	/spende_liebe - hilf meinem Macher mich besser zu machen
	/cancel - beendet die Funktion /wuensch_dir_was oder /schluessel
	'''

	buttons = [['/verbinden','/schluessel'],['/wuensch_dir_was', '/wunsch_loeschen'],['/wunschliste', '/wunsch_erfuellen'],['/cancel', '/hilfe'],['/einstellungen']]

	reply_markup = ReplyKeyboardMarkup(buttons, one_time_keyboard = False)

	context.bot.send_message(update.effective_chat.id, text, reply_markup=reply_markup, parse_mode=ParseMode.HTML)

	user = get_user(update.effective_chat.id)

	user['lang'] = 'ger'

	write_to_user(user, update.effective_chat.id)

def cancel(update, context):
	#cancels the conversations for /key and /add_wish

	#at first the language the user chose is checked and the text is set accordingly
	if get_lang(update.effective_chat.id) == 'eng':
		text = f'Okay then. Maybe another time.'
	elif get_lang(update.effective_chat.id) == 'ger':
		text = f'Alles klar. Vielleicht ein anderes mal.'

	#now the text is send to the user
	context.bot.send_message(chat_id=update.effective_chat.id, text=text)
	return ConversationHandler.END

def wrong_input(update, context):
	#if the user is sending a second command, apart from /cancel, after the conversation started this function is raised and ends the conversation
	if get_lang(update.effective_chat.id) == 'eng':
		text = f'Ups. You sent to many commands. Now I\'m not sure what you wanted to do. What was it again?'
	elif get_lang(update.effective_chat.id) == 'ger':
		text=f'Ups. Jetzt hast du versehentlich mehrere Befehle auf einmal ausgeführt. Versuche es noch einmal.'

	context.bot.send_message(chat_id=update.effective_chat.id, text= text)
	return ConversationHandler.END

def add_wish(update, context):
	#starts the conversationhandler to add a wish to the wishlist

	if get_lang(update.effective_chat.id) == 'eng':
		text = f'What wish do you want to add? You can add multiple wishes by writting each wish in a new line.'
	elif get_lang(update.effective_chat.id) == 'ger':
		text = f'Welchen Wunsch möchtest du hinzufügen? Du kannst mehrere Wünsche hinzufügen, indem du jeden Wunsch in eine neue Zeile schreibst.'

	context.bot.send_message(chat_id=update.effective_chat.id, text= text)
	return ADD_WISH_ANSWER

def add_wish_answer(update, context):
	#adds wishes to the wishlist
	#multiple wishes are possible, if each wish is in a new line
	wishes = update.message.text.split('\n')
	user = get_user(update.effective_chat.id)
	answer = ''
	for wish in wishes:
		user['wish_list'].append(wish)
		#text for the reply is created
		if wish != wishes[-1]:
			if get_lang(update.effective_chat.id) == 'eng':
				answer += wish + ' and '
			elif get_lang(update.effective_chat.id) == 'ger':
				answer += wish + ' und '
		else:
			answer += wish

	if get_lang(update.effective_chat.id) == 'eng':
		text = f'{answer} has been added to the wish list.'
	elif get_lang(update.effective_chat.id) == 'ger':
		text = f'{answer} wurde(n) der Wunschliste hinzugefügt.'

	#wishlist is updated, reply send to user and conversation ended
	write_to_user(user, update.effective_chat.id)
	context.bot.send_message(chat_id=update.effective_chat.id, text= text)
	return ConversationHandler.END

def show_wishlist(update, context):
	user = get_user(update.effective_chat.id)
	wish_list = user['wish_list']

	if get_lang(update.effective_chat.id) == 'eng':
		text1 = 'Your wishlist is currently empty. If you want to add a wish type /add_wish'
		text2 = '\n'.join(wish_list)
	elif get_lang(update.effective_chat.id) == 'ger':
		text = 'Du hast gerade keinen Wunsch in deiner Wunschliste. Wenn du einen hinzufügen möchtest, tippe /wuensch_dir_was'
		text2 = '\n'.join(wish_list)

	if len(wish_list) == 0:
		context.bot.send_message(chat_id=update.effective_chat.id, text= text1)
	else:
		context.bot.send_message(chat_id=update.effective_chat.id, text= text2)

def remove_wish(update, context):
	if get_lang(update.effective_chat.id) == 'eng':
		placeholder = 'This is just a placeholder, because a poll needs at least two options. Please don\'t select me.'
		text = 'You can\'t delete a wish since your wishlist is empty.'
		text2 = 'This is your wishlist. Select the wishes you want to remove and press "Vote".'
	elif get_lang(update.effective_chat.id) == 'ger':
		placeholder = 'Das ist nur ein Platzhalter. Eine Umfrage mindestens 2 Optionen braucht. Bitte wähle mich nicht aus.'
		text = 'Du kannst keinen Wunsch löschen, weil deine Wunschliste leer ist.'
		text2 = 'Das ist deine Wunschliste. Wähle die Wünsche aus, die du löschen möchtest und drücke auf "Abstimmen".'

	#first the wishlist is loaded
	user = get_user(update.effective_chat.id)
	wish_list = user['wish_list']

	#now the length of the wishlist is checked
	#since a poll can only contain 10 options a number of sets is calculated
	#each set represents a poll
	#if the poll would contain only one option a placeholder is added
	if len(wish_list) == 0:
		context.bot.send_message(update.effective_chat.id, text)
		return
	elif len(wish_list)%10 == 0:
		n_of_sets = len(wish_list)//10
	else:
		n_of_sets = len(wish_list)//10+1
	for i in range(n_of_sets):
		wishes = wish_list[i*10:i*10+10]
		if len(wish_list) == 1:
			wishes.append(placeholder)
		message = context.bot.send_poll(update.effective_chat.id, text2, wishes, is_anonymous=False, allows_multiple_answers=True)
		#the poll data is saved in the bot to handle when the user takes the poll
		payload = {
			message.poll.id: {
				"wishes": wishes,
				"message_id": message.message_id,
				"chat_id": update.effective_chat.id,
				"answers": 0,
			}
		}
		context.bot_data.update(payload)

def remove_wish_answer(update, context):
	answer = update.poll_answer
	poll_id = answer.poll_id
	chat_id = context.bot_data[poll_id]["chat_id"]

	if get_lang(chat_id) == 'eng':
		text = f"The wish wasn\'t on the list for some reason ;). Or you selected the placeholder!"
	elif get_lang(chat_id) == 'ger':
		text = f"Der Wunsch war aus irgendeinem Grund nicht mehr auf der Liste ;). Oder du hast den Platzhalter ausgewählt!"

	#Summarize a users poll vote
	wish_list = get_user(chat_id)['wish_list']
	try:
		wishes = context.bot_data[poll_id]["wishes"]
	#this means this poll answer update is from an old poll, we can't do our answering then
	except KeyError:
		return
	selected_options = answer.option_ids
	answer_string = ""
	removed_wishes = []
	for question_id in selected_options:
		#answerstring is created the same way as in /add_wish_answer
		if question_id != selected_options[-1]:
			if get_lang(chat_id) == 'eng':
				answer_string += wishes[question_id] + " and "
				removed_wishes.append(wishes[question_id])
			elif get_lang(chat_id) == 'ger':
				answer_string += wishes[question_id] + " und "
				removed_wishes.append(wishes[question_id])
		else:
			answer_string += wishes[question_id]
			removed_wishes.append(wishes[question_id])

	#if a wish is about to be removed from the list, but isn't there anymore
	#it means the partner granted the wish already, so the user get's a message
	for wish in removed_wishes:
		try:
			wish_list.remove(wish)
		except ValueError:
			context.bot.send_message(
				chat_id,
				text
			)

	if get_lang(chat_id) == 'eng':
		text = f"You removed {answer_string} from your wishlist!"
	elif get_lang(chat_id) == 'ger':
		text = f"Du hast {answer_string} von deiner Wunschliste entfernt!"

	context.bot.send_message(
		chat_id,
		text
	)
	context.bot.stop_poll(
		chat_id, context.bot_data[poll_id]["message_id"]
	)

	#overwrite wishlist of current user
	user = get_user(chat_id)
	user['wish_list'] = wish_list
	write_to_user(user, chat_id)

def connect(update, context):
	key = random.randint(100000, 999999)

	if get_lang(update.effective_chat.id) == 'eng':
		text = 'You already generated a key. Please wait for your partner to connect.'
		text2 = f'To connect with your partner please show him or her the key: {key} \n They have to enter \"/key (your key)\" to connect with your profile.'
		text3 = 'You are already connected to someone. Do you want to /disconnect?'
	elif get_lang(update.effective_chat.id) == 'ger':
		text = 'Du hast bereits einen Schlüssel. Bitte warte darauf, dass sich die andere Person mit dir verbindet.'
		text2 = f'Um dich mit deiner Partnerin, deinem Partner zu verbinden, zeig ihr oder ihm bitte den Schlüssel: {key}\nDeine Partnerin oder dein Partner muss dann den Befehl  \"/schluessel\" ausführen und anschließend den Schlüssel eingeben, um sich mit dir zu verbinden.'
		text3 = 'Du bist bereits mit jemandem verbunden. Möchtest du dich trennen? /trenne_dich'

	user = get_user(update.effective_chat.id)
	key_list = load_key_list()

	#this checks if the user already is connected, already generated a key before actually
	#creating and passing a key-user-pair
	#this is to keep the keylist clean an to prefent accidental connecting to several persons
	try:
		for entry in key_list:
			#checks if user already created a key
			if entry['user_chat_id'] == update.effective_chat.id:
				context.bot.send_message(update.effective_chat.id, text)
				return
		#checks if user already has a partner
		if user['partner_chat_id'] is None:
			context.bot.send_message(chat_id=update.effective_chat.id, text=text2)
			key_list.append({'key': key, 'user_chat_id': update.effective_chat.id})
			write_to_key_list(key_list)
			return
		else:
			context.bot.send_message(update.effective_chat.id, text3)
			return
	except:
		pass
	#fallback if keylist is empty and the forloop fails
	else:
		if user['partner_chat_id'] is None:
			context.bot.send_message(chat_id=update.effective_chat.id, text=text2)
			key_list.append({'key': key, 'user_chat_id': update.effective_chat.id})
			write_to_key_list(key_list)
		else:
			context.bot.send_message(update.effective_chat.id, text3)

def key(update, context):
	#starts the /key conversationhandler
	if get_lang(update.effective_chat.id) == 'eng':
		text = 'Oh! You\'re already connected to someone. Do you want to make a new connection? Then you must /disconnect first.'
		text2 = 'Ah! You want to connect to someone. Good for you! What\'s the key?'
	elif get_lang(update.effective_chat.id) == 'ger':
		text = 'Oh! Du bist schon mit jemandem verbunden. Möchtest du eine neue Verbindung aufbauen? Dann /trenne_dich zu erst von der bestehenden Verbindung.'
		text2 = 'Ah! Du möchtest dich mit jemandem verbinden. Das freut mich für dich! Wie lautet der Schlüssel?'

	user = get_user(update.effective_chat.id)
	#checks if user is already connected and ends conversation if so
	if user['partner_chat_id']:
		context.bot.send_message(update.effective_chat.id, text)
		return ConversationHandler.END
	context.bot.send_message(update.effective_chat.id, text2)
	return KEY_ANSWER

def key_answer(update, context):
	if get_lang(update.effective_chat.id) == 'eng':
		text = f'Conragtulations! You are now both connected through the wishingwell. Now go on and fulfill each others wishes and create a happier relationship!'
		text2 = 'Your key wasn\'t found. Please try again.'
		text3 = 'Sorry. I couldn\'t read your key. It must be a number with 6 digits. Please try again.'
	elif get_lang(update.effective_chat.id) == 'ger':
		text = f'Herzlichen Glückwunsch! Ihr seid nun beide durch den Wunschbrunnen mit einander verbunden. Jetzt legt los und macht euch glücklich(er). Viel Spaß beim Wünschen!'
		text2 = 'Dein Schlüssel wurde nicht gefunden. Bitte versuche es noch einmal.'
		text3 = 'Entschuldigung, den Schlüssel konnte ich nicht lesen. Es muss eine sechsstellige Zahl sein. Bitte versuche es noch einmal.'

	key_list = load_key_list()
	try:
		key = int(update.message.text)
		for i in range(len(key_list)):
			#searches the key-user-pair
			if key_list[i]['key'] == key:
				user1 = get_user(key_list[i]['user_chat_id'])
				user1['partner_chat_id'] = update.effective_chat.id
				write_to_user(user1, key_list[i]['user_chat_id'])
				user2 = get_user(update.effective_chat.id)
				user2['partner_chat_id'] = key_list[i]['user_chat_id']
				write_to_user(user2, update.effective_chat.id)
				context.bot.send_message(chat_id=update.effective_chat.id, text=text)
				context.bot.send_message(chat_id=key_list[i]['user_chat_id'], text=text)
				#this removes the key-user-pair and checks if the partner also generated a key
				#if so this key-user-pair is also deleted, then the conversation is ended
				key_list.pop(i)
				for j in range(len(key_list)-1):
					if key_list[j]['user_chat_id'] == update.effective_chat.id:
						key_list.pop(j)
				write_to_key_list(key_list)
				return ConversationHandler.END
		#answer if the key wasn't found
		context.bot.send_message(update.effective_chat.id, text2)
	#fallback if user enters anything but a number
	except ValueError as err:
		context.bot.send_message(update.effective_chat.id, text3)

def disconnect(update, context):
	if get_lang(update.effective_chat.id) == 'eng':
		text = 'You are now disconnected. :('
	elif get_lang(update.effective_chat.id) == 'ger':
		text = 'Du bist nun getrennt. :('

	user = get_user(update.effective_chat.id)
	user2 = get_user(user['partner_chat_id'])
	user2_id = user['partner_chat_id']
	user['partner_chat_id'] = None
	user2['partner_chat_id'] = None
	context.bot.send_message(update.effective_chat.id, text)
	write_to_user(user, update.effective_chat.id)
	write_to_user(user2, user2_id)

def grant_a_wish(update, context):
	if get_lang(update.effective_chat.id) == 'eng':
		placeholder = 'This is just a placeholder, because a poll needs at least two options. Please don\'t select me.'
		text1 = 'Here are two wishes from your partner. Choose which one you want to fullfill and select that one.'
		text2 = 'Your partner has only one wish.'
		text3 = 'Your partner has no wish on the wish list. Go and say "I love you" anyway. Unless you don\'t, then don\'t. But if you do, do it. Now!'
		text4 = 'You\'re not yet connected to someone. Do you want to /connect ?'
	elif get_lang(update.effective_chat.id) == 'ger':
		placeholder = 'Das ist ein Platzhalter, da eine Umfrage mindestens 2 Optionen braucht. Bitte wähle mich nicht aus.'
		text1 = 'Hier sind zwei zufällige Wünsche von der Wunschliste deiner Partnerin oder deines Partners. Wähle einen aus und erfülle ihn.'
		text2 = 'Deine Partnerin, dein Partner hat nur einen Wunsch.'
		text3 = 'Deine Partnerin, dein Partner ist wunschlos glücklich. Aber wenn du jetzt zu ihr oder ihm sagst "Ich liebe dich", machst du ihn oder sie bestimmt noch glücklicher. Also los!'
		text4 = 'Du bist noch mit niemandem verbunden. Möchtest du dich mit jemandem /verbinden ?'

	current_user = get_user(update.effective_chat.id)
	try:
		partner = get_user(current_user['partner_chat_id'])
		wish_list = partner['wish_list']
		partner_chat_id = current_user['partner_chat_id']
		#a poll with two random wishes of the partner is created
		#if the partner has no wish text3 is send to the user and the function ended
		#if the partner has only wish a placeholder is added
		if len(wish_list) > 1:
			rands = set()
			while len(rands) < 2:
				rands.add(random.randint(0, len(wish_list)-1))
			wishes = []
			for rand in rands:
				wishes.append(wish_list[rand])
			text = text1
		elif len(wish_list) == 1:
			wishes = wish_list[:]
			wishes.append(placeholder)
			text = text2
		else:
			text = text3
			context.bot.send_message(update.effective_chat.id, text)
			return
		message = update.effective_message.reply_poll(text, wishes, type=Poll.REGULAR)
		payload = {
			message.poll.id: {
				"wishes": wishes,
				"wish_list": wish_list,
				"message_id": message.message_id,
				"chat_id": update.effective_chat.id,
				"partner_chat_id": partner_chat_id
			}
		}
		context.bot_data.update(payload)
	#fallback if the user isn't connected to someone
	except TypeError:
		context.bot.send_message(update.effective_chat.id, text4)

def grant_a_wish_answer(update, context):
	if update.poll.is_closed:
		return
	else:
		try:
			quiz_data = context.bot_data[update.poll.id]
		# this means this poll answer update is from an old poll, we can't stop it then
		except KeyError:
			return
		wish_fulfilled = ''

		answer = update.poll.options
		for option in answer:
			if option['voter_count'] == 1:
				wish_fulfilled = option['text']
				wish_list = quiz_data['wish_list']
				if get_lang(quiz_data["chat_id"]) == 'eng':
					text = f'You fulfilled {wish_fulfilled}.'
					text2 = f'For some reason the wish wasn\'t in the wishlist anymore. Or you selected the placeholder.'
				elif get_lang(quiz_data["chat_id"]) == 'ger':
					text = f'Du hast {wish_fulfilled} erfüllt.'
					text2 = f'Aus irgendeinem Grund war der Wunsch nicht mehr in der Wunschliste. Oder du hast den Platzhalter ausgewählt.'
				#check if wish is still there to be removed
				#if not it means was delete by the partner or the placeholder was selected and text2is send to user
				try:
					wish_list.remove(wish_fulfilled)
					partner = get_user(quiz_data['partner_chat_id'])
					partner['wish_list'] = wish_list
					write_to_user(partner, quiz_data['partner_chat_id'])
					context.bot.stop_poll(quiz_data["chat_id"], quiz_data["message_id"])
					context.bot.send_message(quiz_data['chat_id'], text)
				except ValueError:
					context.bot.stop_poll(quiz_data["chat_id"], quiz_data["message_id"])
					context.bot.send_message(quiz_data['chat_id'], text2)

def spent_some_love(update, context):
	#simple function asking for feedback and support
	if get_lang(update.effective_chat.id) == 'eng':
		text = 'Hey there, \nIf you like the bot and improved your relationship, maybe you want to help me out a bit. Every small donation or nice words to wishingwellbot@posteo.de (PayPal) is highly appreciated.'
	elif get_lang(update.effective_chat.id) == 'ger':
		text = 'Hallihallo, \nWenn du den Bot magst und deine Beziehung verbessert hast, magst du mir vielleicht helfen. Jede kleine Spende, Kritik oder nette Worte an wishingwellbot@posteo.de (PayPal) helfen und freuen mich sehr.'

	context.bot.send_message(update.effective_chat.id, text)

def help(update, context):
	if get_lang(update.effective_chat.id) == 'eng':
		text = '''Hello, \nYou need some help? No problem! Let me explain the options you have:
		/connect - generates a key to connect to your partner
		/key - enter the key generated by your partner here to connect
		/disconnect - deletes the connection to your partner
		/add_wish - adds a wish to your wishlist
		/show_wishlist - displays your wishlist
		/remove_wish - shows you your wishes in a poll
		/grant_a_wish - shows you two random wishes of your partner
		/spent_some_love - help my maker to make me better
		/cancel - cancels /add_wish or /key
		/help - shows you the available commands
		/settings - let\'s you change the language

		If something is still unclear or you have suggestions to improve the bot, just drop a message to wishingwellbot@posteo.de'''
	elif get_lang(update.effective_chat.id) == 'ger':
		text = '''Hallo, \nDu benötigst Hilfe? Klar, kein Problem! Hier sind noch einmal alle verfügbaren Befehle:
		/verbinden - erzeugt einen Schlüssel, um dich mit einer anderen Person zu verbinden
		/schluessel - gib hier den Schlüssel ein, um die Verbindung herzustellen
		/trenne_dich - löscht die Verbindung zur anderen Person
		/wuensch_dir_was - füge einen Wunsch zu deiner Wunschliste hinzu
		/wunschliste - zeigt dir deine Wunschliste
		/wunsch_loeschen - löscht die Wünsche deiner Wahl von deiner Wunschliste
		/wunsch_erfuellen -  erfülle einen Wunsch der anderen Person, es werden dir zwei zufällig angezeigt
		/spende_liebe - hilf meinem Macher mich besser zu machen
		/cancel - beendet die Funktion /wuensch_dir_was oder /schluessel
		/hilfe - zeigt dir alle verfügbaren Befehle
		/einstellungen - hier kannst du die Sprache des Bots ändern

		Wenn noch immer etwas unklar ist oder du Vorschläge für eine Verbesserung hast, dann schreib mir einfach an wishingwellbot@posteo.de.'''

	context.bot.send_message(update.effective_chat.id, text)

def settings(update, context):
	#function to change the language
	#to be exchange by an inlinekeyboardmarkup
	if get_lang(update.effective_chat.id) == 'eng':
		text = 'You want to change the language? Do you want to talk in /english oder in /deutsch with me?'
	elif get_lang(update.effective_chat.id) == 'ger':
		text = 'Du möchtest die Sprache ändern? Möchtest du mit mir in /english oder in /deutsch weiter reden?'

	context.bot.send_message(update.effective_chat.id, text)

def get_me(update, context):
	context.bot.send_message(update.effective_chat.id, update.effective_chat.id)

def statistics(update, context):
	users = load_users()
	lonley_user_count = 0
	for user in users:
		if user['partner_chat_id'] == None:
			lonley_user_count += 1
	context.bot.send_message(ADMIN_CHAT_ID, text= 'NutzerInnen insgesamt: ' + str(len(users)) + '\nNutzerInnen ohne Verbindung: ' + str(lonley_user_count))

def weekly_job(context, job):
	jobqueue.run_repeating(statistics, interval= 604800, first= 10)

def main():
	#the first few commands to start the bot and set the user profile
	start_handler = CommandHandler('start', start)
	dispatcher.add_handler(start_handler)

	english_handler = CommandHandler('english', english)
	dispatcher.add_handler(english_handler)

	deutsch_handler = CommandHandler('deutsch', deutsch)
	dispatcher.add_handler(deutsch_handler)

	#english commands
	add_wish_conv_handler = ConversationHandler(entry_points = [CommandHandler('add_wish',  add_wish)],
		states = {ADD_WISH_ANSWER: [MessageHandler(Filters.text & (~Filters.command), add_wish_answer)]},
		fallbacks = [CommandHandler('cancel', cancel), MessageHandler(Filters.command, wrong_input)])

	key_conv_handler = ConversationHandler(entry_points = [CommandHandler('key',  key)],
		states = {KEY_ANSWER: [MessageHandler(Filters.text & (~Filters.command), key_answer)]},
		fallbacks = [CommandHandler('cancel', cancel), MessageHandler(Filters.command, wrong_input)])

	dispatcher.add_handler(key_conv_handler)
	dispatcher.add_handler(add_wish_conv_handler)

	show_wishlist_handler = CommandHandler('show_wishlist', show_wishlist)
	dispatcher.add_handler(show_wishlist_handler)

	remove_wish_handler = CommandHandler('remove_wish', remove_wish)
	dispatcher.add_handler(remove_wish_handler)

	dispatcher.add_handler(PollAnswerHandler(remove_wish_answer))

	connect_handler = CommandHandler('connect', connect)
	dispatcher.add_handler(connect_handler)

	disconnect_handler = CommandHandler('disconnect', disconnect)
	dispatcher.add_handler(disconnect_handler)

	grant_a_wish_handler = CommandHandler('grant_a_wish', grant_a_wish)
	dispatcher.add_handler(grant_a_wish_handler)

	grant_a_wish_answer_handler = PollHandler(grant_a_wish_answer)
	dispatcher.add_handler(grant_a_wish_answer_handler)

	help_handler = CommandHandler('help', help)
	dispatcher.add_handler(help_handler)

	settings_handler = CommandHandler('settings', settings)
	dispatcher.add_handler(settings_handler)

	spent_some_love_handler = CommandHandler('spent_some_love', spent_some_love)
	dispatcher.add_handler(spent_some_love_handler)

	#german commands
	add_wish_conv_handler = ConversationHandler(entry_points = [CommandHandler('wuensch_dir_was', add_wish)],
		states = {ADD_WISH_ANSWER: [MessageHandler(Filters.text & (~Filters.command), add_wish_answer)]},
		fallbacks = [CommandHandler('cancel', cancel), MessageHandler(Filters.command,wrong_input)])

	key_conv_handler = ConversationHandler(entry_points = [CommandHandler('schluessel', key)],
		states = {KEY_ANSWER: [MessageHandler(Filters.text & (~Filters.command), key_answer)]},
		fallbacks = [CommandHandler('cancel', cancel), MessageHandler(Filters.command,wrong_input)])

	dispatcher.add_handler(key_conv_handler)
	dispatcher.add_handler(add_wish_conv_handler)

	show_wishlist_handler = CommandHandler('wunschliste',show_wishlist)
	dispatcher.add_handler(show_wishlist_handler)

	remove_wish_handler = CommandHandler('wunsch_loeschen',remove_wish)
	dispatcher.add_handler(remove_wish_handler)

	dispatcher.add_handler(PollAnswerHandler(remove_wish_answer))

	connect_handler = CommandHandler('verbinden',connect)
	dispatcher.add_handler(connect_handler)

	disconnect_handler = CommandHandler('trenne_dich',disconnect)
	dispatcher.add_handler(disconnect_handler)

	grant_a_wish_handler = CommandHandler('wunsch_erfuellen',grant_a_wish)
	dispatcher.add_handler(grant_a_wish_handler)

	grant_a_wish_answer_handler = PollHandler(grant_a_wish_answer)
	dispatcher.add_handler(grant_a_wish_answer_handler)

	help_handler = CommandHandler('hilfe', help)
	dispatcher.add_handler(help_handler)

	settings_handler = CommandHandler('einstellungen', settings)
	dispatcher.add_handler(settings_handler)

	spent_some_love_handler = CommandHandler('spende_liebe',spent_some_love)
	dispatcher.add_handler(spent_some_love_handler)

	#jobqueue sending me statistics every week
	statistics_handler = CommandHandler('statistics', statistics, pass_job_queue=True)
	dispatcher.add_handler(statistics_handler)

	updater.start_polling()

	updater.idle()

if __name__ == '__main__':
	main()


import unittest
import io

from seqfiletk.sample import sample, get_number_sequences

class TestSample(unittest.TestCase):
    def setUp(self):
        self.input_str=""">test0
aaaaaaaaaaaaaaaa
>test1
cccccccccccccccc
>test2
dddddddddddddddd
>test3
tttttttttttttttt
        """

        self.input=io.StringIO(self.input_str)
        self.output=io.StringIO()

    def test_get_number_sequences(self):
        c = get_number_sequences(self.input, 'fasta')
        self.assertEqual(4, c)

    def test_sample(self):
        sample(self.input, self.output, number_sequences=2, seed=0)
        sampled_file_str = self.output.getvalue()

        ans_file_str = """>test2
dddddddddddddddd
>test3
tttttttttttttttt
"""
        self.assertEqual(ans_file_str, sampled_file_str)

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


from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler
import os
import time
import datetime
from datetime import date
from data_storage import *

doc_types = ('.doc', '.docx', '.txt', '.pdf', '.xls', '.ppt', '.xlsx', '.pptx')
img_types = ('.jpg', '.jpeg', '.png', '.svg', '.gif', '.tif', '.tiff')
software_types = ('.exe', '.pkg', '.dmg')

# now = datetime.datetime.now()
# current_hour = now.hour
# current_minute = now.minute
# current_date = date.today()

# global f_name
# f_name = f"Screen Shot "

# assumes at least one of the following arguments is unique:
#   time, days_of_week, source_path, desired_files
class Handler(FileSystemEventHandler):
    def on_modified(self, event):
        names = get_all_names()
        for name in names:
            src_path = get_entry_by_key(name, "sourcePath")
            hours = get_entry_by_key(name, "hours")
            mins = get_entry_by_key(name, "mins")
            days_of_week = get_entry_by_key(name, "daysOfWeek")

            # check if date matches
            now = datetime.datetime.now()
            if (now.hour == int(hours)) and (now.minute >= int(mins)) \
                    and (date.today().weekday() in days_of_week):
                self.find_files(name, now, src_path)

    def find_files(self, name, now, src_path):
        dest_path = get_entry_by_key(name, "destPath")
        desired_files = get_entry_by_key(name, "desiredFiles")
        new_file_name = get_entry_by_key(name, "newFileName")

        # look through all files at source path
        for file in os.listdir(src_path):
            source = src_path + '/' + file
            file_name = os.path.splitext(source)[0]
            file_extension = os.path.splitext(source)[1]

            # check for name or extension in desired files
            if (file_extension in desired_files) or (file_name in desired_files):
                am_pm = "AM"
                if now.hour > 12:
                    am_pm = "PM"

                # move file
                new_path = dest_path + '/' + str(date.today()) + "-" + str(now.hour) + am_pm
                os.makedirs(new_path, exist_ok=True)

                # rename files
                number_files = len(os.listdir(new_path))
                new = new_path + '/File-' + str((number_files + 1)) + str(file_extension)
                os.rename(source, new)

# path_file = open('path.txt', 'r')
# tracker_paths = path_file.readline()
# tracker = '/Users/kaitl'
# path_file = open('path_destination.txt', 'r')
# destination_paths = path_file.readline()
# destination = '/Users/kaitl/Downloads/test'
# if current_hour == 3:
#     destination = '/Users/sahaj/Desktop/SC2'
# elif current_hour == 4:
#     destination = '/Users/sahaj/Desktop/SC3'

event_handler = Handler()
observer = Observer()

# initialize observer for each path
source_paths = extract_entries_by_key("sourcePath")
source_paths = list(set(source_paths))
for path in source_paths:
    print(path)
    observer.schedule(event_handler, path=path, recursive=True)
observer.start()
print("observer start")

try:
    while True:
        time.sleep(10)
except KeyboardInterrupt:
    observer.stop()
observer.join()


import os
import json
import numpy as np
import pylab as pl
import datetime
from textblob import TextBlob

CURRENT_DIRECTORY = os.getcwd()
NUMBER_TO_ANALYZE = 10000
MESSAGE_THRESHOLD = 100

def get_json_data(chat):
    try:
        json_location = CURRENT_DIRECTORY + "/messages/" + chat + "/message.json"
        with open(json_location) as json_file:
            json_data = json.load(json_file)
            return json_data
    except IOError:
        pass # some things the directory aren't messages (DS_Store, stickers_used, etc.)

chats = os.listdir(CURRENT_DIRECTORY + "/messages")[:NUMBER_TO_ANALYZE]
sorted_chats = []
final_data_messages = {}
final_data_times = {}
final_data_num_words = {}
final_data_words = {}
invalid_message_count = 0

print('Analyzing ' + str(min(NUMBER_TO_ANALYZE, len(chats))) + ' chats...')

for chat in chats:
    json_data = get_json_data(chat)
    if json_data != None:
        messages = json_data["messages"]
        if len(messages) >= MESSAGE_THRESHOLD:
            sorted_chats.append((len(messages), chat, messages))

sorted_chats.sort(reverse=True)

print('Finished processing chats...')

for i, (messages, chat, messages) in enumerate(sorted_chats):
    number_messages = {}
    person_to_times = {}
    number_words = {}
    words = {}

    print(str(i) + " - " + str(len(messages)) + " messages - " + str(chat))

    for message in messages:
        try:
            name = message["sender_name"]
            time = message["timestamp_ms"]
            message_content = message["content"]

            number_messages[name] = number_messages.get(name, 0)
            number_messages[name] += 1

            person_to_times[name] = person_to_times.get(name, [])
            person_to_times[name].append(datetime.datetime.fromtimestamp(time/1000.0))

            number_words[name] = number_words.get(name, [])
            number_words[name].append(len(message_content.split()))

            words[name] = words.get(name, [])
            temp = message_content.split()
            for word in temp:
                if(word.isalpha() and len(word) > 4):
                    words[name].append(word)
            #words[name].append(message_content.split())
        except KeyError:
            # happens for special cases like users who deactivated, unfriended, blocked
            invalid_message_count += 1

    final_data_messages[i] = number_messages
    final_data_times[i] = person_to_times
    final_data_num_words[i] = number_words
    final_data_words[i] = words

print('Found ' + str(invalid_message_count) + ' invalid messages...')
print('Found ' + str(len(sorted_chats)) + ' chats with ' + str(MESSAGE_THRESHOLD) + ' messages or more')

def plot_num_messages(chat_number):
    plotted_data = final_data_messages[chat_number]
    X = np.arange(len(plotted_data))
    pl.bar(X, list(plotted_data.values()), align='center', width=0.5, color = 'r', bottom = 0.3)
    pl.xticks(X, plotted_data.keys(), rotation = 90)
    pl.title('Number of Messages Sent')
    pl.tight_layout()
    pl.show()

def plot_histogram_words(chat_number):
    temp = {}
    for person in final_data_num_words[chat_number]:
        temp[person] = np.average(final_data_num_words[chat_number][person])
    plotted_data = temp
    X = np.arange(len(plotted_data))
    pl.bar(X, list(plotted_data.values()), align='center', width=0.5, color = 'r', bottom = 0.3)
    pl.xticks(X, plotted_data.keys(), rotation = 90)
    pl.title('Average Word Count')
    pl.tight_layout()
    pl.show()

def most_common_words(chat_number):
    print("\nMost Common Words:")
    for person in final_data_words[chat_number]:
        count = 0
        tempcount = 0
        words = final_data_words[chat_number][person]
        for word in words:
            for another in words:
                if(word == another):
                    tempcount += 1
            if(tempcount > count):
                count = tempcount
                result = word
            tempcount = 0
        print(person+": "+result)

def sentiment_analysis(chat_number):
    print("\nSentiment Analysis:")
    for person in final_data_words[chat_number]:
        count = 0
        tempcount = 0
        sentiment = get_sentiment(" ".join(final_data_words[chat_number][person]))
        print(person+": "+sentiment)

def get_sentiment(mess):
        '''
        Utility function to classify sentiment of passed tweet
        using textblob's sentiment method
        '''
        # create TextBlob object of passed tweet text
        analysis = TextBlob(mess)
        # set sentiment
        if analysis.sentiment.polarity > 0:
            return 'positive'
        elif analysis.sentiment.polarity == 0:
            return 'neutral'
        else:
            return 'negative'

def plot(chat_number):
    plot_num_messages(chat_number)
    plot_histogram_words(chat_number)

plot(18)
most_common_words(18)
sentiment_analysis(18)


import time

import jax.numpy as jnp
from datasets import concatenate_datasets, load_dataset
from whisper_jax import FlaxWhisperPipline

BATCH_SIZES = [4, 8, 16, 32, 64, 128]
NUM_BATCHES = 100

# load a dataset of 73 audio samples
librispeech = load_dataset("hf-internal-testing/librispeech_asr_dummy", "clean", split="validation")

for batch_size in BATCH_SIZES:
    eval_dataset = librispeech.select(range(batch_size // 2))
    eval_dataset = concatenate_datasets([eval_dataset for _ in range(2 * NUM_BATCHES)])

    eval_dataloader = eval_dataset.with_format("numpy").iter(batch_size=batch_size)

    # Create the FlaxWhisperPipeline object
    pipeline = FlaxWhisperPipline(
        "openai/whisper-tiny.en",
        dtype=jnp.bfloat16,  # use bfloat16 precision
        batch_size=batch_size,  # enable batching
    )

    # warm-up step
    batch = next(iter(eval_dataloader))

    start = time.time()
    for batch in eval_dataloader:
        for audio in batch["audio"]:
            # Pass the audio file path to the pipeline
            transcription = pipeline(audio["path"])
    runtime = time.time() - start

    print(f"{batch_size}: {runtime:.06}")


# Python initialisieren :
import matplotlib.pyplot as pl;
import numpy as np;
# Parameter:
q=4.; x_0=-12.; x_1=-0.2; x_2=- x_1; x_E=- x_0;
y_a=-6.; y_b=- y_a; N_f =201; N_g =3; lw =3; fig =1;
tc_x=np.r_[x_0: x_E +1.:1.]; tc_y=np.r_[y_a: y_b +1.:1.];
# Funktionen :
def f(x): y =0.5*(x + q / x); return y;
# Daten :
x_a_data=np.linspace(x_0, x_E, N_f);
x_b_data=np.linspace(x_0, x_E, N_f);
f_a_data=f(x_a_data);
f_b_data=f(x_b_data);
x_data=np.linspace(x_0, x_E, N_g);
g_data=x_data;
# Plot :
fh=pl.figure(fig);
pl.plot(x_a_data, f_a_data, linewidth=lw);
pl.plot(x_data, g_data, linewidth=lw);
pl.xlabel(r'$x$'); pl.ylabel(r'$y$');
pl.xticks(tc_x); pl.yticks(tc_y);
pl.grid(visible=True); pl.axis('image');
pl.xlim([x_0, x_E]); pl.ylim([y_a, y_b]);
pl.savefig("02_A04_fixpunkt_iteration.png")


import os
import sys
sys.path.append("lib/itchat")
import itchatmp
import json
# import qrcode
import time
import logging
import time
import requests
import config
from chatbot import ChatBot
from register_menu import register_menu
from user_id import UserId

#########################################################
logger = logging.getLogger('wechat')

USER = UserId()
#########################################################
# for production environment
#########################################################
itchatmp.update_config(itchatmp.WechatConfig(
    token = config.TOCKEN,
    appId = config.APP_ID,
    appSecret = config.APP_SECRET,
    encryptMode = itchatmp.content.SAFE if config.ENCRYPT else itchatmp.content.NORMAL,
    encodingAesKey = config.ENCODING_AES_KEY if config.ENCRYPT else ''))

#########################################################
def get_image_name_from_url(tag, url):
    fileName = url.split('=')[-1]
    return fileName

def fetch_image(tag, url):
    result = requests.get(url)
    if result.status_code != 200:
        logger.error('fetch image {} failed!'.format(url))
        return None
    file_name = get_image_name_from_url(tag, url)
    if not os.path.exists('./uploads'): os.makedirs('./uploads')
    file_path = 'uploads/{}'.format(file_name)
    if not os.path.exists(file_path):
        with open(file_path, 'wb') as file:
            file.write(result.content)
    return file_path

def download_media(media_id):
    r = itchatmp.messages.download(media_id)
    if 'File' in r:
        if not os.path.exists('./downloads'): os.makedirs('./downloads')
        file_path = os.path.join('./downloads', r.get('FileName', 'unknown.jpg'))
        with open(file_path, 'wb') as f:
            f.write(r['File'].getvalue())
        return file_path

# def get_picture_id(media_id):
#     file = download_media(media_id)
#     if not file: return None
#     return qrcode.scan(file)

#########################################################
def construct_reply(reply, user_id, active = False):
    content = reply['content']
    if reply['type'] == 'article':
        print('Reply article')
        title = content['title']
        description = content['description']
        picture_url = content['cover-url']
        article_url = content['content-url']
        article = {'Title':title,'Description':description,'PicUrl':picture_url,'Url':article_url}
        if active : article = {'title':title,'description':description,'picurl':picture_url,'url':article_url}
        return {'MsgType' : itchatmp.content.NEWS,
                'Articles' : [article]}
    elif reply['type'] == 'image':
        print('Reply image')
        pic_tag = content['tag']
        pic_url = content['url']
        logger.error("content is "+ str(content))
        if ('payment' in content) and (content['payment'] == 'wx'):
            itchatmp.send("请您使用微信扫描下面二维码支付，谢谢", user_id)
            return generate_qr_code_url(user_id)
        image = fetch_image(pic_tag, pic_url)
        print('image = ' + image)
        if not image: raise Exception('fetch image from {} failed'.format(pic_url))
        return {'MsgType': itchatmp.content.IMAGE,'FileDir': image}
    elif reply['type'] == 'qrcode':
        print('Reply qrcode')
        orderId = content['orderId']
        return generate_qr_code_url(orderId)
    elif reply['type'] == 'custom-service':
        print('Reply custom-service')
        return generate_reply_by_custom_service(user_id)
    print('Reply text')
    return content

#########################################################
def active_reply(replies, user_id):
    for reply in replies:
        try:
            itchatmp.send(construct_reply(reply, user_id, True), user_id)
        except Exception as e:
            print('Exception occured when active send!')

#########################################################
def reply_to_user(replies, user_id = None):
    if len(replies) > 1:
        active_reply(replies[0:-1], user_id)
    return construct_reply(replies[-1], user_id)

########################################################
@itchatmp.access_token
def get_access_token(accessToken=None):
    return accessToken

def generate_reply_by_custom_service(user_id):
    if (has_online_customer()):
        itchatmp.send("正在帮您接通人工客服，请稍等...", user_id)
        return {'MsgType' : itchatmp.content.TRANSFER}
    return "抱歉，当前客服座席忙，稍后会主动联系您..."

def has_online_customer():
    customUrl = "https://api.weixin.qq.com/cgi-bin/customservice/getonlinekflist?access_token=" + get_access_token()
    logger.error("customUrl is:" + customUrl)
    online_customer = json.loads(requests.get(customUrl).text)
    logger.error("online customer is " + str(online_customer))
    if (len(online_customer["kf_online_list"]) < 1) :
        return False
    else:
        return True

def generate_qr_code_url(orderId):
    wxUrl = "https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=" + get_access_token()
    logger.error("qr generate url is:" + wxUrl)
    body = {"expire_seconds": 604800, "action_name": "QR_STR_SCENE", "action_info": {"scene": {"scene_str": orderId}}}
    rsp = requests.post(wxUrl, json=body)
    picture_url = "https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket="+  json.loads(rsp.text)['ticket']
    imagePath = fetch_image("qrCode", picture_url)
    logger.error("local file path:" + imagePath)
    if not imagePath: raise Exception('fetch image from {} failed'.format(picture_url))
    return {'MsgType': itchatmp.content.IMAGE,'FileDir': imagePath}

#########################################################
@itchatmp.msg_register(itchatmp.content.TEXT)
def text_reply(msg):
    user_id = msg['FromUserName']
    content = msg['Content']
    print("receive text")
    return reply_to_user(ChatBot().reply_to_text(user_id, content), user_id)

#########################################################
@itchatmp.msg_register(itchatmp.content.VOICE)
def voice_reply(msg):
    user_id = msg['FromUserName']
    content = msg['Recognition']
    chatbot = ChatBot()
    print("receive voice")
    if not content or content.strip() == '': return reply_to_user(chatbot.reply_to_unknown(user_id))
    return reply_to_user(chatbot.reply_to_text(user_id, content), user_id)

#########################################################
@itchatmp.msg_register(itchatmp.content.EVENT)
def subscribe_reply(msg):
    user_id = msg['FromUserName']
    if msg['Event'] == 'subscribe' :
        print("receive event: subscribe")
        return reply_to_user(ChatBot().reply_to_subscribe(user_id), user_id)
    elif msg['Event'] == 'SCAN' :
        print("receive event: SCAN")
        return reply_to_user(ChatBot().reply_to_order_pay(user_id, msg['EventKey']), user_id)
    # elif msg['Event'] == 'CLICK' :
    #     print("receive event: CLICK")
    #     role_id = msg['EventKey']
    #     USER.set_role(user_id, role_id)
    #     return USER.role_modified_reply(role_id)
    return ''

#########################################################
# @itchatmp.msg_register(itchatmp.content.IMAGE)
# def image_reply(msg):
#     user_id = msg['FromUserName']
#     media_id = msg['MediaId']
#     image_url = msg['PicUrl']
#     picture_id = get_picture_id(media_id)
#     return reply_to_user(ChatBot().reply_to_media(user_id, picture_id, image_url, media_id), user_id)

#########################################################
# register_menu()
itchatmp.run(port=config.HTTP_PORT)


from functools import reduce
import math
import random

def fact(n):
    acc = 1
    for i in range(1, n + 1):
        acc *= i
    return acc

def wilson(p):
    return (fact(p-1) + 1) % p == 0

def eratosphen(n):
    a = []
    for i in range(n + 1):
        a.append(i)
    a[1] = 0
    i = 2
    while i <= n:
        if a[i] != 0:
            j = i + i
            while j <= n:
                a[j] = 0
                j = j + i
        i += 1
    a = set(a)
    a.remove(0)
    a = list(a)
    return a

def factor(n):
    l = eratosphen(n)
    k = n
    pr = []
    while l.count(k) == 0:
        for x in l:
            if k % x == 0:
                pr.append(x)
                k = k/x
                break
    pr.append(int(k))
    return pr

def legendre(a, p):
    if p < 2:
        raise ValueError('p must not be < 2')
    if (a == 0) or (a == 1):
        return a
    if a % 2 == 0:
        r = legendre(a / 2, p)
        if int(p * p - 1) & 8 != 0:
            r *= -1
    else:
        r = legendre(p % a, a)
        if int((a - 1) * (p - 1)) & 4 != 0:
            r *= -1
    return r

def fermat(n):
    a = factor(n-1)
    test = [pow(ai, n-1) % n == 1 % n for ai in a]
    return reduce(lambda x, y: x & y, test)

def carmichael(p):
    if fermat(p):
        pr = factor(p)
        for x in pr:
            if pr.count(x) > 1:
                print(p, ' is Prime number')
                return ''
        if len(pr) <= 1:
            print(p, ' is Prime number')
        else:
            print(p, ' is Carmichael number')
    else:
        print(p, ' is Composite number')

def solovay_strassen(n, k):
    if n % 2 == 0:
        print(n, ' is Composite number')
        return ''
    for i in range(1, k+1):
        random.seed()
        a = random.randint(2, n-1)
        if math.gcd(a, n) > 1:
            print(n, ' is Composite number')
            return ''
        if ((a ** ((n-1)//2))) % n != legendre(a, n) % n:
            print(n, ' is Composite number')
            return ''
    print(n, ' is likely a Prime number')
    return ''

def miller_rabin(n, k):
    if n == 3:
        print(n, ' is Prime number')
    if n % 2 == 0:
        print(n, ' is Composite number')
        return ''
    s = 0
    t = n-1
    while t % 2 != 0:
        s += 1
        t = t//2
    i = 0
    f = 0
    while i < k:
        random.seed()
        a = random.randint(2, n-1)
        x = (a**t) % n
        if x == 1 or x == n-1:
            i += 1
            continue
        for j in range(0, s-1):
            x = (x**2) % n
            if x == 1:
                print(n, ' is Composite number')
            if x == n-1:
                i += 1
                break
        f = 1
    if f != 1:
        print(n, ' is likely a Prime number')
    else:
        print(n, ' is Composite number')

c = [0] * 10000

def coef(n):
    c[0] = 1
    for i in range(n):
        c[1 + i] = 1
        for j in range(i, 0, -1):
            c[j] = c[j - 1] - c[j]
        c[0] = -c[0]

def aks(n):
    coef(n)
    c[0] = c[0] + 1
    c[n] = c[n] - 1

    i = n
    while (i > -1 and c[i] % n == 0):
        i = i - 1

    return True if i < 0 else False

def main():
    print(wilson(561))
    print(fermat(561))
    carmichael(41041)
    solovay_strassen(41047, 50)
    miller_rabin(41047, 50)
    print(aks(561))

if __name__ == '__main__':
    main()


from random import randint

import requests

import common
import discord
from discord.ext import commands

class Reddit(commands.Cog):
    """ Reddit Fetchers"""

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

    @commands.command(name='dankmeme', aliases=['dankmay', 'dankmaymay'])
    @commands.cooldown(2, 60 * 5)
    async def dankmeme(self, ctx):
        """Get a succulent dank may-may"""
        await ctx.send(get_reddit("dankmemes"))

    @commands.command(name='bertstrip', aliases=['badchildhood'])
    @commands.cooldown(2, 60 * 5)
    async def bertstrip(self, ctx):
        """Ruin your childhood"""
        await ctx.send(get_reddit("bertstrips"))

def get_reddit(subreddit):
    """
    Function that fetches dank memes.

    :param subreddit: Subreddit to use for the reddit fetch
    :return: a string to send the client
    """
    number_to_fetch = str(100)
    url = 'https://www.reddit.com/r/{}.json?limit={}'.format(
        subreddit,
        number_to_fetch)
    headers = {
        'User-Agent': 'Brochat-Bot {}.{}'.format(common.VERSION_YEAR,
                                                 common.VERSION_MONTH)
    }
    response = requests.get(url, headers=headers)
    response_json = response.json()

    if 'data' in response_json:
        for entry in response_json['data']['children']:
            if entry['data']['stickied'] is True \
                    or (entry['data']['url'][-4:] != '.png' and
                        entry['data']['url'][-4:] != '.jpg'):
                response_json['data']['children'].remove(entry)
        print(str(len(response_json['data']['children'])))
        seed = randint(0, len(response_json['data']['children']) - 1)
        link = response_json['data']['children'][seed]['data']['url']

        return '{}'.format(link)
    else:
        print('Error, response code: {}'.format(response.status_code))
        return "Looks like an adversary developer pwned " \
               "us...\nhttps://cdn.meme.am/cache/instances/" \
               "folder861/20989861.jpg"

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


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Fri May  1 15:38:05 2020

@author: rfablet
"""

import numpy as np
import torch
from torch import nn
import torch.nn.functional as F
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")

class CorrelateNoise(torch.nn.Module):
    def __init__(self, shape_data, dim_cn):
        super(CorrelateNoise, self).__init__()
        self.conv1 = torch.nn.Conv2d(shape_data, dim_cn, (3, 3), padding=1, bias=False)
        self.conv2 = torch.nn.Conv2d(dim_cn, 2 * dim_cn, (3, 3), padding=1, bias=False)
        self.conv3 = torch.nn.Conv2d(2 * dim_cn, shape_data, (3, 3), padding=1, bias=False)

    def forward(self, w):
        w = self.conv1(F.relu(w)).to(device)
        w = self.conv2(F.relu(w)).to(device)
        w = self.conv3(w).to(device)
        return w

class RegularizeVariance(torch.nn.Module):
    def __init__(self, shape_data, dim_rv):
        super(RegularizeVariance, self).__init__()
        self.conv1 = torch.nn.Conv2d(shape_data, dim_rv, (3, 3), padding=1, bias=False)
        self.conv2 = torch.nn.Conv2d(dim_rv, 2 * dim_rv, (3, 3), padding=1, bias=False)
        self.conv3 = torch.nn.Conv2d(2 * dim_rv, shape_data, (3, 3), padding=1, bias=False)

    def forward(self, v):
        v = self.conv1(F.relu(v)).to(device)
        v = self.conv2(F.relu(v)).to(device)
        v = self.conv3(v).to(device)
        return v

class ConvLSTM2d(torch.nn.Module):
    def __init__(self, input_size, hidden_size, kernel_size = 3, stochastic=False):
        super(ConvLSTM2d, self).__init__()
        self.input_size = input_size
        self.hidden_size = hidden_size
        self.kernel_size = kernel_size
        self.padding = int((kernel_size - 1) / 2)
        self.Gates = torch.nn.Conv2d(input_size + hidden_size, 4 * hidden_size, kernel_size = self.kernel_size, stride = 1, padding = self.padding)
        self.stochastic = stochastic
        #self.correlate_noise = CorrelateNoise(input_size, 10)
        #self.regularize_variance = RegularizeVariance(input_size, 10)

    def forward(self, input_, prev_state):

        # get batch and spatial sizes
        batch_size = input_.shape[0]
        spatial_size = input_.shape[2:]
        """
        if self.stochastic == True:
            z = torch.randn(input_.shape).to(device)
            z = self.correlate_noise(z)
            z = (z-torch.mean(z))/torch.std(z)
            #z = torch.mul(self.regularize_variance(z),self.correlate_noise(z))
        """
        # generate empty prev_state, if None is provided
        if prev_state is None:
            state_size = [batch_size, self.hidden_size] + list(spatial_size)
            prev_state = (
                torch.autograd.Variable(torch.zeros(state_size)).to(device),
                torch.autograd.Variable(torch.zeros(state_size)).to(device)
            )

        # prev_state has two components
        prev_hidden, prev_cell = prev_state

        # data size is [batch, channel, height, width]
        stacked_inputs = torch.cat((input_, prev_hidden), 1)
        """
        if self.stochastic == False:
            stacked_inputs = torch.cat((input_, prev_hidden), 1)
        else:
            stacked_inputs = torch.cat((torch.add(input_,z), prev_hidden), 1)
        """

        gates = self.Gates(stacked_inputs)

        # chunk across channel dimension: split it to 4 samples at dimension 1
        in_gate, remember_gate, out_gate, cell_gate = gates.chunk(4, 1)

        # apply sigmoid non linearity
        in_gate = torch.sigmoid(in_gate)
        remember_gate = torch.sigmoid(remember_gate)
        out_gate = torch.sigmoid(out_gate)

        # apply tanh non linearity
        cell_gate = torch.tanh(cell_gate)

        # compute current cell and hidden state
        cell = (remember_gate * prev_cell) + (in_gate * cell_gate)
        hidden = out_gate * torch.tanh(cell)

        return hidden, cell

class ConvLSTM1d(torch.nn.Module):
    def __init__(self, input_size, hidden_size, kernel_size = 3):
        super(ConvLSTM1d, self).__init__()
        self.input_size = input_size
        self.hidden_size = hidden_size
        self.kernel_size = kernel_size
        self.padding = int((kernel_size - 1) / 2)
        self.Gates = torch.nn.Conv1d(input_size + hidden_size, 4 * hidden_size, kernel_size = self.kernel_size, stride = 1, padding = self.padding)

    def forward(self, input_, prev_state):

        # get batch and spatial sizes
        batch_size = input_.shape[0]
        spatial_size = input_.shape[2:]

        # generate empty prev_state, if None is provided
        if prev_state is None:
            state_size = [batch_size, self.hidden_size] + list(spatial_size)
            prev_state = (
                torch.autograd.Variable(torch.zeros(state_size)).to(device),
                torch.autograd.Variable(torch.zeros(state_size)).to(device)
            )

        # prev_state has two components
        prev_hidden, prev_cell = prev_state

        # data size is [batch, channel, height, width]
        stacked_inputs = torch.cat((input_, prev_hidden), 1)
        gates = self.Gates(stacked_inputs)

        # chunk across channel dimension: split it to 4 samples at dimension 1
        in_gate, remember_gate, out_gate, cell_gate = gates.chunk(4, 1)

        # apply sigmoid non linearity
        in_gate = torch.sigmoid(in_gate)
        remember_gate = torch.sigmoid(remember_gate)
        out_gate = torch.sigmoid(out_gate)

        # apply tanh non linearity
        cell_gate = torch.tanh(cell_gate)

        # compute current cell and hidden state
        cell = (remember_gate * prev_cell) + (in_gate * cell_gate)
        hidden = out_gate * torch.tanh(cell)

        return hidden, cell

def compute_WeightedLoss(x2,w):
    #  fix normalizing factor ( Sum w = 1 != w~ bool index)
    if len(list(w.size()))>0:
        x2_msk = (x2 * w[None, :, None, None])[:, w>0, ...]
    else:
        x2_msk = x2[:, w==1, ...]
    x2_num = ~x2_msk.isnan() & ~x2_msk.isinf()
    if x2_num.sum() == 0:
        return torch.scalar_tensor(0., device=x2_num.device)
    # loss2 = x2_msk[x2_num].sum()
    loss2 = F.mse_loss(x2_msk[x2_num], torch.zeros_like(x2_msk[x2_num]))
    return loss2

def compute_spatio_temp_weighted_loss(x2, w):
    x2_w = (x2 * w[None, ...])
    non_zeros = (torch.ones_like(x2) * w[None, ...]) == 0.
    x2_num = ~x2_w.isnan() & ~x2_w.isinf() & ~non_zeros
    if x2_num.sum() == 0:
        return torch.scalar_tensor(0., device=x2_num.device)
    loss = F.mse_loss(x2_w[x2_num], torch.zeros_like(x2_w[x2_num]))
    return loss

# Modules for the definition of the norms for
# the observation and prior model
class Model_WeightedL2Norm(torch.nn.Module):
    def __init__(self):
        super(Model_WeightedL2Norm, self).__init__()

    def forward(self,x,w,eps=0.):
        loss_ = torch.nansum( x**2 , dim = 3)
        loss_ = torch.nansum( loss_ , dim = 2)
        loss_ = torch.nansum( loss_ , dim = 0)
        loss_ = torch.nansum( loss_ * w )
        loss_ = loss_ / (torch.sum(~torch.isnan(x)) / x.shape[1] )

        return loss_

class Model_WeightedL1Norm(torch.nn.Module):
    def __init__(self):
        super(Model_WeightedL1Norm, self).__init__()

    def forward(self,x,w,eps):

        loss_ = torch.nansum( torch.sqrt( eps**2 + x**2 ) , dim = 3)
        loss_ = torch.nansum( loss_ , dim = 2)
        loss_ = torch.nansum( loss_ , dim = 0)
        loss_ = torch.nansum( loss_ * w )
        loss_ = loss_ / (torch.sum(~torch.isnan(x)) / x.shape[1] )

        return loss_

class Model_WeightedLorenzNorm(torch.nn.Module):
    def __init__(self):
        super(Model_WeightedLorenzNorm, self).__init__()

    def forward(self,x,w,eps):

        loss_ = torch.nansum( torch.log( 1. + eps**2 * x**2 ) , dim = 3)
        loss_ = torch.nansum( loss_ , dim = 2)
        loss_ = torch.nansum( loss_ , dim = 0)
        loss_ = torch.nansum( loss_ * w )
        loss_ = loss_ / (torch.sum(~torch.isnan(x)) / x.shape[1] )

        return loss_

class Model_WeightedGMcLNorm(torch.nn.Module):
    def __init__(self):
        super(Model_WeightedL1Norm, self).__init__()

    def forward(self,x,w,eps):

        loss_ = torch.nansum( 1.0 - torch.exp( - eps**2 * x**2 ) , dim = 3)
        loss_ = torch.nansum( loss_ , dim = 2)
        loss_ = torch.nansum( loss_ , dim = 0)
        loss_ = torch.nansum( loss_ * w )
        loss_ = loss_ / (torch.sum(~torch.isnan(x)) / x.shape[1] )

        return loss_

def compute_WeightedL2Norm1D(x2,w):
    loss_ = torch.nansum(x2**2 , dim = 2)
    loss_ = torch.nansum( loss_ , dim = 0)
    loss_ = torch.nansum( loss_ * w )
    loss_ = loss_ / (torch.sum(~torch.isnan(x2)) / x2.shape[1] )

    return loss_

# Gradient-based minimization using a LSTM using a (sub)gradient as inputs
class model_GradUpdateLSTM(torch.nn.Module):
    def __init__(self,ShapeData,periodicBnd=False,DimLSTM=0,rateDropout=0.,stochastic=False):
        super(model_GradUpdateLSTM, self).__init__()

        with torch.no_grad():
            self.shape     = ShapeData
            if DimLSTM == 0 :
                self.dim_state  = 5*self.shape[0]
            else :
                self.dim_state  = DimLSTM
            self.PeriodicBnd = periodicBnd
            if( (self.PeriodicBnd == True) & (len(self.shape) == 2) ):
                print('No periodic boundary available for FxTime (eg, L63) tensors. Forced to False')
                self.PeriodicBnd = False

        self.convLayer     = self._make_ConvGrad()
        K = torch.Tensor([0.1]).view(1,1,1,1)
        self.convLayer.weight = torch.nn.Parameter(K)

        self.dropout = torch.nn.Dropout(rateDropout)
        self.stochastic=stochastic

        if len(self.shape) == 2: ## 1D Data
            self.lstm = ConvLSTM1d(self.shape[0],self.dim_state,3)
        elif len(self.shape) == 3: ## 2D Data
            self.lstm = ConvLSTM2d(self.shape[0],self.dim_state,3,stochastic=self.stochastic)

    def _make_ConvGrad(self):
        layers = []

        if len(self.shape) == 2: ## 1D Data
            layers.append(torch.nn.Conv1d(self.dim_state, self.shape[0], 1, padding=0,bias=False))
        elif len(self.shape) == 3: ## 2D Data
            layers.append(torch.nn.Conv2d(self.dim_state, self.shape[0], (1,1), padding=0,bias=False))

        return torch.nn.Sequential(*layers)
    def _make_LSTMGrad(self):
        layers = []

        if len(self.shape) == 2: ## 1D Data
            layers.append(ConvLSTM1d(self.shape[0],self.dim_state,3))
        elif len(self.shape) == 3: ## 2D Data
            layers.append(ConvLSTM2d(self.shape[0],self.dim_state,3,stochastic=self.stochastic))

        return torch.nn.Sequential(*layers)

    def forward(self,hidden,cell,grad,gradnorm=1.0):
        # compute gradient
        grad  = grad / gradnorm
        grad  = self.dropout( grad )

        if self.PeriodicBnd == True :
            dB     = 7
            #
            grad_  = torch.cat((grad[:,:,grad.size(2)-dB:,:],grad,grad[:,:,0:dB,:]),dim=2)
            if hidden is None:
                hidden_,cell_ = self.lstm(grad_,None)
            else:
                hidden_  = torch.cat((hidden[:,:,grad.size(2)-dB:,:],hidden,hidden[:,:,0:dB,:]),dim=2)
                cell_    = torch.cat((cell[:,:,grad.size(2)-dB:,:],cell,cell[:,:,0:dB,:]),dim=2)
                hidden_,cell_ = self.lstm(grad_,[hidden_,cell_])

            hidden = hidden_[:,:,dB:grad.size(2)+dB,:]
            cell   = cell_[:,:,dB:grad.size(2)+dB,:]
        else:
            if hidden is None:
                hidden,cell = self.lstm(grad,None)
            else:
                hidden,cell = self.lstm(grad,[hidden,cell])

        grad = self.dropout( hidden )
        grad = self.convLayer( grad )

        return grad,hidden,cell

# New module for the definition/computation of the variational cost
class Model_Var_Cost(nn.Module):
    def __init__(self ,m_NormObs, m_NormPhi, ShapeData,dim_obs=1,dim_obs_channel=0,dim_state=0):
        super(Model_Var_Cost, self).__init__()
        self.dim_obs_channel = dim_obs_channel
        self.dim_obs        = dim_obs
        if dim_state > 0 :
            self.dim_state      = dim_state
        else:
            self.dim_state      = ShapeData[0]

        # parameters for variational cost
        self.alphaObs    = torch.nn.Parameter(torch.Tensor(1. * np.ones((self.dim_obs,1))))
        self.alphaReg    = torch.nn.Parameter(torch.Tensor([1.]))
        if self.dim_obs_channel[0] == 0 :
            self.WObs           = torch.nn.Parameter(torch.Tensor(np.ones((self.dim_obs,ShapeData[0]))))
            self.dim_obs_channel  = ShapeData[0] * np.ones((self.dim_obs,))
        else:
            self.WObs            = torch.nn.Parameter(torch.Tensor(np.ones((self.dim_obs,np.max(self.dim_obs_channel)))))
        self.WReg    = torch.nn.Parameter(torch.Tensor(np.ones(self.dim_state,)))
        self.epsObs = torch.nn.Parameter(0.1 * torch.Tensor(np.ones((self.dim_obs,))))
        self.epsReg = torch.nn.Parameter(torch.Tensor([0.1]))

        self.normObs   = m_NormObs
        self.normPrior = m_NormPhi

    def forward(self, dx, dy):

        loss = self.alphaReg**2 * self.normPrior(dx,self.WReg**2,self.epsReg)
        if self.dim_obs == 1 :
            loss +=  self.alphaObs[0]**2 * self.normObs(dy,self.WObs[0,:]**2,self.epsObs[0])
        else:
            for kk in range(0,self.dim_obs):
                loss +=  (
                    self.alphaObs[kk]**2
                    * self.normObs(
                        dy[kk],
                        self.WObs[kk,0:dy[kk].size(1)]**2,
                        self.epsObs[kk]
                    )
                )

        return loss

# 4DVarNN Solver class using automatic differentiation for the computation of gradient of the variational cost
# input modules: operator phi_r, gradient-based update model m_Grad
# modules for the definition of the norm of the observation and prior terms given as input parameters
# (default norm (None) refers to the L2 norm)
# updated inner modles to account for the variational model module
class Solver_Grad_4DVarNN(nn.Module):
    NORMS = {
            'l1': Model_WeightedL1Norm,
            'l2': Model_WeightedL2Norm,
    }
    def __init__(self ,phi_r,mod_H, m_Grad, m_NormObs, m_NormPhi, shape_data,n_iter_grad, stochastic=False):
        super(Solver_Grad_4DVarNN, self).__init__()
        self.phi_r         = phi_r

        if m_NormObs == None:
            m_NormObs =  Model_WeightedL2Norm()
        else:
            m_NormObs = self.NORMS[m_NormObs]()
        if m_NormPhi == None:
            m_NormPhi = Model_WeightedL2Norm()
        else:
            m_NormPhi = self.NORMS[m_NormPhi]()
        self.shape_data = shape_data
        self.model_H = mod_H
        self.model_Grad = m_Grad
        self.model_VarCost = Model_Var_Cost(m_NormObs, m_NormPhi, shape_data, mod_H.dim_obs, mod_H.dim_obs_channel)

        self.stochastic = stochastic

        with torch.no_grad():
            self.n_grad = int(n_iter_grad)

    def forward(self, x, yobs, mask, *internal_state):
        return self.solve(x, yobs, mask, *internal_state)

    def solve(self, x_0, obs, mask, hidden=None, cell=None, normgrad_=0.):
        x_k = torch.mul(x_0,1.)
        x_k_plus_1 = None
        for _ in range(self.n_grad):
            x_k_plus_1, hidden, cell, normgrad_ = self.solver_step(x_k, obs, mask,hidden, cell, normgrad_)

            x_k = torch.mul(x_k_plus_1,1.)

        return x_k_plus_1, hidden, cell, normgrad_

    def solver_step(self, x_k, obs, mask, hidden, cell,normgrad = 0.):
        _, var_cost_grad= self.var_cost(x_k, obs, mask)
        if normgrad == 0. :
            normgrad_= torch.sqrt( torch.mean( var_cost_grad**2 + 0.))
        else:
            normgrad_= normgrad
        grad, hidden, cell = self.model_Grad(hidden, cell, var_cost_grad, normgrad_)
        grad *= 1./ self.n_grad
        x_k_plus_1 = x_k - grad
        return x_k_plus_1, hidden, cell, normgrad_

    def var_cost(self , x, yobs, mask):
        dy = self.model_H(x,yobs,mask)
        dx = x - self.phi_r(x)

        loss = self.model_VarCost( dx , dy )

        var_cost_grad = torch.autograd.grad(loss, x, create_graph=True)[0]
        return loss, var_cost_grad


#Github link
url="https://github.com/manoja328/trojai-example"
# url="https://github.com/manoja328/trojai-rl-july"
#commit id

import subprocess
import re
process = subprocess.Popen(["git", "ls-remote", url], stdout=subprocess.PIPE)
stdout, stderr = process.communicate()
sha = re.split(r'\t+', stdout.decode('ascii'))[0]
print(sha)

template={}
template["nlayers_1"] =  {
    "description": "The hidden number of layers for training.",
    "type": "integer",
    "minimum": 1,
    "maximum": 3,
    "suggested_minimum": 2,
    "suggested_maximum": 3
}

meta_schema= {"$schema": "http://json-schema.org/draft-07/schema#",
              "title": "SRI Trinity Framework",
              "technique": "SRI value , action gradient based pipeline",
              "technique_description": "We are looking at action/value gradient, values and the final rewards",
              "technique_changes": "Some bug fixes on inferencing and loss calculation. Small changes to classifier design.",
              "technique_type": ["Trigger Inversion", "Jacobian Inspection"],
              "commit_id": sha,
              "repo_name": url,
              "required": [],
              "additionalProperties": False,
              "type": "object",
              'properties': template}

params = {}
for k in template:
    params[k] = 2

import json
with open('metaparameters_schema.json','w') as f:
    json.dump(meta_schema,f)

with open('metaparameters.json','w') as f:
    json.dump(params,f)

print("Metaparameters generated and saved.....")


from flask import Flask, request
from flask_mysqldb import MySQL
from flask import jsonify
from typing import Dict
from .customer_handlers import create_customer, update_customer, get_customer_details, delete_customer

app = Flask(__name__)
if __name__ == "__main__":
	app.run()

app.config['MYSQL_HOST'] = 'localhost'
app.config['MYSQL_USER'] = 'root'
app.config['MYSQL_PASSWORD'] = '123' #replace with your root password
app.config['MYSQL_DB'] = 'carRental' #database should be created first using SQL file 'car_rental.sql'

mysql = MySQL(app)

@app.route('/customer', methods=["POST", "PUT"])
def post_or_update_customer():
	input_data = request.json
	if request.method == 'POST':
		return create_customer(input_data, mysql)

	elif request.method == "PUT":
		return update_customer(input_data, mysql)

@app.route('/customer/<int:id>', methods=["GET", "DELETE"])
def get_or_delete_customer(id):
	if request.method == 'GET':
		return get_customer_details(id,mysql)

	elif request.method == "DELETE":
		return delete_customer(id, mysql)


from __future__ import print_function
import math
import sys

import numpy as np
from scipy.sparse import csc_matrix
from pyspark.sql import SparkSession

# cosine similarity of two csc represented array
def cos_sim(a, b):
    return float(a.multiply(b).sum()) / (np.linalg.norm(a.toarray()) * np.linalg.norm(b.toarray()))

# def cos_sim(a, b):
#   return float(sum(a * b)) / (np.linalg.norm(a) * np.linalg.norm(b))

def parseVector(line):
    return np.array([float(x) for x in line.split(' ')])

# usage: closestPoint(p, kPoints)
def closestPoint(p, centers):
    bestIndex = 0
    closest = float("+inf")
    for i in range(len(centers)):
        tempDist = cos_sim(p, centers[i])
        # tempDist = np.sum((p - centers[i]) ** 2)
        if tempDist < closest:
            closest = tempDist
            bestIndex = i
    return bestIndex

if __name__ == "__main__":

    spark = SparkSession \
        .builder \
        .appName("PythonKMeans") \
        .getOrCreate()

    ##
    with open("case_s/docword.enron_s.txt") as f:
        linesTmp = f.readlines()

    num_docs = int(linesTmp[0])
    num_vocab = int(linesTmp[1])
    num_words = int(linesTmp[2])

    maxIndex = 0
    df = {}
    for i in linesTmp[3:]:
        tmp = i.split(' ')  # tmp is (1, 118, 1)

        if int(tmp[1]) in df:
            df[int(tmp[1])] += 1
        else:
            df[int(tmp[1])] = 1

        if int(tmp[1]) > maxIndex:
            maxIndex = int(tmp[1])

    # formalize into idf
    idf = {}
    for i in df:
        idf[i] = np.log2((num_docs + 1.0) / float(df[i] + 1.0))

    f.close()
    linesTmp = None
    ##

    ## process doc data
    lines = spark.read.text(sys.argv[1]).rdd.map(lambda r: r[0])
    # lines = spark.read.text("case_s/docword.enron_s.txt").rdd.map(lambda r: r[0])
    data = lines.map(parseVector).filter(lambda x: len(x) > 1).cache()

    K = int(sys.argv[2])
    # K = 3
    convergeDist = float(sys.argv[3])
    # convergeDist = 0.00001
    outputFileName = sys.argv[4]
    # outputFileName = "out1.txt"

    ##
    data = data.map(lambda x: (x[0], (x[1], x[2]))).groupByKey().map(lambda x: (x[0], list(x[1]))).map(
        lambda x: (x[0], ([i[0] for i in x[1]], [i[1] * idf[i[0]] for i in x[1]]))).map(
        lambda x: (x[0], (x[1][0], [i / np.linalg.norm(x[1][1]) for i in x[1][1]]))).map(
        lambda x: (x[0], csc_matrix((np.array(x[1][1]), (np.array([0 for i in range(len(x[1][0]))]), np.array(x[1][0]))),
                                    shape=(1, maxIndex + 1)))).sortByKey().map(lambda x: x[1])

    # print (data.collect())

    kPoints = data.repartition(1).takeSample(False, K, 1)

    tempDist = 1.0

    while tempDist > convergeDist:

        closest = data.map(lambda p: (closestPoint(p, kPoints), (p, 1)))
        pointStats = closest.reduceByKey(lambda p1_c1, p2_c2: (p1_c1[0] + p2_c2[0], p1_c1[1] + p2_c2[1]))
        newPoints = pointStats.map(lambda st: (st[0], st[1][0] / st[1][1])).collect()
        tempDist = sum(np.linalg.norm((kPoints[iK] - p).toarray()) for (iK, p) in newPoints)
        print (tempDist)

        for (iK, p) in newPoints:
            kPoints[iK] = p

    print("Final centers: " + str(kPoints))

    spark.stop()

    with open(outputFileName, "w") as f:
        for i in kPoints:
            f.write('{}\n'.format(str(len(i.nonzero()[1]))))


# @Time : 2020/7/19 14:04
# @Author : YLXY
# @File : CallMain.py
# -*- coding: utf-8 -*-

import sys
from PyQt5.QtWidgets import QWidget, QMessageBox, QApplication, QMainWindow
from PyQt5.QtCore import QTimer, QDateTime, Qt
from PyQt5 import QtCore, QtGui
from main import Ui_Form
import re

class Calu(QWidget,Ui_Form):
    def __init__(self):
        super(Calu, self).__init__()
        self.setupUi(self)
        self.connecter()
        self.curNum = 1
        self.curAScore = 0
        self.curBScore = 0
        self.outputWritten('\t+---------------------------------------+')
        self.outputWritten('\t| 局数\t| 组名\t| 分数\t| 组名\t| 分数\t|')
        self.outputWritten('\t+---------------------------------------+')

        timer = QTimer(self)
        timer.timeout.connect(self.showtime)
        timer.start()

    def showtime(self):
        datetime = QDateTime.currentDateTime()
        text = datetime.toString()
        self.Timelabel.setText(text)

    def connecter(self):
        self.ResetButton.clicked.connect(self.reset)
        self.RecordButton.clicked.connect(self.record)

    def reset(self):
        self.AEdit.clear()
        self.BEdit.clear()
        self.AScoreEdit.clear()
        self.BScoreEdit.clear()
        self.textBrowser.clear()
        self.curNum = 1
        self.curAScore = 0
        self.curBScore = 0
        self.ANumber.display(self.curAScore)
        self.BNumber.display(self.curBScore)

    def record(self):
        A_score = self.AScoreEdit.text()
        B_score = self.BScoreEdit.text()
        A_name = self.AEdit.text()
        B_name = self.BEdit.text()
        if A_name == '' or B_name == '':
            reply = QMessageBox.warning(self, "警告", "组名为空，请输入组名")
            return
        elif A_score == '' or B_score == '':
            reply = QMessageBox.warning(self, '警告',"填写内容为空，请输入当前分数！")
            return
        elif re.match(r'^-?[0-9]{1,3}$', A_score) == None or re.match(r'^-?[0-9]{1,3}$', B_score) == None:
            reply = QMessageBox.warning(self, '警告',"填写内容非法，请重新输入！")
            return
        self.outputWritten('\t|   {}\t|  A组\t|  {}\t|  B组\t|  {}\t|'.format(self.curNum, A_score, B_score))
        self.outputWritten('\t+---------------------------------------+')
        self.curNum += 1
        self.curAScore += int(A_score)
        self.curBScore += int(B_score)
        self.AScoreEdit.clear()
        self.BScoreEdit.clear()
        self.ANumber.display(self.curAScore)
        self.BNumber.display(self.curBScore)
        if self.curAScore >= 1000 :
            reply = QMessageBox.information(self, "恭喜", "恭喜{}组获胜！！！".format(self.AEdit.text()))
        elif self.curBScore >= 1000:
            reply = QMessageBox.information(self, "恭喜", "恭喜{}组获胜！！！".format(self.BEdit.text()))

    def keyPressEvent(self, key):
        if key.key() == Qt.Key_Enter or key.key() == Qt.Key_Return:
            self.record()

    def outputWritten(self, text):
        cursor = self.textBrowser.textCursor()
        # cursor.movePosition(QtGui.QTextCursor.End)
        cursor.insertText(text + '\n')
        # self.textBrowser.setTextCursor(cursor)
        # self.textBrowser.ensureCursorVisible()

if __name__  == "__main__":
    app = QApplication(sys.argv)
    calu = Calu()
    calu.show()
    sys.exit(app.exec())


from helpers import time_it, load_text_file
from pathlib import Path
from rich import print
import os
import click

def signal_position(data, n_distinct_chars):
    """
    Return position after the fisrt set of
    n_distinct_chars
    """
    signal = False
    marker = [0,n_distinct_chars]
    while signal is False and marker[1] < len(data):

        signal_data = data[marker[0]:marker[1]]

        if len(set(signal_data)) < n_distinct_chars:
            marker = list(map(sum, zip(marker, [1, 1])))
        else:
            signal = True
            print(f"The marker is in position {marker[1]}")
            print(f"{signal_data}\n")

@click.command()
@click.option("--file-path", type=Path, default = "data")
def main(file_path):
    # load data
    path_file = os.path.join(file_path, "input_p6.txt")
    input_data = load_text_file(path_file)[0]

    print("\n[b] Solution [/] for [u]problem one[/]\n")
    signal_position(input_data, 4)

    print("[b] Solution [/] for [u]problem two[/]\n")
    signal_position(input_data, 14)

if __name__ == "__main__":
    main()


from PIL import Image
import tkinter as tk
from tkinter import filedialog as fd

class BnT:

    def __init__(self, root):

        root.title('BnT converter')
        root.resizable(False, False)

        mnf = tk.Frame(root, borderwidth=10)
        mnf.grid(column=0, row=0, sticky=('N, W, E, S'))
        mnf.columnconfigure(0, weight=1, minsize=75)
        mnf.columnconfigure(1, weight=4, minsize=225)
        mnf.rowconfigure(0, weight=1)

        #setting global variables
        self.path = tk.StringVar()
        self.status = tk.StringVar()
        self.path_short = tk.StringVar()

        #Info Labels
        tk.Label(mnf, text ='   ').grid(column=0, row=0)
        tk.Label(mnf, text='Black and Transparency converter:', font=('Default', 15)).grid(column=0, row=1, columnspan=2)
        tk.Label(mnf, text =
            'This application takes an image, converts it to grayscale \n'
            'and then converts it to an image made only of black pixels \n'
            ' of varying opacity.', relief = 'sunken').grid(column = 0, row = 2, columnspan = 2, pady = 10)

        #Pick options for grayscaling
        radbutton = tk.Frame(mnf, borderwidth=10)
        radbutton.grid(column=0, row=3, columnspan=2)
        self.optionpicked = tk.IntVar()
        options = [('Grayscale as seen\n by the human eye', 0),
                   ('Grayscale without \n correcting for the eye', 1)]
        tk.Label(radbutton, text='Pick how the conversion is handled').pack()
        for optname, val in options:
            tk.Radiobutton(radbutton, text=optname, variable=self.optionpicked, value=val).pack(side=tk.LEFT)

        #Open File
        tk.Button(mnf, text='Open a File',
            command=self.select_file).grid(column=0, row=4, pady = 10, sticky='E')

        tk.Label(mnf, textvariable = self.path_short, wraplength=260).grid(column=1, row=4, pady = 10, sticky='W')

        #Save File
        tk.Button(mnf, text='Save', command=self.save).grid(column = 0, row = 5, pady = 10, sticky='E')
        tk.Label(mnf, textvariable = self.status).grid(column=1, row=5, pady = 10, sticky='W')

    def select_file(self):
        filetypes = (
            ('png files', '*.png'),
            ('jpg files', '*.jpg'),
            ('jpeg files', '*.jpeg'),
            ('gif files', '*.gif'),
            ('All files', '*.*')
        )
        filepath = fd.askopenfilename(
            title='Open a file',
            filetypes=filetypes)
        self.path.set(filepath)
        self.path_short.set('...' + str(self.path.get())[-35:])
        self.status.set('')

    def save(self):

        img_path = self.path.get() #image preprocessing
        print(img_path)
        img = Image.open(img_path)
        img = img.convert("RGB") #flattens the transparency
        img = img.convert('RGBA') #adds it back in

        if self.optionpicked.get() == 0: #depends on the radiobutton
            out = self.greyscale(img)
        elif self.optionpicked.get() == 1:
            out = self.nohue(img)
        out = out.convert('RGBA')

        file = fd.asksaveasfile(mode='wb', defaultextension=".png", filetypes=(("PNG file", "*.png"),("All Files", "*.*") )) #image saving
        if file:
            out.save(file)
            self.status.set("Done!")

    def greyscale(self, img):
        datas = img.getdata()
        newData = []
        for item in datas:
            newData.append((0, 0, 0, 255-int((item[0] * 299/1000 + item[1] * 587/1000 + item[2] * 114/1000)))) #pixel conversion
        img.putdata(newData)
        return img
    def nohue(self, img):
        datas = img.getdata()
        newData = []
        for item in datas:
            newData.append((0,0,0,255 - max(item[0], item[1], item[2]))) #pixel conversion, removes the color channels and creates a key
        img.putdata(newData)
        return img

root = tk.Tk()
BnT(root)
root.mainloop()