from bitBoard import app, jsonify_errors, add_null_entities, \
		THREADS_PER_PAGE, POSTS_PER_PAGE, \
		PM_RECIPIENT_LIMIT, \
		parse_ugly_date_and_time, format_ugly_date_and_time, \
		add_extra_stylesheet
from bitBoard.views.base import RedirectForm, get_redirect_target
from bitBoard.models import *
from bitBoard.parser import parse_text
from bitBoard.wtforms_extended_selectfield import SelectField
from flask import Flask, request, session, g, redirect, url_for, \
		abort, render_template, flash, jsonify, escape
from flask.ext.wtf import Form, TextField, PasswordField, HiddenField, \
		EqualTo, Required, TextAreaField, RadioField, FileField
from sqlalchemy.orm import joinedload, subqueryload, defer
from sqlalchemy.sql.expression import true

def get_viewable_forums():
	# do permission checks here
	return db.session.query(Forum).\
			join(ForumPermissions).\
			filter(ForumPermissions.group_id==g.effective_group_id).\
			filter(ForumPermissions.can_view==True).\
			order_by(Forum.position).\
			options(joinedload('last_thread')).\
			all()
def get_viewable_categories():
	return db.session.query(Category).\
			order_by(Category.position).\
			options(joinedload(Category.forums)).\
			all()

def get_viewable_forum_ids():
	return map(lambda x: x[0],
			db.session.query(ForumPermissions.forum_id).\
			filter_by(group_id=g.effective_group_id, can_view=True).\
			all())

def get_layout_extra(post):
	user = post.creator

	data = {}

	if user.post_style == 2:
		if user.style_url:
			data['style_url'] = user.style_url

	return data

@app.route('/forum')
def forum_index():
	c_query = db.session.query(Category).order_by('position')

	if g.user:
		on_clause = db.and_(
			Thread.id == ThreadRead.thread_id,
			ThreadRead.user_id == g.user.id)

		condition = db.case(
			whens=((ThreadRead.time == None, true()),),
			else_=Thread.last_updated_at > ThreadRead.time)

		subquery = db.session.query(db.func.count(Thread.id)).\
			outerjoin(ThreadRead, on_clause).\
			correlate(Forum).\
			filter(Thread.forum_id == Forum.id, condition).\
			as_scalar()

		entities = (Forum, subquery)
	else:
		entities = (Forum,)

	f_query = db.Query(entities, session=db.session()).\
		order_by(Forum.position).\
		options(joinedload('last_thread'), joinedload('last_thread.last_poster'))

	categories = []
	forum_lists = {}
	for category in c_query:
		list = []
		forum_lists[category.id] = list
		categories.append((category, list))

	if g.user:
		forums = f_query
	else:
		forums = add_null_entities(f_query, 0)

	for forum, unread_count in forums:
		forum_lists[forum.category_id].append((forum, unread_count))

	return render_template('forum_index.html', categories=categories)
	#return redirect(url_for('updated_threads'), code=303)

@app.route('/forum/latest_posts')
def latest_posts():
	viewable = get_viewable_forum_ids()

	posts_and_threads = db.session.query(Post, Thread).\
			filter(Thread.id==Post.thread_id).\
			filter(Thread.forum_id.in_(viewable)).\
			order_by(db.desc(Post.created_at)).\
			options(joinedload('creator')).limit(50).all()

	posts = map(lambda x: x[0], posts_and_threads)

	return render_template('post_list.html', mode='latest_posts', posts=posts)

def fetch_threads_and_threadread_query():
	# This bit of code is horrible. Really. Horrible.
	entities = ((Thread, ThreadRead) if g.user else Thread)

	base_query = db.Query(entities, session=db.session()).\
			options(
			joinedload('creator'), joinedload('last_poster'),
			joinedload('last_post')
			).\
			order_by(db.desc(Thread.last_updated_at))

	if g.user:
		read_on_clause = db.and_(
			Thread.id == ThreadRead.thread_id,
			ThreadRead.user_id == g.user.id)
		base_query = base_query.outerjoin(ThreadRead, read_on_clause)

	return base_query

@app.route('/messages')
def private_messages():
	if not g.user:
		abort(403)

	threads = fetch_threads_and_threadread_query().\
			filter(Thread.type == Thread.PRIVATE).\
			filter(Thread.private_users.contains(g.user))

	# This is since we depend on the userpanel_base template
	g.edited_user = g.user

	return render_template('thread_list.html',
		mode='private_messages', user=g.user,
		threads=threads)

@app.route('/forum/updated_threads')
def updated_threads():
	viewable = get_viewable_forum_ids()

	threads = fetch_threads_and_threadread_query().\
			filter(Thread.forum_id.in_(viewable)).\
			limit(50)

	if not g.user:
		threads = add_null_entities(threads)

	return render_template('thread_list.html',
		mode='updated_threads',
		threads=threads)

@app.route('/forum/<slug>')
def view_forum(slug):
	forum = Forum.query.filter_by(slug=slug).first()
	if not forum:
		abort(404)
	if not forum.can_be_viewed_by(g.user):
		abort(403)

	base_query = fetch_threads_and_threadread_query().\
		filter(Thread.forum == forum)
	query = base_query.filter(Thread.is_stickied==False)
	pagenum = int(request.args.get('page', 1))

	pagination = query.paginate(pagenum, THREADS_PER_PAGE, error_out=False)

	stickies = base_query.filter(Thread.is_stickied==True).all()

	if not g.user:
		pagination.items = add_null_entities(pagination.items)
		stickies = add_null_entities(stickies)

	return render_template('thread_list.html',
		mode='forum', forum=forum, stickies=stickies,
		threads=pagination.items, pagination=pagination)

def post_page_num(post):
	query = db.session.query(db.func.count(Post.id)).\
		filter(Post.thread_id == post.thread_id, Post.id < post.id)

	count_before = query.scalar()
	page_num = (count_before / POSTS_PER_PAGE) + 1
	return page_num

def redirect_to_post(thread, post):
	if not post:
		return redirect_to_post(thread, thread.last_post)
	page_num = post_page_num(post)
	page_bit = ('?page=%d' % page_num) if page_num != 1 else ''

	url = u'%s%s#post%d' % (post.thread.url, page_bit, post.id)
	return redirect(url, code=303)

@app.route('/forum/<slug>/<int:thread_id>')
@app.route('/forum/<slug>/<int:thread_id>-<thread_slug>')
def view_thread(slug, thread_id, thread_slug=None):
	url_forum = Forum.query.filter_by(slug=slug).first()
	thread = Thread.query.get(thread_id)
	if not thread:
		abort(404)
	if not thread.can_be_viewed_by(g.user):
		abort(403)
	if not thread.is_basic_thread:
		abort(403)
	if url_forum != thread.forum or thread_slug != thread.slug:
		return redirect(thread.url, code=301)
	return _base_view_thread(thread)

@app.route('/messages/<int:thread_id>')
@app.route('/messages/<int:thread_id>-<thread_slug>')
def pm_view_thread(thread_id, thread_slug=None):
	thread = Thread.query.get(thread_id)
	if not thread:
		abort(404)
	if not thread.can_be_viewed_by(g.user):
		abort(403)
	if not thread.is_private:
		abort(403)
	if thread_slug != thread.slug:
		return redirect(thread.url, code=301)
	return _base_view_thread(thread)

def _base_view_thread(thread):
	# Find a specific post, if we need to
	if 'findPost' in request.args:
		post_id = int(request.args['findPost'])
		post = Post.query.get(post_id)
		if not post:
			abort(404)
		if post.thread_id != thread.id:
			abort(404)
		return redirect_to_post(thread, post)
	elif 'findPostAfter' in request.args:
		raw_timestamp = request.args['findPostAfter']
		timestamp = parse_ugly_date_and_time(raw_timestamp)

		if timestamp:
			post = Post.query.\
				filter(Post.thread == thread, Post.created_at > timestamp).\
				order_by(db.asc(Post.created_at)).\
				first()
		else:
			post = Post.query.\
				filter(Post.thread == thread).\
				order_by(db.asc(Post.created_at)).\
				first()

		return redirect_to_post(thread, post)
	elif g.user and 'findLastUnread' in request.args:
		read = ThreadRead.query.filter_by(user_id=g.user.id, thread_id=thread.id).first()
		url = u'{0}?findPostAfter={1}'.format( \
			thread.url, format_ugly_date_and_time(read.time))
		return redirect(url, code=303)

	if g.user:
		read = ThreadRead.query.filter_by(user_id=g.user.id, thread_id=thread.id).first()
		if not read:
			read = ThreadRead(user_id=g.user.id, thread_id=thread.id)
			db.session.add(read)
		read.time = datetime.datetime.now()
		db.session.commit()

		notification = Notification.query.\
			filter_by(
				recipient_id=g.user.id, thread_id=thread.id).\
			first()
		if notification:
			db.session.delete(notification)

	query = thread.posts.options(
			joinedload('creator'),
			joinedload('current_version'))

	pagenum = int(request.args.get('page', 1))
	pagination = query.paginate(pagenum, POSTS_PER_PAGE, error_out=False)

	# for custom layouts
	for post in pagination.items:
		user = post.creator
		if user.post_style == 2:
			add_extra_stylesheet(user.style_url)

	quick_reply = PostForm(formdata=None)
	return render_template('view_thread.html',
			forum=thread.forum, thread=thread,
			posts=pagination.items, pagination=pagination,
			qr_form=quick_reply)

class PostForm(Form):
	content = TextAreaField('Post Content', validators=[Required()])

class ThreadForm(PostForm):
	title = TextField('Title', validators=[Required()])
	subtitle = TextField('Subtitle')

class PrivateThreadForm(ThreadForm):
	recipients = TextAreaField('Recipients')

class MoveThreadForm(Form):
	destforum = SelectField('Destination Forum', coerce=int)

@app.route('/forum/<forum_slug>/post',
	endpoint='post_thread', methods=['GET', 'POST'])
@app.route('/messages/post', defaults={'is_private': True},
	endpoint='pm_post_thread', methods=['GET', 'POST'])
def post_thread(forum_slug=None, is_private=False):
	if is_private:
		# TODO: g.effective_group.can_send_messages?
		if not g.user:
			abort(403)
		forum = None
		url = url_for('pm_post_thread')
		form = PrivateThreadForm()
	else:
		forum = Forum.query.filter_by(slug=forum_slug).first()
		if not forum:
			abort(404)
		if not forum.can_be_posted_in_by(g.user):
			abort(403)
		url = forum.post_url
		form = ThreadForm()

	recipients = None
	recipient_errors = []
	# This is a bit of an ugly mess, but my brain isn't working right atm and
	# I can't think of a better method. TODO: refactor me?
	if is_private and form.recipients.data:
		recipients = [g.user]
		r_names = form.recipients.data.split('\n')

		for name in r_names:
			name = name.strip()
			if not name: continue
			u = User.query.filter(db.func.lower(User.name) == db.func.lower(name)).first()
			if u:
				if u in recipients: continue
				if u == g.user: continue
				recipients.append(u)
			else:
				recipient_errors.append(u"There doesn't seem to be a user named '%s'." % name)
				actually_valid = False

		if len(recipients) > PM_RECIPIENT_LIMIT:
			recipient_errors.append(u"You have added too many users to this private thread. The current limit is %d users, other than yourself." % (PM_RECIPIENT_LIMIT - 1))
			actually_valid = False
		elif len(recipients) <= 1:
			recipient_errors.append(u"You must enter at least one person other than yourself who will be part of this thread.")
			actually_valid = False

	if form.validate_on_submit() and not recipient_errors:
		thread = Thread(
				title=form.title.data,
				subtitle=form.subtitle.data,
				forum=forum,
				creator=g.user,
				type=(Thread.PRIVATE if is_private else Thread.BASIC_THREAD),
				post_count=1)
		thread.make_slug()
		db.session.add(thread)

		if is_private:
			thread.private_users = recipients
			post_number = -1
		else:
			post_number = g.user.post_count + 1

		post = Post(
				thread=thread,
				creator=g.user,
				created_at=datetime.datetime.now(),
				created_ip=request.remote_addr,
				version_count=1,
				number=post_number)
		db.session.add(post)

		if not is_private:
			g.user.post_count += 1
			g.user.thread_count += 1

			forum.post_count += 1
			forum.thread_count += 1

		thread.update_last_post(post)

		version = PostVersion(
			content=form.content.data,
			post=post,
			creator=g.user,
			created_at=datetime.datetime.now(),
			created_ip=request.remote_addr)
		db.session.add(version)
		post.current_version = version

		if is_private:
			for user in recipients:
				if user != g.user:
					notify = Notification(
						thread=thread, recipient=user,
						type=Notification.NEW_PRIVATE_THREAD)
					db.session.add(notify)

		db.session.commit()

		flash('Your thread has been posted successfully.')
		return redirect(thread.url, code=303)

	return render_template('post.html',
			is_thread=True,
			is_private=is_private,
			recipient_errors=recipient_errors,
			form=form,
			forum=forum,
			pm_recipient_limit=PM_RECIPIENT_LIMIT,
			url=url)

@app.route('/forum/<forum_slug>/<int:thread_id>-<thread_slug>/reply',
	endpoint='post_reply', methods=['GET', 'POST'],
	defaults={'type': Thread.BASIC_THREAD})
@app.route('/messages/<int:thread_id>-<thread_slug>/reply',
	endpoint='pm_post_reply', methods=['GET', 'POST'],
	defaults={'type': Thread.PRIVATE})
def post_reply(thread_id, thread_slug, type,
	forum_slug=None, dcategory_slug=None):

	if type == Thread.BASIC_THREAD:
		url_forum = Forum.query.filter_by(slug=forum_slug).first()

	thread = Thread.query.get(thread_id)
	if not thread:
		abort(404)
	if type != thread.type:
		abort(404)

	if not thread.can_be_replied_to_by(g.user):
		abort(403)

	if request.method == 'GET':
		url_valid = True
		if type == Thread.BASIC_THREAD and url_forum != thread.forum:
			url_valid = False
		elif thread_slug != thread.slug:
			url_valid = False
		if not url_valid:
			return redirect(thread.reply_url, code=301)

	ajax = ('ajax' in request.values)

	form = PostForm()

	if form.validate_on_submit():
		if type == Thread.PRIVATE:
			post_number = -1
		else:
			post_number = g.user.post_count + 1

		post = Post(
			thread=thread,
			creator=g.user,
			created_at=datetime.datetime.now(),
			created_ip=request.remote_addr,
			version_count=1,
			number=post_number)
		db.session.add(post)

		version = PostVersion(
			content=form.content.data,
			post=post,
			creator=g.user,
			created_at=datetime.datetime.now(),
			created_ip=request.remote_addr)
		db.session.add(version)
		post.current_version = version

		thread.post_count += 1
		if type != Thread.PRIVATE:
			g.user.post_count += 1
			if type == Thread.BASIC_THREAD:
				thread.forum.post_count += 1
		thread.update_last_post(post)

		# This is ugly. Deal with notifications.
		u_table = pm_thread_users if (type == Thread.PRIVATE) else thread_followers
		notify_join = db.and_(
			Notification.type == Notification.FOLLOWED_THREAD,
			u_table.c.user_id == Notification.recipient_id,
			u_table.c.thread_id == Notification.thread_id
			)

		notify_which = db.session.query(u_table.c.user_id, Notification.id).\
			filter(u_table.c.thread_id == thread.id).\
			filter(u_table.c.user_id != g.user.id).\
			outerjoin(Notification, notify_join)
		add_new = []
		update_existing = []

		for uid, nid in notify_which:
			if nid:
				update_existing.append(nid)
			else:
				add_new.append({
					'recipient_id': uid,
					'type': Notification.FOLLOWED_THREAD,
					'thread_id': thread.id
					})

		if update_existing:
			Notification.query.\
				filter(Notification.id.in_(update_existing)).\
				update({'count': Notification.count + 1}, synchronize_session=False)

		if add_new:
			db.session.execute(Notification.__table__.insert(), add_new)

		db.session.commit()

		if not ajax:
			flash('Your reply has been posted.')
			return redirect(post.url, code=303)
		else:
			return jsonify(
				was_posted=True,
				post_id=post.id,
				post_html=render_template('post_box.html',
					post=post,
					postNumber=thread.post_count),
				layout_extra=get_layout_extra(post)
				)

	if not ajax:
		return render_template('post.html',
				form=form,
				thread=thread,
				forum=thread.forum,
				url=thread.reply_url)
	else:
		return jsonify(was_posted=False, errors=jsonify_errors(form))

@app.route('/forum/<forum_slug>/<int:thread_id>-<thread_slug>/<int:post_id>/edit',
	endpoint='edit_post', methods=['GET', 'POST'],
	defaults={'type': Thread.BASIC_THREAD})
def edit_post(thread_id, thread_slug, post_id,
	type, forum_slug=None, dcategory_slug=None):

	if type == Thread.BASIC_THREAD:
		url_forum = Forum.query.filter_by(slug=forum_slug).first()

	url_thread = Thread.query.get(thread_id)
	post = Post.query.get(post_id)
	if not post:
		abort(404)

	thread = post.thread
	if thread.type != type:
		abort(404)
	if not post.can_be_edited_by(g.user):
		abort(403)
	if request.method == 'GET':
		if thread_id != thread.id or \
		   thread_slug != thread.slug or \
		   (type == Thread.BASIC_THREAD and url_forum != thread.forum):
			return redirect(post.edit_url, code=301)

	posts_before = Post.query.\
		filter(Post.thread == thread, Post.id < post.id).\
		count()

	edits_thread = (thread.is_basic_thread and (posts_before == 0))

	ajax = ('ajax' in request.values)

	cur_version = post.current_version
	form_cls = ThreadForm if edits_thread else PostForm
	form = form_cls(obj=post,
		content=cur_version.content,
		title=thread.title,
		subtitle=thread.subtitle)

	if 'getQuickEditAjaxForm' in request.args:
		html = render_template('inline_edit.html',
				post=post,
				is_thread=edits_thread,
				form=form,
				url=post.edit_url)
		return jsonify(form_html=html)

	if form.validate_on_submit():
		if cur_version.content != form.content.data:
			version = PostVersion(
				content=form.content.data,
				post=post,
				creator=g.user,
				created_at=datetime.datetime.now(),
				created_ip=request.remote_addr)
			db.session.add(version)

			post.version_count += 1
			post.current_version = version
		else:
			# Return the current version, as we're quick editing
			version = cur_version

		if edits_thread:
			thread.title = form.title.data
			thread.subtitle = form.subtitle.data
			thread.slug = slugify(thread.title)

		db.session.commit()

		if not ajax:
			flash('Your post has been updated.')
			return redirect(post.url, code=303)
		else:
			return jsonify(
				was_edited=True,
				post_html=escape(parse_text(version.content))
				)

	if not ajax:
		return render_template('post.html',
				form=form,
				is_thread=edits_thread,
				is_edit=True,
				thread=thread,
				forum=thread.forum,
				url=post.edit_url)
	else:
		return jsonify(was_edited=False, errors=jsonify_errors(form))

@app.route('/forum/<forum_slug>/<int:thread_id>-<thread_slug>/<int:post_id>/delete',
	endpoint='delete_post', methods=['GET', 'POST'],
	defaults={'type': Thread.BASIC_THREAD})
def delete_post(thread_id, thread_slug, post_id,
	type, forum_slug=None, dcategory_slug=None):

	if type == Thread.BASIC_THREAD:
		url_forum = Forum.query.filter_by(slug=forum_slug).first()

	url_thread = Thread.query.get(thread_id)
	post = Post.query.get(post_id)
	if not post:
		abort(404)

	thread = post.thread
	if thread.type != type:
		abort(404)
	if not post.can_be_deleted_by(g.user):
		abort(403)
	if request.method == 'GET':
		if thread_id != thread.id or \
		   thread_slug != thread.slug or \
		   (type == Thread.BASIC_THREAD and url_forum != thread.forum):
			return redirect(post.delete_url, code=301)

	ajax = ('ajax' in request.values)

	if request.method == 'POST':
		post.is_deleted = True
		db.session.commit()

		if not ajax:
			flash('Your post has been deleted.')
			return redirect(post.url, code=303)
		else:
			return jsonify(
				was_deleted=True,
				post_html=render_template('post_box.html', post=post)
				)
	else:
		return render_template('confirm_post_delete.html',
			post=post,
			thread=post.thread,
			forum=post.thread.forum,
			url=post.delete_url)

@app.route('/forum/<forum_slug>/<int:thread_id>-<thread_slug>/move',
	endpoint='move_thread', methods=['GET', 'POST'])
def thread_move_action(forum_slug, thread_id, thread_slug):
	url_forum = Forum.query.filter_by(slug=forum_slug).first()
	thread = Thread.query.get(thread_id)

	if not thread:
		abort(404)
	if not thread.is_basic_thread:
		abort(404)

	forum = thread.forum
	url = thread.move_url

	if not forum.can_be_moderated_by(g.user):
		abort(403)

	if request.method == 'GET' and (url_forum != thread.forum or thread_slug != thread.slug):
		return redirect(url, code=301)

	# wild copypasta
	c_query = db.session.query(Category).order_by('position')
	f_query = db.session.query(Forum).order_by('position')

	categories = []
	forum_lists = {}
	good_forums = []
	for category in c_query:
		list = []
		forum_lists[category.id] = list
		categories.append((category.name, list))

	for iter_forum in f_query:
		if iter_forum != forum and forum.can_be_viewed_by(g.user):
			forum_lists[iter_forum.category_id].append((iter_forum.id, iter_forum.name))
			good_forums.append(iter_forum.id)

	ajax = ('ajax' in request.values) # TODO use this eventually
	form = MoveThreadForm(destforum=thread.forum_id)
	form.destforum.choices = categories

	if request.method == 'POST':
		new_forum_id = form.destforum.data

		if new_forum_id not in good_forums:
			# TODO: use something else here?
			# this is not exactly a 404-worthy error...
			abort(404)

		old_forum = thread.forum
		old_forum.thread_count -= 1
		old_forum.post_count -= thread.post_count

		thread.forum_id = new_forum_id

		new_forum = Forum.query.filter_by(id=new_forum_id).first()
		new_forum.thread_count += 1
		new_forum.post_count += thread.post_count

		db.session.commit()

		old_forum.update_last_thread()
		new_forum.update_last_thread()

		db.session.commit()
		return redirect(thread.url, code=303)

	else:
		return render_template('move_thread.html',
			form=form,
			forum=forum, thread=thread,
			url=url)

@app.route('/forum/<forum_slug>/<int:thread_id>-<thread_slug>/lock',
	endpoint='lock_thread', defaults={'action': 'lock'}, methods=['GET', 'POST'])
@app.route('/forum/<forum_slug>/<int:thread_id>-<thread_slug>/sticky',
	endpoint='sticky_thread', defaults={'action': 'sticky'}, methods=['GET', 'POST'])
@app.route('/forum/<forum_slug>/<int:thread_id>-<thread_slug>/follow',
	endpoint='follow_thread', defaults={'action': 'follow'}, methods=['GET', 'POST'])
def thread_mod_action(forum_slug, thread_id, thread_slug, action):
	# This view is becoming spaghetti.
	url_forum = Forum.query.filter_by(slug=forum_slug).first()
	thread = Thread.query.get(thread_id)

	if not thread:
		abort(404)
	if not thread.is_basic_thread:
		abort(404)

	forum = thread.forum
	requires_moderator = True
	if action == 'sticky':
		url = thread.sticky_url
	elif action == 'lock':
		url = thread.lock_url
	elif action == 'follow':
		if not thread.can_be_followed:
			abort(404)
		url = thread.follow_url
		requires_moderator = False

	if requires_moderator:
		if not forum.can_be_moderated_by(g.user):
			abort(403)
	else:
		if not forum.can_be_viewed_by(g.user):
			abort(403)

	if request.method == 'GET' and (url_forum != thread.forum or thread_slug != thread.slug):
		return redirect(url, code=301)

	ajax = ('ajax' in request.values)
	form = RedirectForm()

	if action == 'sticky':
		old_value = thread.is_stickied
		attr = 'is_stickied'

		if old_value:
			cap_verb = 'Unstick'
			done_word = 'unstickied'
			link_title = 'Stick'
			message = 'Are you sure you want to make this thread a normal thread?'
		else:
			cap_verb = 'Stick'
			done_word = 'stickied'
			link_title = 'Unstick'
			message = 'Are you sure you want to make this thread a sticky?'
	elif action == 'lock':
		old_value = thread.is_locked
		attr = 'is_locked'

		if old_value:
			cap_verb = 'Unlock'
			done_word = 'unlocked'
			link_title = 'Lock'
			message = 'Are you sure you want to unlock this thread?'
		else:
			cap_verb = 'Lock'
			done_word = 'locked'
			link_title = 'Unlock'
			message = 'Are you sure you want to lock this thread?'
	elif action == 'follow':
		old_value = thread.is_followed_by(g.user)
		attr = None

		if old_value:
			cap_verb = 'Follow'
			link_title = 'Follow'
			message = 'Are you sure you want to follow this thread?'
		else:
			cap_verb = 'Unfollow'
			link_title = 'Unfollow'
			message = 'Are you sure you want to stop following this thread?'

	if request.method == 'POST':
		if action == 'follow':
			if old_value:
				thread.followers.remove(g.user)
				thread.follower_count -= 1
				msg = 'You are no longer following this thread.'
			else:
				thread.followers.append(g.user)
				thread.follower_count += 1
				msg = 'You are now following this thread. You will receive notifications about new posts.'
		else:
			setattr(thread, attr, not old_value)
			msg = 'The thread has been %s.' % done_word
		db.session.commit()

		if ajax:
			return jsonify(toast=msg, link_title=link_title)
		else:
			flash(msg)
			return form.redirect(url=thread.url)
	else:
		return render_template('confirm.html',
			form=form,
			crumbs_type='thread',
			forum=forum, thread=thread,
			final_crumb=('%s Thread' % cap_verb),
			message=message,
			url=url)


from graphviz import Digraph
from queue import Queue
from pprint import pprint
import itertools
# esse codigo eh uma implementacao do algoritmo do slide 5c do prof Mokarzel
fold = "questao_lista/"

class AfndNode:
    def __init__(self, left, right):
        self.left = left
        self.right = right
        self.idx = None

    def __str__(self):
        return "".join(self.left) + "->" + "".join(self.right)

class AfdNode:
    def __init__(self, closure):
        self.closure = sorted(closure)
        self.idx = None

    def __str__(self):
        return ", ".join(self.closure)

class Graph:
    def __init__(self, terminais, naoterminais, seguintes, producoes):
        self.terminais = terminais
        self.naoterminais = naoterminais
        self.seguintes = seguintes
        self.graph = {}
        self.nodes = {}
        self.state = "afnd"
        self.simbolos = None
        self.producoes = producoes

    def add_node(self, node):
        if str(node) not in self.graph:
            self.graph[str(node)] = {}
            self.nodes[str(node)] = node

    def add_edge(self, from_node, to_node, label):
        self.add_node(from_node)
        self.add_node(to_node)
        self.graph[str(from_node)][str(to_node)] = label

    def rename_nodes(self):
        idx = 0
        for key, value in self.nodes.items():
            value.idx = idx
            idx += 1

    def reduce_to_afd(self):
        start = "E'->.E"
        afd = Graph(self.terminais, self.naoterminais, self.seguintes, self.producoes)
        closure = self.__get_closure(start)

        simbolos = set(itertools.chain(*[prod.left + prod.right for prod in self.nodes.values()]))
        self.simbolos = [x for x in simbolos if x != '.']

        queue = Queue(maxsize=1000)
        queue.put(AfdNode(closure))
        hash = {}
        while not queue.empty():
            front = queue.get()
            for simbolo in simbolos:
                tmp = []
                for prod in front.closure:
                    tmp += [neighbor for neighbor in self.graph[prod] if self.graph[prod][neighbor] == simbolo]
                if len(tmp):
                    goto = []
                    tmpclosure = itertools.chain(*[self.__get_closure(x) for x in tmp])
                    for node in tmpclosure:
                        if node not in goto:
                            goto.append(node)
                    afdnode = AfdNode(goto)
                    afd.add_edge(front, afdnode, simbolo)
                    if str(afdnode) not in hash:
                        queue.put(afdnode)
                        hash[str(afdnode)] = True

        self.graph = afd.graph
        self.nodes = afd.nodes
        self.state = "afd"

        self.get_slr_table()

    def __get_closure(self, node):
        closure = [node]
        queue = Queue(maxsize=10000)
        queue.put(node)
        while not queue.empty():
            front = queue.get()
            for neighbor in self.graph[front]:
                if self.graph[front][neighbor] == "eps" and neighbor not in closure:
                    closure.append(neighbor)
                    queue.put(neighbor)
        return closure

    def view(self):
        f = Digraph()
        f.attr(rankdir='LR', size='8,5')
        if self.state == "afd":
            for from_node in self.graph:
                for to_node in self.graph[from_node]:
                    f.edge(str(self.nodes[from_node].idx), str(self.nodes[to_node].idx), label=self.graph[from_node][to_node])
                    f.render(fold + 'afd.gv', view=False)
        else:
            for from_node in self.graph:
                for to_node in self.graph[from_node]:
                    f.edge(from_node, to_node, label=self.graph[from_node][to_node])
            f.render(fold + 'afnd.gv', view=False)

    def get_slr_table(self):
        if self.state == "afd":
            table = {"acao": {}, "goto": {}}

            self.rename_nodes()
            max_idx = len(self.nodes)
            for i in range(max_idx):
                for simbolo in self.terminais + ["$"]:
                    if i not in table["acao"]:
                        table["acao"][i] = {}
                    table["acao"][i][simbolo] = ""
                for simbolo in self.naoterminais:
                    if i not in table["goto"]:
                        table["goto"][i] = {}
                    table["goto"][i][simbolo] = ""

            for node in self.graph:
                for neighbor in self.graph[node]:
                    if self.graph[node][neighbor] in self.terminais + ["$"]:
                        if table["acao"][self.nodes[node].idx][self.graph[node][neighbor]] != "":
                            print("NÃO É SLR!!")
                        table["acao"][self.nodes[node].idx][self.graph[node][neighbor]] = "d " + str(self.nodes[neighbor].idx)

            for node in self.nodes.values():
                alfaponto = [prod for prod in node.closure if prod[-1] == "."]
                if len(alfaponto) > 1:
                    print("FUDEU!")
                elif len(alfaponto) == 1 and alfaponto[0] != "E'->E.":
                    for seguinte in self.seguintes[alfaponto[0][0]]:
                        if table["acao"][node.idx][seguinte]:
                            print("NÃO É SLR!!")
                        table["acao"][node.idx][seguinte] = "r " + str(self.producoes[alfaponto[0][:-1]])
                elif len(alfaponto) == 1 and alfaponto[0] == "E'->E.":
                    if table["acao"][node.idx]["$"] != "":
                        print("NÃO É SLR!!")
                    table["acao"][node.idx]["$"] = "act"

            for node in self.graph:
                for neighbor in self.graph[node]:
                    if self.graph[node][neighbor] in naoterminais:
                        if self.nodes[node].idx not in table["goto"]:
                            table["goto"][self.nodes[node].idx] = {}
                        table["goto"][self.nodes[node].idx][self.graph[node][neighbor]] = str(self.nodes[neighbor].idx)

            with open(fold + 'tabela.csv', 'w') as f:
                header = "; " + "; ".join(terminais) + "; $; " + "; ".join(naoterminais) + "\n"
                f.write(header)
                for i in range(len(self.nodes)):
                    row = str(i) + "; " + "; ".join(table["acao"][i][terminal] for terminal in terminais) + "; " + table["acao"][i]["$"] + "; " + "; ".join([table["goto"][i][naoterminal] for naoterminal in naoterminais]) + "\n"
                    f.write(row)

# prods = [
#     AfndNode(["E'"], ["E"]),
#     AfndNode(["E"], ["E", "+", "T"]),
#     AfndNode(["E"], ["T"]),
#     AfndNode(["T"], ["T", "*", "F"]),
#     AfndNode(["T"], ["F"]),
#     AfndNode(["F"], ["(", "E", ")"]),
#     AfndNode(["F"], ["id"]),
# ]
#
# terminais = ["id", "+", "*", "(", ")", "$"]
# naoterminais = ["E", "T", "F"]
#
# seguintes = {
#     "E": ["+", ")", "$"],
#     "T": ["+", "*", ")", "$"],
#     "F": ["+", "*", ")", "$"],
#     "E'": ["$"]
# }

prods = [
    AfndNode(["E'"], ["E"]),
    AfndNode(["E"], ["E", "+", "T"]),
    AfndNode(["E"], ["T"]),
    AfndNode(["T"], ["T", "*", "F"]),
    AfndNode(["T"], ["F"]),
    AfndNode(["F"], ["P", "@", "F"]),
    AfndNode(["F"], ["P"]),
    AfndNode(["P"], ["(", "E", ")"]),
    AfndNode(["P"], ["a"]),
    AfndNode(["P"], ["a", "(", "L", ")"]),
    AfndNode(["L"], ["L", ",", "E"]),
    AfndNode(["L"], ["E"]),
]

terminais = ["@", "+", "*", "(", ")", "a", ","]
naoterminais = ["E", "T", "F", "P", "L"]
seguintes = {
    "E'": ['$'],
    'E': ['$', '+', ')', ','],
    'F': ['*', '$', '+', ')', ','],
    'L': [')', ','],
    'P': ['@', '*', '$', '+', ')', ','],
    'T': ['*', '$', '+', ')', ',']
}

prods_ext = []
for prod in prods:
    for i in range(len(prod.right)):
        prods_ext.append(AfndNode(prod.left, prod.right[:i] + ["."] + prod.right[i:]))
    prods_ext.append(AfndNode(prod.left, prod.right + ["."]))

graph = Graph(terminais, naoterminais, seguintes, {str(prods[i]): i for i in range(len(prods))})
for prod in prods_ext:
    # primeiro tipo de transicao de AFND
    if prod.right[-1] != ".":
        next_prod_right = []
        i = 0
        transicao = None
        while i < len(prod.right):
            if prod.right[i] != ".":
                next_prod_right.append(prod.right[i])
                i += 1
            else:
                next_prod_right.append(prod.right[i + 1])
                transicao = prod.right[i+1]
                next_prod_right.append(".")
                i += 2
        new_prod = AfndNode(prod.left, next_prod_right)

        graph.add_edge(prod, new_prod, transicao)

    # segundo tipo de transicao de AFND
    if prod.right[-1] != ".":
        next_prod_right = []
        i = 0
        while i < len(prod.right):
            if prod.right[i] == ".":
                prods_transicoes = [x for x in prods_ext if x.left[0] == prod.right[i+1] and x.right[0] == "." and str(prod) != str(x)]
                for prod_transicao in prods_transicoes:
                    graph.add_edge(prod, prod_transicao, "eps")
            i += 1

graph.view()
graph.reduce_to_afd()
graph.view()


from Crypto.Util.number import inverse, bytes_to_long, long_to_bytes
from pwn import *

def s2n(s):
    return bytes_to_long(bytearray(s, 'latin-1'))

def n2s(n):
    return long_to_bytes(n).decode('latin-1')

def gcd(x, y):
   while(y):
       x, y = y, x % y
   return x

def inv_mod(a, b):
    mod = b
    x0, x1, y0, y1 = 0, 1, 1, 0
    while a != 0:
        q, b, a = b // a, a, b % a
        y0, y1 = y1, y0 - q * y1
        x0, x1 = x1, x0 - q * x1
    return x0 % mod

def encrypt(r, c):
    r.recvuntil("4. encrypt")
    r.sendline("4")
    r.sendline(c)
    r.recvuntil("input the data:")
    return int(r.recvline()[:-1], 16)

def recover_n(r):
    plains, ciphers = [],[]
    for i in range(4):
        c = encrypt(r, chr(2 + i))
        plains.append(2 + i)
        ciphers.append(c)

    n = ciphers[0] - pow(plains[0], 0x10001)
    for i in range(1, 4):
        n = -gcd(n, ciphers[i] - pow(plains[i], 0x10001))
    return n

def recover_fake_flag(r):
    r.recvuntil("4. encrypt")
    r.clean(1.0)
    r.sendline("3")
    return int(r.recvline()[:-1], 16)

def recover_flag(r):
    r.recvuntil("4. encrypt")
    r.clean(1.0)
    r.sendline("1")
    return int(r.recvline()[:-1], 16)

if __name__ == '__main__':
    r = remote('crypto.chal.csaw.io', 1001)

    n = recover_n(r)
    fake_flag_ko = recover_fake_flag(r)
    flag = recover_flag(r)

    for i in range(10000):
        fake_flag = 'fake_flag{%s}' % (('%X' % i).rjust(32, '0'))

        m = s2n(fake_flag)
        g = gcd(fake_flag_ko - pow(m, 0x10001, n), n)
        if g != 1 and g != n:
            break

    p = n // g
    q = n // p
    d = inv_mod(0x10001, (p - 1) * (q - 1))
    m = pow(flag, d, n)
    print(n2s(m))


import gspread
import pprint
import tabulate
import csv
import sys
import string
from os import path, mkdir
from colors import *

# Output Directory Name
OUTPUTDIR = "outputCsv/"

# Final attributes to be used in the output CSV file.
contactFileAttributes     = ['Name', 'Given Name', 'Additional Name', 'Family Name', 'Yomi Name', 'Given Name Yomi', 'Additional Name Yomi', 'Family Name Yomi', 'Name Prefix', 'Name Suffix', 'Initials', 'Nickname', 'Short Name', 'Maiden Name', 'Birthday', 'Gender', 'Location', 'Billing Information', 'Directory Server', 'Mileage', 'Occupation', 'Hobby', 'Sensitivity', 'Priority', 'Subject', 'Notes', 'Language', 'Photo', 'Group Membership', 'E-mail 1 - Type', 'E-mail 1 - Value', 'Phone 1 - Type', 'Phone 1 - Value']

# Must have attributes for the output CSV file.
contactRequiredAttributes = [ "Name", "Phone 1 - Value"]

# Google Sheet attribute list
sheetAllAttributes = ["First Name", "Last Name", "Email Address", "Mobile", "City", "Occupation"]

# Must have attributes in the Google Sheet
sheetRequiredAttributes = ["First Name", "Last Name", "Mobile"]

MappingsSheetToCsv = {
"Name" : ["First Name" , "Last Name"],
"Family Name" : "Last Name",
"E-mail 1 - Value" : "Email Address",
"Phone 1 - Value" : "Mobile",
"Occupation" : "Occupation",
"Location" : "City"
}

def displayTable(dict_list):
    """
    This function
        1. Takes a list of dictionary
        2. Add an Index column, and
        3. Displays the data in tabular format
    """
    header = ['idx'] + list(dict_list[0].keys())
    rows = [[idx + 1] + list(x.values()) for idx, x in enumerate(dict_list)]
    print(tabulate.tabulate(rows, header, tablefmt='grid'))
    print("\n")

def displayTableFromList(listname, list_vals):
    tmp_dict = []
    for temp in list_vals:
        tmp = {listname : temp }
        tmp_dict.append(tmp)

    displayTable(tmp_dict)

def selectOptionFromList(listname, list_vals):
    displayTableFromList(listname, list_vals)
    index = int(input('Enter {} index: '.format(listname)))
    if index > len(list_vals):
        prRed("[ERROR] : Wrong choice entered, please try again!")
        sys.exit()

    optionVal = list_vals[index - 1]
    prBlue("The {} Selected is \"{}\"".format(listname, optionVal))
    return index, optionVal

class Mappings:
    def __init__(self, idealMap, dList, sList):
        self.idealMapping   = idealMap
        self.dstMappingList = dList
        self.srcMappingList = sList

    def createFinalMappingBasedOnFiles(self):
        self.finalMapping = {}
        for key, value in self.idealMapping.items():
            if type(value) == list:
                flag = all(item in self.srcMappingList for item in value)
            else:
                flag = value in self.srcMappingList
            if flag and key in self.dstMappingList:
                self.finalMapping[key] = value

    def updateMapping(self):
        displayDictionaryAsMappings(self.finalMapping)

        choice = input("Do you want to add any more mappings? Type yes or no: ")
        while choice == "yes":
            fieldIndex1, fieldValue1 = selectOptionFromList('Destination File Field', self.dstMappingList)
            fieldIndex2, fieldValue2 = selectOptionFromList('Source File Field', self.srcMappingList)
            self.finalMapping[fieldValue1] = fieldValue2
            prYellow('\nCurrent Mappings : ')
            displayDictionaryAsMappings(self.finalMapping)
            choice = input("\nDo you want to add any more mappings? Type yes or no: ")
        else:
            prGreen("\n[+] Final Mappings")

        displayDictionaryAsMappings(self.finalMapping)

class RecordClass:
    def __init__(self, rcList, rcAttr):
        self.allRecords = rcList
        self.recordAttributes = rcAttr
        self.recordSize = len(self.allRecords)
        self.trimmedRecords = []

    def checkRequiredAttributes(self):
        missingFields = []

        if self.bIsDestFile:
            for field in self.allAttributes:
                if field not in self.recordAttributes:
                    missingFields.append(field)
        else:
            for field in self.requiredAttributes:
                if field not in self.recordAttributes:
                    missingFields.append(field)

        if (len(missingFields)):
            prRed("\n[ERROR] : There are missing fields in the sheet, they are : ")
            displayTableFromList('Field Name', missingFields)
            sys.exit()

    def fetchAttrValueListFromRecords(self, attrName):
        contactNumbers = list(set([ num[attrName] for num in self.allRecords ]))
        return contactNumbers

    def setAllAttributes(self, allAttr, requiredAttr):
        self.allAttributes      = allAttr
        self.requiredAttributes = requiredAttr

    def removeDuplicatesBasedOnValue(self, uniqVal=None):
        new_list = []
        new_list_vals = []
        if uniqVal is not None:
            for item in self.allRecords:
                if item[uniqVal] not in new_list_vals and item[uniqVal] != "None":
                    new_list.append(item)
                    new_list_vals.append(item[uniqVal])

            # Update the records and record size as well
            prLightPurple("[!] Number of Removed Duplicates : {}".format(len(self.allRecords) - len(new_list)))
            self.allRecords = new_list
            self.recordSize = len(self.allRecords)

class FileClass(RecordClass):
    def __init__(self, name1 = "", name2 = "", ext=""):
        self.fileName = OUTPUTDIR + "Contacts - " + name1 + " - " + name2 + ext
        if path.isfile(self.fileName):
            self.bFileExists = True
        else:
            self.bFileExists = False
        self.bIsDestFile = False

    def fetchRecordsFromFile(self):
        if not self.bFileExists:
            prRed("[ERROR] : Cant fetch records from a file that doesn't exist! Returning...")
            sys.exit()

        self.fileRecords = []
        with open(self.fileName, 'r') as csFile:
            reader = csv.DictReader(csFile)
            for dataRow in reader:
                self.fileRecords.append(dataRow)

        self.fileRecordFields  = list(self.fileRecords[0].keys())
        super().__init__(self.fileRecords, self.fileRecordFields)

class SheetClass(RecordClass):
    def __init__(self, sheetClnt, name1 = "", name2 = ""):
        try :
            sheetClnt.open(name1).worksheet(name2)
        except :
            prRed("\n[ERROR] : Please check if you've provided the correct values!\nSpreadsheet Name : " + name1 + "\nSheet Name : " + name2)
            prRed("\n[ERROR] : Alternatively, please check if you've given the correct access to the service account for the specified sheet.")
            sys.exit()

        self.spreadsheetName = name1
        self.sheetName       = name2
        self.sheetObject     = sheetClnt.open(self.spreadsheetName).worksheet(self.sheetName)
        self.sheetHeaders    = self.sheetObject.row_values(1)
        self.bIsDestFile     = False

        super().__init__(self.sheetObject.get_all_records(default_blank='None'), self.sheetHeaders)

    def fetchColumnIndex(self):
        displayTableFromList('Column', self.sheetHeaders)
        index = int(input('Enter Column index: '))
        return index

    def fetchColumnValues(self, columnIndex=None):

        if columnIndex is None:
            columnIndex = self.fetchColumnIndex()

        # Perform a sanity check
        if columnIndex > len(self.sheetHeaders):
            prRed("[ERROR] : You have selected an invalid column name : {}".format(columnIndex));
            sys.exit()

        columnValues = self.sheetObject.col_values(columnIndex)
        columnValues.remove(self.sheetHeaders[columnIndex - 1])
        columnValues = list(set(columnValues))

        return columnValues, self.sheetHeaders[columnIndex - 1]

def getWorksheetName():
  spreadsheetName = str(input("Enter the spreadsheet name: "))
  spreadsheetName = spreadsheetName.strip()
  sheetName = str(input("Enter the Sheet name: "))
  sheetName = sheetName.strip()
  if spreadsheetName and sheetName:
    prYellow ("\nThe Spreadsheet selected is : " + spreadsheetName + "\nThe Sheet selected is : " + sheetName + "\n")
  else:
    prYellow("Please enter the name of the Spreadsheet and Sheet!");
    exit();
  return spreadsheetName, sheetName;

def getAuthClient():

    # Check if the service account credentials are stored properly or not.
    homeDir = path.expanduser( '~' )
    jsonFilePath = homeDir + '/.config/gspread/service_account.json'
    if not path.isfile(jsonFilePath):
        prRed("[ERROR] : Please ensure that the service account credentials file is there at {}. For more info : https://docs.gspread.org/en/v5.7.0/oauth2.html#for-bots-using-service-account".format(jsonFilePath))
        sys.exit()

    # Authorise the client
    return gspread.service_account()

def checkOrCreateDestDir(dirName):
    if not path.exists(dirName):
        prGreen("\n[+] Creating {} directory in the same folder!".format(OUTPUTDIR))
        mkdir(dirName)

def fetchTheClientRecords(allAttr=None, reqAttr=None):

    # Authorise the client
    client = getAuthClient()

    # Get the spreadsheet and Sheet Name
    spreadsheetName, sheetName = getWorksheetName()

    prGreen("[+] Fetching all the records...")
    clientSheet = SheetClass(client, spreadsheetName, sheetName)

    # Check if the following headers are present in the sheet, otherwise exit
    if allAttr == None and reqAttr == None:
        clientSheet.setAllAttributes(sheetAllAttributes, sheetRequiredAttributes)
    else:
        clientSheet.setAllAttributes(allAttr, reqAttr)

    clientSheet.checkRequiredAttributes()
    return clientSheet

def createDictionaryFromMappings(mapping, contactAttributes, recordVal):
    tmpDictionary = {}

    for attr in contactAttributes:
        if attr in mapping.keys():
            if type(mapping[attr]) == list:
                tmpDictionary[attr] = ""
                for index in mapping[attr]:
                    tmpDictionary[attr] += recordVal[index] + " "
                tmpDictionary[attr] = str(tmpDictionary[attr].strip())
            else:
                tmpDictionary[attr] = str(recordVal[mapping[attr]])
        else:
            tmpDictionary[attr] = ""

    return tmpDictionary

def removeExistingContacts(clientContactsFileObject, clientSheetObject):

    # Note that these are in string format
    currentSavedContacts = clientContactsFileObject.fetchAttrValueListFromRecords('Phone 1 - Value')

    clientSheetObject.trimmedRecords = []
    for i in range(clientSheetObject.recordSize):
        mobile = str(clientSheetObject.allRecords[i]['Mobile'])
        if mobile not in currentSavedContacts and mobile != "None":
            clientSheetObject.trimmedRecords.append(clientSheetObject.allRecords[i])

    if len(clientSheetObject.trimmedRecords) == 0:
        prBlue("[++] There are no new contacts.. Exiting!")
        sys.exit()

    prLightPurple("[!] Number of new contacts : {}".format(len(clientSheetObject.trimmedRecords)))

def createContactFileObject(Prefix, Suffix, bIsDest, fileExt=""):
    contactFileObject = FileClass(Prefix, Suffix, fileExt)
    contactFileObject.bIsDestFile = bIsDest
    contactFileObject.setAllAttributes(contactFileAttributes, contactRequiredAttributes)

    return contactFileObject

def getRecordsWithAttr(recordList, attrKey, attrValue):
    if len(recordList) <= 0:
        prRed("[ERROR] : Record List is empty!")
        sys.exit()

    final_record = []
    for client_deet in recordList:
        if client_deet.get(attrKey) == attrValue:
            final_record.append(client_deet)

    return final_record

def displayKeyValuePairs(dictName):
    prYellow('This is how the mapping is done :')
    for key, value in dictName.items():
        if type(value) == list:
            val = " + ".join(value)
            print (f"{key:<30}{'==>':<10}{val:<40}")
        else:
            print (f"{key:<30}{'==>':<10}{value:<40}")

def displayDictionaryAsMappings(dictName):
    listDict = []
    listDict.append(dictName)
    displayTable(listDict)

def addRecordsToFile(fileName, fileHeaders, operationChoice, records):

    fileName = fileName
    if operationChoice == "append":
        with open(fileName, 'a') as csvFile:
            writer = csv.DictWriter(csvFile, fieldnames = fileHeaders)
            writer.writerows(records)

    elif operationChoice == "write":
        with open(fileName, 'w') as csvFile:
            writer = csv.DictWriter(csvFile, fieldnames = fileHeaders)
            writer.writeheader()
            writer.writerows(records)
    else:
        prRed("[ERROR] : Unknown Choice... Exiting!")
        sys.exit()

    prLightPurple("[++] Contacts added to File : {}\n".format(fileName))

def createDestinationFileFromSourceRecords(objMapping, destFileObject, sourceRecords, bIsDstFileTmp):
        recordFinalList = []
        for record in sourceRecords:
            recordFinalList.append(createDictionaryFromMappings(objMapping.finalMapping, objMapping.dstMappingList ,record))

        fileName    = destFileObject.fileName
        fileHeaders = objMapping.dstMappingList

        if destFileObject.bFileExists and not bIsDstFileTmp:
            addRecordsToFile(fileName, fileHeaders, "append", recordFinalList)
        else:
            addRecordsToFile(fileName, fileHeaders, "write", recordFinalList)

def main():

    # Fetch the client records from the spreadsheet
    clientSheetObject = fetchTheClientRecords()
    prLightPurple("[!] Number of Fetched Records : {}".format(len(clientSheetObject.allRecords)))

    prGreen("[+] Removing all the duplicated and invalid rows...")
    clientSheetObject.removeDuplicatesBasedOnValue('Mobile')

    # Create a contact file object
    clientContactsFileObject = createContactFileObject(
        clientSheetObject.spreadsheetName,
        clientSheetObject.sheetName,
        True,
        ".csv"
    )

    currentContactTmpObject = createContactFileObject(
        "My",
        "Temp",
        True,
        ".csv"
    )

    if clientContactsFileObject.bFileExists:
        # Fetch all the records
        prLightPurple("\n[!] There is already an existing file for this sheet, fetching its Records...")
        clientContactsFileObject.fetchRecordsFromFile()

        # Check for required Fields
        clientContactsFileObject.checkRequiredAttributes()

        # If the file has some records, remove them from the fetched records
        prGreen("[+] Removing all the Records that are already present in the file...")
        removeExistingContacts(clientContactsFileObject, clientSheetObject)

    prYellow("\n\nThe current Mapping is as follows :")
    mappingSheetToCsv = Mappings(MappingsSheetToCsv, clientContactsFileObject.allAttributes, clientSheetObject.recordAttributes)
    mappingSheetToCsv.createFinalMappingBasedOnFiles()
    mappingSheetToCsv.updateMapping()

    if clientContactsFileObject.bFileExists:
        recordList = clientSheetObject.trimmedRecords
    else:
        recordList = clientSheetObject.allRecords

    # Check if directory exists, and if not, create one!
    checkOrCreateDestDir(OUTPUTDIR)

    # Adding to main file
    prGreen("[+] Adding all the new contacts to the main file...")
    createDestinationFileFromSourceRecords(mappingSheetToCsv, clientContactsFileObject, recordList, False)

    # Adding to temporary File
    if len(clientSheetObject.trimmedRecords):
        prGreen("[+] Adding all the new contacts to the temporary file...")
        createDestinationFileFromSourceRecords(mappingSheetToCsv, currentContactTmpObject, clientSheetObject.trimmedRecords, True)

if __name__ == '__main__':
    main()


import torch
import numpy

w = torch.tensor([1.],requires_grad=True)
x = torch.tensor([2.],requires_grad=False)
a = torch.add(x,w)
b = torch.add(w,1)
y = torch.mul(a,b)

#f=(x+w)*(w+1) = w2 + (x+1)w + x
#df(w) = 2w + x +1
y.backward()
print(w.grad)
print(x.grad)

# -------------
w = torch.tensor([1.],requires_grad=True)
x = torch.tensor([2.],requires_grad=True)

for i in range(3):
    a = torch.add(x,w)
    b = torch.add(w,1)
    y = torch.mul(a,b)

    y.backward()
    print(w.grad)
    w.grad.zero_()

# --------------
a = torch.rand(3,4)
b = torch.rand(4)
x = a+b


import unireedsolomon as ReedSalomon
import lib as Lib
import mpmath as BigNumbers
import numpy as np

class Coder:
    # Constuctor, initializes the parameters.
    def __init__(self):
        self.RSCoder = ReedSalomon.rs.RSCoder(
            Lib.CODE_WORD_LENGTH, Lib.MESSAGE_LENGTH)
        self.receivedData = list()

    # TODO: Test
    def newVectorReceived(self, vector):
        self.receivedData.append(vector)
        length = len(self.receivedData)

        while (self.dataReceivedIsTooLong(length)):
            self.receivedData.pop(0)

        if (self.dataReceivedHasRightLength(length)):
            return self.decode(self.receivedData)
        else:
            print(Lib.DECODING_NOT_READY)
            return (False, Lib.DECODING_NOT_READY)

    # Checks if the received data is too long.
    def dataReceivedIsTooLong(self, length):
        return length > Lib.NEEDED_AMOUNT_OF_VECTORS

    # Checks if the received data has the correct lenght.
    def dataReceivedHasRightLength(self, length):
        return length == Lib.NEEDED_AMOUNT_OF_VECTORS

    # Encodes the string so that it can be sent as k bits at a time.
    def encode(self, string):
        rsEncodedString = self.applyEcc(string)
        byteVectorList = self.stringToListOfByteVectors(rsEncodedString)
        chunkedVectorsList = self.chunk(byteVectorList)

        return chunkedVectorsList

    # Decodes k-bit vectors to get back a readable string.
    def decode(self, tupleList):
        output = Lib.DECODING_FAILED
        isDecoded = False

        try:
            assembledVectorsList = self.assemble(tupleList)
            stringReceived = self.listOfByteVectorsToString(
                assembledVectorsList)
            output = self.recoverEcc(stringReceived)
            isDecoded = True
        except:
            print(Lib.DECODING_FAILED)

        return (isDecoded, output)

    # Chunks the 8-bit vectors into smaller vectors.
    def chunk(self, vectorList):
        # Chunk
        chuncked = list(map(lambda vector: [vector[i:i + Lib.CHUNK_SIZE] for i in range(0, len(vector), Lib.CHUNK_SIZE)],
                            vectorList))

        # Flatten
        outputList = list()
        for i in range(0, len(chuncked)):
            for j in range(0, len(chuncked[i])):
                outputList.append(chuncked[i][j])

        return outputList

    # Assembles the k-bit vectors to have 8-bit vectors again.
    def assemble(self, vectorList):
        output = list()
        step = int(Lib.BYTE_BIT_SIZE / Lib.CHUNK_SIZE)

        for i in range(0, len(vectorList), step):
            tempList = list()
            for j in range(0, step):
                tempList.append(vectorList[i + j])
            output.append([bit for vector in tempList for bit in vector])

        return output

    # Applies an error correcting encoding. In this case it is the Reed Solomon ECC.
    def applyEcc(self, string):
        return self.RSCoder.encode(string)

    # Tries to recover the original string from a received Reed Solomon ECC.
    def recoverEcc(self, string):
        return self.RSCoder.decode(string)[0]

    # Randomizes the bytes to expect having a P(0)=P(1)=1/2 so that we can use an ML rule.
    def randomizeBytes(self, byteString):
        '''
        output = map(lambda x: int.from_bytes(
            [x], byteorder=Lib.BYTE_ENDIANESS) + 1, byteString)
        output = map(lambda x: BigNumbers.fmul(
            x, Lib.BIG_PRIME_NUMBER), output)
        output = map(lambda x: BigNumbers.fmod(
            x, Lib.BYTE_DIFF_VALUES), output)
        output = map(lambda x: int(BigNumbers.nstr(
            x)[: - 2]), output)
        '''
        output = map(lambda x: Lib.BYTE_RANDOMIZE_MAP.get(int.from_bytes(
            [x], byteorder=Lib.BYTE_ENDIANESS)), byteString)

        return bytes(output)

    # Recovers the original bytes that have been randomized.
    def recoverBytes(self, byteString):
        output = map(lambda x: Lib.BYTE_RECOVER_MAP.get(int.from_bytes(
            [x], byteorder=Lib.BYTE_ENDIANESS)), byteString)

        return bytes(output)

    # Converts a regular string into a list of 8-bit vectors.
    # "He" -> [[0, 1, 0, 0, 1, 0, 0, 0], [0, 1, 1, 0, 0, 1, 0, 1]]
    def stringToListOfByteVectors(self, string):
        tmp = list(
            map(lambda x: bin(x)[2:], self.randomizeBytes(string.encode(Lib.UTF_8))))

        output = list()
        for e in tmp:
            test = list()
            for i in e:
                test.append(int(i))
            output.append(test)

        for e in output:
            if len(e) < 8:
                for i in range(8-len(e)):
                    e.insert(0, 0)

        return output

    # Converts a list of 8-bit vectors to a regular string (with accents).
    # [[0, 1, 0, 0, 1, 0, 0, 0], [0, 1, 1, 0, 0, 1, 0, 1]] -> "He"
    def listOfByteVectorsToString(self, byteVectors):
        return self.recoverBytes(bytes(list(
            map(lambda bitString: int(bitString, 2),
                map(lambda vector: "".join(
                    map(lambda x: repr(x), vector)), byteVectors))))).decode(
                        Lib.UNICODE_ESCAPE).encode(Lib.LATIN_1).decode(Lib.UTF_8)

    # Creates a random array using a seed.
    def createRandomArray(self, array_size, seed, max_value):
        np.random.seed(seed)
        tmp = np.random.randint(max_value, size=(array_size))
        return tmp


from uuid import UUID
from ipaddress import IPv4Address
import pandas as pd
import pytest

from ontolocy import (
    IPAddressNode,
    Country,
    DataOrigin,
    ListeningSocket,
    IPAddressHasOpenPort,
    IPAddressBelongsToASN,
    IPAddressLocatedInCountry,
    ASN,
)

@pytest.mark.parametrize(
    "ip_address,private,version",
    [
        ("1.1.1.1", False, "ipv4"),
        ("8.8.8.8", False, "ipv4"),
        ("192.168.101.123", True, "ipv4"),
        ("10.4.5.6", True, "ipv4"),
        ("2001:db8::1", True, "ipv6"),
        ("2001:4860:4860::8888", False, "ipv6"),
    ],
)
def test_basic_ips(ip_address, private, version):

    ip = IPAddressNode(ip_address=ip_address)

    assert ip.private is private
    assert ip.ip_version == version
    assert ip.get_identifier() == ip_address

    if private:
        assert ip.namespace is not None

    else:
        assert ip.namespace is None

@pytest.mark.parametrize(
    "ip_address,unique_id",
    [
        ("1.1.1.1", "b3845f07-e8e2-5374-85cd-1c5e381a095f"),
        ("8.8.8.8", "918605df-3e1c-5fc8-ae3b-f76918df2b55"),
        ("2001:4860:4860::8888", "37d7589d-643e-5f19-8f88-1564af8972ef"),
    ],
)
def test_repeatable_unique_id_public(ip_address, unique_id):

    ip1 = IPAddressNode(ip_address=ip_address, namespace="this shouldn't matter")

    uuid1 = ip1.unique_id

    ip2 = IPAddressNode(ip_address=ip_address)

    uuid2 = ip2.unique_id

    assert uuid1 == uuid2

    assert uuid1 == UUID(unique_id)

def test_repeatable_unique_id_private():

    ip1 = IPAddressNode(ip_address="192.168.0.1", namespace="ontolocy-test")

    uuid1 = ip1.unique_id

    ip2 = IPAddressNode(ip_address="192.168.0.1", namespace="ontolocy-test")

    uuid2 = ip2.unique_id

    assert uuid1 == uuid2

    assert uuid1 == UUID("9ec0a0fc-1fc5-50b1-925c-db5393faf934")

def test_unique_id_private():

    ip1 = IPAddressNode(ip_address="192.168.0.1")

    uuid1 = ip1.unique_id

    ip2 = IPAddressNode(ip_address="192.168.0.1")

    uuid2 = ip2.unique_id

    assert uuid1 != uuid2

def test_ingest_df(use_graph):

    my_ips = [
        {
            "ip_address": "192.168.10.1",
            "namespace": "ontolocy-test",
        },
        {
            "ip_address": "192.168.10.2",
            "namespace": "ontolocy-test",
        },
    ]

    my_ips_df = pd.DataFrame.from_records(my_ips)

    data_origin = DataOrigin(name="Ontolocy Test Data")

    IPAddressNode.ingest_df(my_ips_df, data_origin)

    cypher = """
    MATCH (o:DataOrigin)-[:ORIGIN_GENERATED]->(ip:IPAddress)
    WHERE o.name = 'Ontolocy Test Data'
    RETURN COUNT(DISTINCT ip)
    """

    result = use_graph.evaluate(cypher)

    assert result == 2

def test_merge_df(use_graph):

    my_ips = [
        {
            "ip_address": "192.168.10.1",
            "namespace": "ontolocy-test",
        },
        {
            "ip_address": "192.168.10.1",
            "namespace": "ontolocy-test",
        },
        {
            "ip_address": "192.168.10.2",
            "namespace": "ontolocy-test",
        },
        {
            "ip_address": "1.1.1.1",
            "namespace": "ontolocy-test",
        },
        {
            "ip_address": "8.8.8.8",
            "namespace": "ontolocy-test",
        },
        {
            "ip_address": "8.8.8.8",
            "namespace": "ontolocy-test",
        },
        {
            "ip_address": "2001:4860:4860::8888",
            "namespace": "ontolocy-test",
        },
        {
            "ip_address": "2001:db8::1",
            "namespace": "ontolocy-test",
        },
        {
            "ip_address": "2001:db8::1",
            "namespace": "ontolocy-test",
        },
    ]

    my_ips_df = pd.DataFrame.from_records(my_ips)

    # merge_df should give us back a list of results which reflects the shape of the data sent in
    merge_results = IPAddressNode.merge_df(my_ips_df)

    assert len(merge_results) == len(my_ips_df)

    assert merge_results[0].ip_address == IPv4Address("192.168.10.1")
    assert merge_results[0].private is True
    assert merge_results[0].ip_version == "ipv4"

    assert merge_results[3].ip_address == IPv4Address("1.1.1.1")
    assert merge_results[3].private is False
    assert merge_results[3].ip_version == "ipv4"

    # we shouldn't have created any duplicate nodes because of the namespacing
    # therefore if we just match all nodes, we should only get 6 hits

    match_results = IPAddressNode.match_nodes()

    assert len(match_results) == 6

def test_ip_address_has_open_port(use_graph):

    ip = IPAddressNode(ip_address="8.8.8.8")
    ip.merge()

    socket = ListeningSocket(ip_address="8.8.8.8", protocol="udp", port_number=53)
    socket.merge()

    rel = IPAddressHasOpenPort(source=ip, target=socket)
    rel.merge()

    cypher = """
    MATCH (ip:IPAddress)-[:IP_ADDRESS_HAS_OPEN_PORT]->(op:ListeningSocket)
    WHERE ip.ip_address = '8.8.8.8'
    RETURN COUNT(DISTINCT op)
    """

    result = use_graph.evaluate(cypher)

    assert result == 1

def test_ip_address_belongs_to_asn(use_graph):

    ip = IPAddressNode(ip_address="8.8.8.8")
    ip.merge()

    asn = ASN(
        number=15169,
        country_code="US",
        registry="arin",
        network_name="GOOGLE",
        description="GOOGLE - Google Inc., US",
        cidr="8.8.8.0/24",
    )
    asn.merge()

    rel = IPAddressBelongsToASN(source=ip, target=asn)
    rel.merge()

    cypher = """
    MATCH (ip:IPAddress)-[:IP_ADDRESS_BELONGS_TO_ASN]->(asn:ASN)
    WHERE ip.ip_address = '8.8.8.8'
    RETURN COUNT(DISTINCT asn)
    """

    result = use_graph.evaluate(cypher)

    assert result == 1

def test_ip_address_located_in_country(use_graph):

    ip = IPAddressNode(ip_address="8.8.8.8")
    ip.merge()

    country = Country(country_code="DE")
    country.merge()

    rel = IPAddressLocatedInCountry(source=ip, target=country)
    rel.merge()

    cypher = """
    MATCH (ip:IPAddress)-[:IP_ADDRESS_LOCATED_IN_COUNTRY]->(country:Country)
    WHERE ip.ip_address = '8.8.8.8'
    RETURN COUNT(DISTINCT country)
    """

    result = use_graph.evaluate(cypher)

    assert result == 1


#Facial detection
import cv2

video = cv2.VideoCapture(0)

#Add in face detection classifiers
body_classifier = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_fullbody.xml')

#Facial Detection
while True:
    #return each frame
    ret, frame = video.read()
    #make the video feed gray
    gray_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

    # Detect faces in the image
    faces_detected = body_classifier.detectMultiScale(
        gray_frame,
        scaleFactor=1.1,
        minNeighbors=5,
        minSize=(30, 30),
        flags=cv2.CASCADE_SCALE_IMAGE
    )

    #DRAW RECTANGLES
    # Draw a rectangle around the faces
    for (column, row, width, height) in faces_detected:
        cv2.rectangle(frame, (column, row), (column + width, row + height), (0, 255, 0), 2)

    # Show the video feed (WHY WON"T IT BE GRAY)
    cv2.imshow('gray_frame', frame)

    if cv2.waitKey(1) == ord('q'):
        break
# When everything done, release the capture
video.release()
cv2.destroyAllWindows()


import urllib

from django.contrib.auth.models import AnonymousUser
from django.core.urlresolvers import reverse
from django.http import HttpRequest
from django.test import TestCase
from django.test.client import RequestFactory

from MyJobs.middleware import RedirectMiddleware
from myjobs.models import User
from myjobs.tests.factories import UserFactory

class RedirectMiddlewareTests(TestCase):
    def setUp(self):
        self.user = UserFactory()
        self.redirect_middleware = RedirectMiddleware()
        self.request_factory = RequestFactory()

    def test_logged_in_no_redirect(self):
        """
        A logged in user whose password_change flag is not set
        should proceed to their original destination
        """
        request = self.request_factory.get(reverse('edit_account'))
        request.user = self.user
        response = self.redirect_middleware.process_request(request)
        self.assertEqual(response, None)

    def test_logged_in_autocreated_user_redirects(self):
        """
        A logged in user whose password_change flag is set should
        be redirected to the password change form
        """
        self.user.password_change = True
        self.user.save()

        request = self.request_factory.get(reverse('saved_search_main'))
        request.user = self.user

        response = self.redirect_middleware.process_request(request)

        self.assertEqual(response.status_code, 302)
        self.assertEqual(response.get('location'),
                         reverse('edit_account'))

    def test_not_logged_in_returns_forbidden(self):
        """
        An anonymous user that tries to post to a private url should
        receive a 403 Forbidden status
        """
        request = self.request_factory.get(reverse('saved_search_main'),
                                           HTTP_X_REQUESTED_WITH='XMLHttpRequest')
        new_request = request.GET.copy()
        new_request['next'] = reverse('home')
        request.GET = new_request
        request.REQUEST.dicts = (new_request, request.POST)
        request.user = AnonymousUser()
        response = self.redirect_middleware.process_request(request)
        self.assertEqual(response.status_code, 403)


import re

import requests
from bs4 import BeautifulSoup

if __name__ == '__main__':
    MPname = ['GQ实验室']
    query = ''
    for query in MPname:
        query.encode()
        query_url = 'http://weixin.sogou.com/weixin?type=1&' \
                    's_from=input&query=' + query + '&ie&=utf8&_sug_=n&_sug_type_'

        pagecode = requests.get(query_url).text

    bs = BeautifulSoup(pagecode, 'lxml')
    res = bs.find_all(attrs={'class': 'tit'})
    for tag in res:
        print(tag.contents[1])


#Faça um programa, com uma função que calcule a média de uma lista.

#inicio:

cont = ''
import statistics#biblioteca do python
#tambem poderia ser usado as funções len(lista) e sum(lista) para realizar o calculo das medias

while cont != 's': #loop do progama
 lista = []
 quant = int(input('bem vindo ao progama de analise,digite a seguir quantos numeros irão compor a sua lista para comecar a analise '))
 for x in range (0,quant):
  dado = float(input('digite um numero para compor a lista: '))
  lista.append(dado)
 else:
  media = statistics.mean(lista)
  print('a media dessa lista é: ',media)

  cont = input('analise encerrada,se quiser realizar outra analise,digite quaquer outra tecla,se quiser encerrar digite S ') #condiçaõ para o fim do progama
print('****progama encerrado****') #fim


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

# Define your item pipelines here
#
# Don't forget to add your pipeline to the ITEM_PIPELINES setting
# See: https://doc.scrapy.org/en/latest/topics/item-pipeline.html
import sqlite3
import pymongo
from cloud.firebase import Firebase_connection
from cloud.dynamodb import DynamoDB_connection

class SqlitePipeline(object):

    def __init__(self):
        self.create_connection()
        self.create_table()

    def create_connection(self):
        self.conn = sqlite3.connect("output/etf.db")
        self.curr = self.conn.cursor()

    def create_table(self):
        self.curr.execute("""DROP TABLE IF EXISTS etf_db""")
        self.curr.execute("""CREATE TABLE etf_db(
                        ticker text,
                        url text,
                        fund_name text
                        )""")

    def process_item(self, item, spider):
        self.store_db(item)
        return item

    def store_db(self, item):
        self.curr.execute("""INSERT INTO etf_db VALUES (?,?,?)""", (
            item['ticker'],
            item['url'],
            item['fund_name']
        ))
        self.conn.commit()

class MongoPipeline(object):
    collection_name = 'etf_items'

    def __init__(self, mongo_uri, mongo_db):
        self.mongo_uri = mongo_uri
        self.mongo_db = mongo_db

    @classmethod
    def from_crawler(cls, crawler):
        return cls(
            mongo_uri=crawler.settings.get('MONGO_URI'),
            mongo_db=crawler.settings.get('MONGO_DATABASE', 'ETF')
        )

    def open_spider(self, spider):
        self.client = pymongo.MongoClient(self.mongo_uri)
        self.db = self.client[self.mongo_db]
        if self.collection_name in self.db.list_collection_names():
            self.db.drop_collection(self.collection_name)

    def close_spider(self, spider):
        self.client.close()

    def process_item(self, item, spider):
        self.db[self.collection_name].insert_one(dict(item))
        return item

class FirebasePipeline(object):

    firebase_client = Firebase_connection()

    def process_item(self, item, spider):

        exists = self.firebase_client.check_doc_exist(item)
        if exists:
            self.firebase_client.update_doc(item)
        else:
            self.firebase_client.add_doc(item)

        return item

class DynamoDBPipeline(object):

    dynamodb_client = DynamoDB_connection()

    def process_item(self, item, spider):
        self.dynamodb_client.add_doc(item)

        return item


import pytest
import os
import json

@pytest.fixture(scope='module', autouse=True)
def setup_test(utils):
    # test multiple repos in one file
    repofile_foo = os.path.join(utils.config['repo_path'], 'yum.repos.d', 'foo.repo')
    utils.edit_config(
        {
            'name': 'Foo Repo',
            'enabled': '1',
            'baseurl': 'http://pkgs.foo.org/foo'
        },
        section='foo',
        filename=repofile_foo
    )
    utils.edit_config(
        {
            'name': 'Foo Debug Repo',
            'enabled': '0',
            'baseurl': 'http://pkgs.foo.org/foo-debug'
        },
        section='foo-debug',
        filename=repofile_foo
    )
    repofile_bar = os.path.join(utils.config['repo_path'], 'yum.repos.d', 'bar.repo')
    utils.edit_config(
        {
            'name': 'Bar Repo',
            'enabled': '1',
            'baseurl': 'http://pkgs.bar.org/bar'
        },
        section='bar',
        filename=repofile_bar
    )
    yield
    teardown_test(utils)

def teardown_test(utils):
    os.remove(os.path.join(utils.config['repo_path'], 'yum.repos.d', 'foo.repo'))
    os.remove(os.path.join(utils.config['repo_path'], 'yum.repos.d', 'bar.repo'))
    os.remove(os.path.join(utils.config['repo_path'], "yum.repos.d", 'test.repo'))
    os.remove(os.path.join(utils.config['repo_path'], "yum.repos.d", 'test1.repo'))

def find_repo(repolist, id):
    for repo in repolist:
        if repo['Repo'] == id:
            return True
    return False

def test_repolist(utils):
    ret = utils.run(['tdnf', 'repolist'])
    assert ret['retval'] == 0

# -j returns a list of repos. Easier to parse.
def test_repolist_json(utils):
    ret = utils.run(['tdnf', 'repolist', '-j'])
    assert ret['retval'] == 0
    repolist = json.loads("\n".join(ret['stdout']))
    assert find_repo(repolist, 'foo')
    assert not find_repo(repolist, 'foo-debug')
    assert find_repo(repolist, 'bar')

# disabled repo should be listed when we enable it on the command line
def test_repolist_json_enable_one(utils):
    ret = utils.run(['tdnf', 'repolist', '--enablerepo=foo-debug', '-j'])
    assert ret['retval'] == 0
    repolist = json.loads("\n".join(ret['stdout']))
    assert find_repo(repolist, 'foo')
    assert find_repo(repolist, 'foo-debug')
    assert find_repo(repolist, 'bar')

def test_repolist_all(utils):
    ret = utils.run(['tdnf', 'repolist', 'all'])
    assert ret['retval'] == 0

def test_repolist_json_all(utils):
    ret = utils.run(['tdnf', 'repolist', 'all', '-j'])
    assert ret['retval'] == 0
    repolist = json.loads("\n".join(ret['stdout']))
    assert find_repo(repolist, 'foo')
    assert find_repo(repolist, 'foo-debug')
    assert find_repo(repolist, 'bar')

def test_repolist_enabled(utils):
    ret = utils.run(['tdnf', 'repolist', 'enabled'])
    assert ret['retval'] == 0

def test_repolist_disabled(utils):
    ret = utils.run(['tdnf', 'repolist', 'disabled'])
    assert ret['retval'] == 0

def test_repolist_json_disabled(utils):
    ret = utils.run(['tdnf', 'repolist', 'disabled', '-j'])
    assert ret['retval'] == 0
    repolist = json.loads("\n".join(ret['stdout']))
    assert not find_repo(repolist, 'foo')
    assert find_repo(repolist, 'foo-debug')
    assert not find_repo(repolist, 'bar')

def test_repolist_invalid(utils):
    ret = utils.run(['tdnf', 'repolist', 'invalid_repo'])
    assert ret['retval'] == 901

# memcheck
def test_repolist_memcheck(utils):
    ret = utils.run_memcheck(['tdnf', 'repolist'])
    assert ret['retval'] == 0

# multiple repoid
def test_multiple_repoid(utils):
    reponame = 'test.repo'
    repofile_test = os.path.join(utils.config['repo_path'], 'yum.repos.d', reponame)
    utils.edit_config(
        {
            'name': 'Test Repo',
            'enabled': '1',
            'baseurl': 'http://pkgs.test.org/test'
        },
        section='test',
        filename=repofile_test
    )

    reponame = 'test1.repo'
    repofile_test1 = os.path.join(utils.config['repo_path'], 'yum.repos.d', reponame)
    utils.edit_config(
        {
            'name': 'Test Repo',
            'enabled': '1',
            'baseurl': 'http://pkgs.test1.org/test1'
        },
        section='test',
        filename=repofile_test1
    )

    ret = utils.run(['tdnf',
                     '--disablerepo=*', '--enablerepo={}'.format(reponame),
                     'makecache'])
    assert ret['retval'] == 1037


import numpy as np
import matplotlib.pyplot as plt
from skimage import io, img_as_float
from skimage.color import rgb2gray

###############################################################################
# all functions ###############################################################
###############################################################################

def plot_images(images, titles=None):
    """This function takes a list of images with
    their titles as arguments and plots side by side."""
    n_ims = len(images)
    if titles is None:
        titles = ['(%d)' % i for i in range(1, n_ims + 1)]
    fig = plt.figure()
    n = 1
    for image, title in zip(images, titles):
        a = fig.add_subplot(1, n_ims, n)  # Subplot
        if image.ndim == 2:  # Is image grayscale?
            plt.gray()
        plt.imshow(image)
        a.set_title(title)
        a.set_xlabel('Number of pixels')
        a.set_ylabel('Number of pixels')
        n += 1
    fig.set_size_inches(np.array(fig.get_size_inches()) * n_ims)
    plt.show()

class generateDataOnClick:
    def __init__(self, verbose=0):
        self.position_on_click_accumulator = []
        self.verbose = verbose

        if self.verbose > 0:
            print(" ")
            print("To use this function: clik on the positions you are")
            print("interested in, then once finished close the plot.")
            print(" ")

    def position_on_click(self, event):
        # x, y = event.x, event.y
        if event.button == 1:
            if event.inaxes is not None:
                if self.verbose > 0:
                    print('data coords: ' + str(event.xdata) + " , " + str(event.ydata))
                self.position_on_click_accumulator.append((event.xdata, event.ydata))
                plt.axvline(event.xdata, color='r')
                plt.show()

    def return_positions(self):
        return self.position_on_click_accumulator

def compute_distance(tuple_1, tuple_2):
    return np.sqrt((tuple_1[0] - tuple_2[0])**2 + (tuple_1[1] - tuple_2[1])**2)

###############################################################################
# processing of one image #####################################################
###############################################################################

# Name of the file ------------------------------------------------------------
filename = 'DSC_0476.JPG'
upload_image = io.imread(filename)  # Upload the image
image_rgb = img_as_float(upload_image[0])  # Convert the image to a np array
image_gray = rgb2gray(image_rgb)  # Convert to gray image

# Show both color and gray images ---------------------------------------------
plot_images(images=[image_rgb[300:, :], image_gray[300:, :]],
            titles=['RGB image', 'Gray image'])

# select two points on the image for performing calibration -------------------
plt.figure()
plt.imshow(image_gray)
plt.xlabel('Number of pixels')
plt.ylabel('Number of pixels')

generate_data_on_click_object = generateDataOnClick(verbose=1)

plt.connect('button_press_event', generate_data_on_click_object.position_on_click)
plt.show()

selected_positions_pixels = generate_data_on_click_object.return_positions()

print(selected_positions_pixels)

# perform calibration ---------------------------------------------------------
# distances in the real world are given in m
distance_real_world = 0.07
distance_pixels = compute_distance(selected_positions_pixels[0], selected_positions_pixels[1])

pixels_to_real_world = distance_real_world / distance_pixels

print("pixels_to_real_world: " + str(pixels_to_real_world))

# measure the length of a droplet ---------------------------------------------
plt.figure()
plt.imshow(image_gray)
plt.xlabel('Number of pixels')
plt.ylabel('Number of pixels')

generate_data_on_click_object = generateDataOnClick(verbose=1)

plt.connect('button_press_event', generate_data_on_click_object.position_on_click)
plt.show()

selected_positions_pixels = generate_data_on_click_object.return_positions()

length_droplet_meters = compute_distance(selected_positions_pixels[0], selected_positions_pixels[1]) * pixels_to_real_world
print("length droplet (m): " + str(length_droplet_meters))


#!/usr/bin/python3
# coding: utf-8
from utils.sync_deal import SyncAll
from multiprocessing import Pool
from time import sleep

def sync_deal():
    opsync = SyncAll()
    opsync.fill_token()
    opsync.update_token()
    opsync.fill_ecs()
    opsync.add_ecs()
    opsync.update_ecs()
    opsync.delete_ecs()
    opsync.status_ecs()
    opsync.delete_time_ecs()
    opsync.delete_tag_ecs()
    opsync.shutoff_tag_ecs()
    #opsync.deal_ecs()

def main():
    while True:
        p = Pool(processes=1)
        p.apply_async(sync_deal)
        p.close()
        p.join()
        sleep(3)

if __name__ == '__main__':
    main()


import pickle
import cv2
import numpy as np
from sklearn.model_selection import train_test_split
import glob
import os

path_to_images = 'Images/'
path_to_labels = 'Labels/'
path_to_data = 'Data/'
path_to_pickle = 'Pickle/'

NUM_CLASS = 20
IMG_X = 640
IMG_Y = 360
IMG_SIZE = 448
CELL_SIZE_X = 7
CELL_SIZE_Y = 7

X_SCALE = IMG_SIZE / IMG_X
Y_SCALE = IMG_SIZE / IMG_Y

def convert_to_labels(filename):
	objs = []
	label = np.zeros((CELL_SIZE_Y, CELL_SIZE_X, 5 + NUM_CLASS)).astype(np.float32)
	for i in range(NUM_CLASS):
		n_class = i
		path = path_to_labels + '%03d' % (i) + '/' + filename
		if os.path.exists(path):
			txtfile = open(path, 'r')
			objs = txtfile.readlines()
			objs = [obj.strip() for obj in objs]
			if int(objs[0]) == 0:
				pass
			else:
				for j in range(len(objs)-1):
					j += 1
					objs[j] = objs[j].split(' ')
					x1 = max((int(objs[j][0]) - (IMG_X/2)) * X_SCALE + (IMG_SIZE/2), 0)
					y1 = max((int(objs[j][1]) - (IMG_Y/2)) * Y_SCALE + (IMG_SIZE/2), 0)
					x2 = min((int(objs[j][2]) - (IMG_X/2)) * X_SCALE + (IMG_SIZE/2), IMG_SIZE)
					y2 = min((int(objs[j][3]) - (IMG_Y/2)) * Y_SCALE + (IMG_SIZE/2), IMG_SIZE)
					boxes = [(x2 + x1) / 2, (y2 + y1) / 2, x2 - x1, y2 - y1]
					x_ind = int((x2 + x1) / 2 * CELL_SIZE_X / IMG_SIZE)
					y_ind = int((y2 + y1) / 2 * CELL_SIZE_Y / IMG_SIZE)
					if label[y_ind, x_ind, 0] == 1:
						continue
					label[y_ind, x_ind, 0] = 1
					label[y_ind, x_ind, 1:5] = boxes
					label[y_ind, x_ind, 5 + n_class] = 1
		else:
			pass
	return label

img_fils = glob.glob(path_to_images + '*.jpg')
images = []
labels = []
for f in img_fils:
	img = cv2.imread(f)
	img = cv2.resize(img, (IMG_SIZE, IMG_SIZE))
	img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
	img = (img / 255.0) * 2.0 - 1.0
	images += [img]
	lf = f.split('/')[1].split('.')[0] + '.txt'
	labels += [convert_to_labels(lf)]
images = np.array(images).astype(np.float32)
labels = np.array(labels).astype(np.float32)

print (images.shape)
print (labels.shape)

X_train, X_test, y_train, y_test = train_test_split(images, labels, test_size = 0.1, random_state = 42)
X_train, X_val, y_train, y_val = train_test_split(X_train, y_train, test_size = 0.1, random_state = 42)

pickle_packet = {'xtrain' : X_train,
				 'ytrain' : y_train,
				 'xvalid' : X_val,
				 'yvalid' : y_val,
				 'xtest'  : X_test,
				 'ytest'  : y_test}
pickle_name = path_to_pickle + 'train' + str(images.shape[0]) + '.pkl'

# if os.path.exists(pickle_name):
with open(pickle_name, 'wb') as f:
	pickle.dump(pickle_packet, f)
	print (pickle_name + ' saved')


# * coding: utf8 *

import logging

from openerp import fields, models, api

_logger = logging.getLogger(__name__)

ENDPOINT = 'Procedure'

class I15dProcedure(models.Model):
    _name = 'fhir.i15d.procedure'

    _inherit = 'fhir.i15d.base'

    _rec_name = 'name'

    text = fields.Text(string="texto", readonly=True)

    name = fields.Char(string="Procedimiento", readonly=True)

    code = fields.Char(string="Codigo", readonly=True)

    encuonter_id = fields.Many2one("fhir.i15d.encounter",
                                   inverse_name='procedures_ids',
                                   string="encuentro")

    @api.model
    def build_procedure(self, procedure):
        # devuelve un diccionario con el procedimiento
        # construido de tal forma para que sea dependiente del encuentro
        dict_json = {

            'resourceType': 'Procedure',

            "status": "preparation",

            'text': self.build_text(procedure),

            'code': self.build_code(procedure),

            'subject': self.build_subject(procedure.cr_id)

        }

        return dict_json

    def build_text(self, procedure):
        # sección con las notas del procedimiento
        dict_text = {'status': 'additional',
                     'div': '''

                     NOTAS: %s \n CANTIDAD: %s
''' % (
                         procedure.notes, procedure.quantity)}

        return dict_text

    def build_code(self, procedure):
        dict_json = {
            ''
            'coding': [{
                'system': 'https://cpockets.com/cups',
                "code": procedure.activity_id.default_code,
                "display": procedure.activity_id.name

            }]

        }
        return dict_json

    def build_subject(self, clinical_record):
        # referencia de paciente al que pertenece el registro clinico
        dict_json = {}
        patient_id = clinical_record.patient_id
        url = self.get_url() + '/Patient/' + (patient_id.id_fhir or 'na')
        dict_json['reference'] = url
        dict_json['type'] = 'Patient'
        dict_json['display'] = '%s (%s)' % (patient_id.name,
                                            patient_id.ref)
        return dict_json

    def create_procedure_list(self, procedures):
        procedure_list = []

        for procedure in procedures:
            res = self.create({
                'text': procedure['text']['div'],
                'name': procedure['code']['coding'][0]['display'],
                'code': procedure['code']['coding'][0]['code']
            })
            procedure_list.append(res.id)

        return [(6, 0, procedure_list)]


import socket, sys, json, time, sched
from collections import namedtuple
import netifaces as ni
from bluepy.btle import Scanner, ScanEntry

from configuration_managers.climate.eq3btsmart import Eq3BtSmartConfig
from multiprocessing import Queue

PORT = 35224
devices = []

def start_tcp_discovery(logger: Queue, queue: Queue):
    ip = ni.ifaddresses('wlan0')[ni.AF_INET][0]['addr']

    # Create a TCP/IP socket
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    # Bind the socket to the port
    server_address = (ip, PORT)
    logger.put("starting up on %s port %s" % server_address)
    sock.bind(server_address)

    # Listen for incoming connections
    sock.listen(1)

    scanner = Scanner()

    while True:
        # Wait for a connection
        logger.put("waiting for a connection")
        connection, client_address = sock.accept()

        try:
            logger.put("connection from %s" % client_address[0])

            # Receive the data in small chunks and retransmit it
            while True:
                data = connection.recv(1024)
                resp = ""
                logger.put("received '%s'" % data)
                msg = data.decode()
                if msg == 'ha-rpi-bt-ext device discovery':
                    logger.put("device discovery '%s'" % msg)
                    devices = scanner.scan(10.0)

                    for dev in devices:
                        eq3 = Eq3BtSmartConfig("homeassistant", ip, dev)
                        if eq3.exists():
                            resp +=";" + dev.addr + "-" + str(dev.rssi) + ";"

                        # eq3 = False
                        # for (adtype, desc, value) in dev.getScanData():
                        #     if desc == "Complete Local Name" and value == "CC-RT-BLE":
                        #         eq3 = True
                        #         break
                        # if eq3:
                        #     resp += dev.addr + ":" + str(dev.rssi) + ";"
                    logger.put("sending data back to the client")
                    logger.put("data: %s" % resp[:-1])
                    connection.sendall((resp[:-1]).encode())
                    queue.put("")
                elif msg.startswith('ha-rpi-bt-ext device configure:'):
                    logger.put("device configure '%s'" % msg)
                    queue.put("configure_device:" + msg[msg.index(":") + 1:])
                    connection.sendall(b'ha-rpi-bt-ext device configured')
                else:
                    logger.put("no more data from %s" % client_address[0])
                    break
        except ConnectionResetError:
            continue
        finally:
            # Clean up the connection
            connection.close()


from __future__ import print_function, division
import numpy as np
from scipy.spatial.distance import pdist
from spatious.geom import sphere_volume
from spatious.distance import pdist_sq_periodic, cdist_sq_periodic

class MetroRCP(object):

    def __init__(self, r_0, L_0, R, dr_max, dL_max, rng=None):
        self.r = r_0
        self.L = L_0
        self.R = R
        self.dr_max = dr_max
        self.dL_max = dL_max
        if rng is None:
            rng = np.random.RandomState()
        self.rng = rng

    def U(self):
        sep_sq = pdist(self.r, metric='sqeuclidean')
        if np.any(sep_sq < (2.0 * self.R) ** 2):
            return np.inf
        for i_dim in range(self.dim):
            if np.any(np.abs(self.r[:, i_dim]) + self.R > self.L[i_dim] / 2.0):
                return np.inf
        return 1.0 / self.pf

    def displace_r(self):
        self.i = self.rng.randint(self.n)
        self.r_old = self.r[self.i].copy()

        dr = np.zeros([self.dim])
        for i_dim in range(self.dim):
            dr[i_dim] = self.rng.uniform(-self.dr_max * self.L[i_dim],
                                         self.dr_max * self.L[i_dim])

        self.r[self.i] += dr

    def revert_r(self):
        self.r[self.i] = self.r_old.copy()

    def displace_L(self):
        self.dL = 1.0 + self.rng.uniform(-self.dL_max, self.dL_max)
        self.L *= self.dL
        self.r *= self.dL

    def revert_L(self):
        self.L /= self.dL
        self.r /= self.dL

    def iterate(self, beta):
        U_0 = self.U()

        i = self.rng.randint(self.n + 1)
        if i < len(self.r):
            self.displace_r()
            revert = self.revert_r
        else:
            self.displace_L()
            revert = self.revert_L

        U_new = self.U()
        if np.exp(-beta * (U_new - U_0)) < self.rng.uniform():
            revert()

    @property
    def n(self):
        return self.r.shape[0]

    @property
    def dim(self):
        return self.L.shape[0]

    @property
    def V(self):
        return np.product(self.L)

    @property
    def V_full(self):
        return self.n * self.V_1

    @property
    def V_1(self):
        return sphere_volume(self.R, self.dim)

    @property
    def pf(self):
        return self.V_full / self.V

class MetroRCPPeriodic(MetroRCP):

    def __init__(self, r_0, L_0, R, dr_max, dL_max, rng=None):
        super(MetroRCPPeriodic, self).__init__(r_0, L_0, R, dr_max, dL_max,
                                               rng)
        self.sep_sq = pdist_sq_periodic(r_0, self.L)

    def U(self):
        if np.any(self.sep_sq < (2.0 * self.R) ** 2):
            return np.inf
        return 1.0 / self.pf

    def displace_r(self):
        super(MetroRCPPeriodic, self).displace_r()

        for i_dim in range(self.dim):
            r = self.r[:, i_dim]
            r[r > self.L[i_dim] / 2.0] -= self.L[i_dim]
            r[r < -self.L[i_dim] / 2.0] += self.L[i_dim]

        self.sep_sq_old = self.sep_sq[self.i].copy()
        sep_sq = cdist_sq_periodic(self.r[np.newaxis, self.i], self.r, self.L)
        self.sep_sq[self.i, :] = sep_sq
        self.sep_sq[:, self.i] = sep_sq
        self.sep_sq[self.i, self.i] = np.inf

    def revert_r(self):
        super(MetroRCPPeriodic, self).revert_r()
        self.sep_sq[self.i, :] = self.sep_sq_old.copy()
        self.sep_sq[:, self.i] = self.sep_sq_old.copy()

    def displace_L(self):
        super(MetroRCPPeriodic, self).displace_L()
        self.sep_sq *= self.dL ** 2

    def revert_L(self):
        super(MetroRCPPeriodic, self).revert_L()
        self.sep_sq /= self.dL ** 2

def metro_rcp_factory(periodic, *args, **kwargs):
    if periodic:
        return MetroRCPPeriodic(*args, **kwargs)
    else:
        return MetroRCP(*args, **kwargs)


import pygame
from pygame.sprite import Sprite

class BossHealth(Sprite):
    def __init__(self, game_settings, screen, boss):
        #create a bar
        super().__init__()
        self.screen = screen

        #creating a health bar
        self.rect = pygame.Rect(0, 0, boss.health, 5)
        self.rect.centerx = boss.rect.centerx
        self.rect.bottom = boss.rect.top

        #storing the bar's position
        self.centerx = float(self.rect.centerx)
        self.centery = float(self.rect.centery)

        self.color = (250,0,0)

    def update(self, boss):
        #moving the bar with the boss
        self.centerx = float(boss.centerx)
        self.centery = float(boss.rect.top - 5)
        self.rect.centerx = self.centerx
        self.rect.centery = self.centery

    def draw_bar(self):
        pygame.draw.rect(self.screen, self.color, self.rect)