from django.shortcuts import render

from django.http import HttpResponse
from django.template import RequestContext, loader
from django.db.models import Q
from mypub.models import Article, Journal, URL, VJ
from mypub.forms import SearchForm,SortForm
import re

def to_full_vj_name(vlist):
	vjlist = {
		'\\VJAS': 'Applications of Superconductivity',
		'\\VJNST': 'Nanoscale Science and Technology',
		'\\VJQI': 'Quantum Information',
	}
	for v in vlist:
		if v.title in vjlist:
			v.title = 'Virtual Journal of ' + vjlist[v.title]
	return vlist

def to_html(s):
	s = re.sub(r'\$(.*?)_{(.*?)}(.*?)\$', r'$\1\2\3$',s)
	s = re.sub(r'\$(.*?)\^{(.*?)}(.*?)\$', r'$\1\2\3$',s)
	s = re.sub(r'\$(.*?)\$', r'\1',s)
	s = s.replace('\\bar{1}',
		'1')
	s = s.replace('\\delta','<math><mi>δ</mi></math>')
	s = s.replace('\\AA{}','Å')
	s = s.replace('\\%','%')
	s = s.replace(u'\u00e9','é')
	s = s.replace(u'\u00c7','Ç')
	return s

def get_all_extra_links(a):
	ul = URL.objects.filter(article_id=a.id).order_by('id')
	vl = VJ.objects.filter(article_id=a.id).order_by('id')
	vl = to_full_vj_name(vl)
	return ul, vl

def get_thumb_name(ulist):
	for u in ulist:
		if u.name == '[Full Text]':
			t = u.link.replace('pdf','png')
	return t

def get_one_paper_from_aid(aid):
	a = Article.objects.get(id=aid)
	j = Journal.objects.get(id=a.journal_id)
	a.title = to_html(a.title)
	a.author = to_html(a.author)
	a.abstract = to_html(a.abstract)
	ulist, vlist = get_all_extra_links(a)
	t = get_thumb_name(ulist)
	return a, j, ulist, vlist, t

def field(x):
	return {'ti': x[0].title,    'au': x[0].author,
		'ab': x[0].abstract, 'yr': x[1].year, }

def sort_plist(plist,sortf,sortd):
	if sortd == 'desc':
		rev = True
	else:
		rev = False
	plist.sort(key = lambda x: field(x)[sortf], reverse=rev)

def get_sort_form(request):
	if 'SortField' in request.GET:
		soform = SortForm(request.GET)
	else:
		soform = SortForm()
	return soform

def process_sort_form(soform,plist):
	if soform.is_valid():
		sortf = soform.cleaned_data['SortField']
		sortd = soform.cleaned_data['SortDir']
		sort_plist(plist,sortf,sortd)

def index(request):
	alist = Article.objects.order_by('-journal__year')
	plist = []
	for a in alist:
		plist.append(get_one_paper_from_aid(a.id))
	seform = SearchForm()
	soform = get_sort_form(request)
	process_sort_form(soform,plist)
	template = loader.get_template('mypub/index.html')
	context = RequestContext(request, {'plist': plist,
		'searchform': seform, 'sortform': soform})
	return HttpResponse(template.render(context))

def detail(request, aid):
	paper = get_one_paper_from_aid(aid)
	template = loader.get_template('mypub/detail.html')
	context = RequestContext(request, {'paper': [paper]})
	return HttpResponse(template.render(context))

def search(request):
	seform = SearchForm(request.GET)
	if seform.is_valid():
		kw = seform.cleaned_data['Keyword']
		slist = kw.split()
		request.session['Keyword'] = kw
		request.session.set_expiry(300)
		message = 'Searched for (%r),' % kw
	else:
		kw = request.session.get('Keyword')
		if kw:
			message = message = 'Searched for (%r),' % kw
			slist = kw.split()
		else:
			slist = []
			message = 'Your keyword is invalid,'
	q = Q()
	for sub in slist:
		q = q & ( Q(title__icontains=sub) \
		| Q(author__icontains=sub) | Q(abstract__icontains=sub) )
	if slist:
		alist = Article.objects.filter(q).order_by('-journal__year')
	else:
		alist = []
	message = message + ' and returned %d records.' % len(alist)
	plist = []
	for a in alist:
		plist.append(get_one_paper_from_aid(a.id))
	soform = get_sort_form(request)
	process_sort_form(soform,plist)
	template = loader.get_template('mypub/index.html')
	context = RequestContext(request, {'plist': plist, 'msg': message,
		'searchform': seform, 'sortform': soform})
	return HttpResponse(template.render(context))


import datetime as dt
import dateutil.parser
import random

GAME_STEPS = {
    "Starting": 0,
    "Draft": 1,
    "Captain": 2,
    "Running": 3,
    "Close": 4}

PRINT_DATE_FORMAT = r"%d-%m-%Y"

class Person:
    def __init__(self, name, dob, dod=None, WID=None, citizenships=[], genders=[], occupations=[]):
        self.name = name
        self.dob = self._parse_date(dob)
        self.dod = self._parse_date(dod)
        self.WID = WID
        self.citizenships = citizenships
        self.genders = genders
        self.occupations = occupations
        self.is_captain = False
        self.is_first_death = False
        self.score = None

    def __eq__(self, other):
        return self.WID == other.WID

    def __repr__(self):
        string = f"{self.name} ({dt.datetime.strftime(self.dob, PRINT_DATE_FORMAT)}"
        if self.dod:
            string += f" - {dt.datetime.strftime(self.dod, PRINT_DATE_FORMAT)}"
        string += ")"
        return f"Person({string})"

    def __str__(self):
        string = f"{self.name} ({dt.datetime.strftime(self.dob, PRINT_DATE_FORMAT)}"
        if self.dod:
            string += f" - {dt.datetime.strftime(self.dod, PRINT_DATE_FORMAT)}"
        string += ")"
        return string

    def _parse_date(self, date):
        if isinstance(date, dt.datetime):
            return date
        elif isinstance(date, str):
            return dateutil.parser.parse(date)
        return None

    @property
    def age(self):
        if self.dod is not None:
            recent_date = self.dod
        else:
            recent_date = dt.datetime.now()
        return self._calculate_age(self.dob, recent_date)

    def _calculate_age(self, date1, date2):
        years = date2.year - date1.year
        months = date2.month - date1.month
        days = date2.day - date1.day
        if months >= 0 and days >= 0:
            return years + 1
        else:
            return years

    def calculate_score(self):
        basic_score = 100 - self.age

        # Primo sangue
        first = 5 if self.is_first_death else 0

        # Speedy gonzales
        gonzales = 0
        if self.dod is not None and self.dod.month == 1:
            gonzales = 3

        # Zona cesarini
        cesarini = 0
        if self.dod is not None and self.dod.month == 12 and self.dod.day >= 25:
            cesarini = 5

        # 27 club
        club27 = 27 if self.age == 27 else 0

        # Globetrotter
        globetrotter = max(0, 2 * (len(self.citizenships) - 1))

        # Inclusivity
        inclusivity = max(0, 5 * (len(self.genders) - 1))

        # Happy birthday
        birthday = 0
        if self.dod is not None and self.dob is not None and self.dod.month == self.dob.month and self.dod.day == self.dob.day:
            birthday = 10

        # Jack of all trades
        jack = max(0, 2 * (len(self.occupations) - 1))

        total_score = basic_score + first + gonzales + cesarini + club27 + globetrotter + inclusivity + birthday + jack

        if self.is_captain:
            return total_score * 2
        else:
            return total_score

    def add_occupation(self, occupation):
        self.occupations.append(occupation)

    def add_citizienship(self, citizienship):
        self.citizenships.append(citizienship)

    def add_gender(self, gender):
        self.genders.append(gender)

class Team:
    def __init__(self, name="", owner=None, players=[], captain=None):
        self.name = name
        self.owner = owner
        self.players = players
        self.captain = self._set_captain(captain)
        self.score = self._calculate_score()

    def __eq__(self, other):
        return self.owner == other.owner and self.name == other.name

    def _set_captain(self, captain):
        self.captain = None
        for idx, player in enumerate(self.players):
            if captain == player:
                self.captain = captain
                self.players[idx].is_captain = True
            else:
                self.players[idx].is_captain = False

    def _calculate_score(self):
        scores = [p.score if p.dod else 0 for p in self.players]
        self.score = sum(scores)

    def calculate_score(self):
        self._calculate_score()
        return self.score

    def set_captain(self, captain):
        self._set_captain(captain)
        return self.captain

    def has_captain(self):
        if self.captain:
            return True
        else:
            return False

    def add_player(self, player):
        if player in self.players:
            raise ValueError("The player is already part of this team")
        self.players.append(player)

    def update_player(self, player):
        if player not in self.players:
            raise ValueError("The player is not part of this team")
        for p in self.players:
            p.dod = player.dod
            p.citizenships = player.citizenships
            p.genders = player.genders
            p.occupations = player.occupations
            p.is_first_death = player.is_first_death

class Game:
    def __init__(self, teams=[], ban_list={}, team_size=10):
        self.teams = teams
        self.all_players = {'alive': {}, 'dead': {}}
        self.ban_list = ban_list
        self.first_death = None
        self.status = GAME_STEPS["Starting"]
        self.draft_order = []
        self.current_drafter = 0
        self.team_size = team_size

    def update_structure(self):
        if not hasattr(self, "team_size"):
            self.team_size = 10

    def add_team(self, team):
        if team.owner in [t.owner for t in self.teams]:
            raise ValueError(f"There is already a team owned by {team.owner}")
        if team in self.teams:
            raise ValueError("The team is already part of the game!")
        self.teams.append(team)

    def start_draft(self):
        self.draft_order = [t for t in self.teams]
        random.shuffle(self.draft_order)
        self.current_drafter = 0
        self.status = GAME_STEPS["Draft"]

    def next_drafter(self):
        self.current_drafter += 1
        if self.current_drafter >= len(self.draft_order):
            self.current_drafter = 0
            self.draft_order.reverse()
        next_drafter = self.draft_order[self.current_drafter]
        return next_drafter

    def get_current_drafter(self):
        return self.draft_order[self.current_drafter]

    def cancel_draft(self):
        for team in self.teams:
            team.players = []
            team.captain = None
            team.score = 0
        self.status = GAME_STEPS["Starting"]

    def start_game(self):
        self.status = GAME_STEPS["Running"]

    def close_game(self):
        self.status = GAME_STEPS["Close"]

    def start_captain(self):
        self.status = GAME_STEPS["Captain"]

    def get_team_from_owner(self, owner):
        team = [t for t in self.teams if t.owner == owner]
        if team:
            return team[0]
        else:
            return None

    def set_captain(self, team, idx):
        if self.status not in [GAME_STEPS["Draft"], GAME_STEPS["Captain"]]:
            raise ValueError("You have to be in the draft or right after to set a captain")
        try:
            idx_team = self.teams.index(team)
        except ValueError:
            raise ValueError("The team is not part of the game!")

        self.teams[idx_team].set_captain(team.players[idx])

    def rename_team(self, team, name):
        try:
            idx_team = self.teams.index(team)
        except ValueError:
            raise ValueError("The team is not part of the game!")
        self.teams[idx_team].name = name

    def get_team_from_name(self, name):
        return [t for t in self.teams if t.name == name]

    def add_player(self, team, player):
        if self.status != GAME_STEPS["Draft"]:
            raise ValueError("You have to start the draft before adding players")
        try:
            idx = self.teams.index(team)
        except ValueError:
            raise ValueError("The team is not part of the game!")
        if player.dod:
            raise ValueError("The player is already dead :(")
        if player.WID in self.ban_list:
            raise ValueError("The player is in the ban list")
        if player.WID in self.all_players['alive']:
            raise ValueError("The player is already part of a team")
        self.all_players['alive'][player.WID] = player
        self.teams[idx].add_player(player)
        return player

    def update_alive_players(self, updated_players):
        if not self.first_death:
            update_first_death = True
            self.first_death = []
        else:
            update_first_death = False
        for id, player in updated_players.items():
            if id in self.all_players['alive']:
                del self.all_players['alive'][id]
                if update_first_death:
                    player.is_first_death = True
                    self.first_death.append(player)
                self.all_players['dead'][id] = player
                for t in self.teams:
                    if player in t.players:
                        t.update_player(player)

    def update_ban_list(self, ban_list):
        self.ban_list = ban_list

    @property
    def ranking(self):
        return ((t.name, t.score) for t in self.teams)


from azure.functions._http import HttpResponse
from azure.functions.http import HttpRequest
from itsdangerous import URLSafeTimedSerializer
from typing import Any
from urllib.parse import urlparse
from http.cookies import SimpleCookie
import uuid

def parse_request(request: HttpRequest, secret: str, max_age: int, **kwargs) -> dict:
    cookies = SimpleCookie()
    cookies.load(request.headers.get("Cookie", ""))
    try:
        return URLSafeTimedSerializer(secret_key=secret).loads(
            getattr(cookies.get("SessionToken", None), "value", ""),
            max_age=max_age,
        )
    except:
        return {"id": uuid.uuid4().hex}

def _generate_session_cookie(
    session: Any,
    secret: str,
    **kwargs,
) -> SimpleCookie:
    cookies = SimpleCookie()
    cookies["SessionToken"] = URLSafeTimedSerializer(secret_key=secret).dumps(session)
    for key, value in kwargs.items():
        cookies["SessionToken"][key.replace("_", "-")] = value
    return cookies

def alter_response(response: HttpResponse, request: HttpRequest, **kwargs):
    cookies = _generate_session_cookie(
        session=getattr(request, "session", {"id": uuid.uuid4().hex}),
        secret=kwargs["secret"],
        domain=urlparse(request.url).netloc,
        path=kwargs.get("path", "/"),
        max_age=kwargs["max_age"],
        secure=kwargs.get("secure", True),
        httponly=kwargs.get("httponly", False),
    )
    for morsel in cookies.values():
        response.headers.add("Set-Cookie", morsel.OutputString())
    return response


import numpy as np
import matplotlib.pyplot as plt
import math
import random
from HRNN2 import HRNN2
np.random.seed(10000)
np.set_printoptions(threshold=np.nan)

def missmatch(pattern,activation):
    diff = np.abs(pattern-activation)
    return np.sum(np.where(np.sum(diff,axis = 1)>0,0,1))

def add_noise(pattern, amt_of_noise):
    # Calculate the percentages
    amt_of_noise = int(amt_of_noise * 100)
    # Pick out a row vector of indices
    index = np.random.choice(100, amt_of_noise, replace=False)
    # Add some noise to the patterns by flipping the randomly selected units
    pattern[index] = pattern[index] + 1
    return np.copy(pattern)

def main():
    random_data = np.random.randint(1,size=(100,100))
    for i, pattern in enumerate(random_data):
        random_data[i, :] = add_noise(pattern, 0.10)
    correct_classed_patterns = [None] * random_data.shape[0]
    biases = [0, .001, .01, .1, 1, 10]
    for bias in biases:
        for p in range(2, 30):
            selected_patterns = random_data[0:p, :]
            print(selected_patterns)
            Network = HRNN2(selected_patterns)
            output = Network.recall(selected_patterns, 1, True, bias)
            correct_classed_patterns[p-2] = missmatch(Network.activations, np.copy(selected_patterns))
            print(correct_classed_patterns[p-2])
        plt.plot(correct_classed_patterns)
        plt.show()

    # random_data = np.where((np.random.rand(300,100) * 10) - 2.5 >=0,1,-1)
    # print(random_data)
    # random_data = np.where(npv.random.rand(2(300,100))==0,-1,1)
    # print(random_data)
#     for p in range(2,random_data.shape[0]):
#         selected_patterns = random_data[0:p, :]
#         # Initialize the Hopfield RNN with three selected patterns from the pict dataset
#         Network = HRNN2(selected_patterns)
#         new_selected_patterns = add_noise(np.copy(selected_patterns), 0.0)
#         epochs = 1 #int(math.log2(len(selected_patterns)))
#         # Initialize a subplot object
#         Network.recall(np.copy(new_selected_patterns[0:p, :]), epochs, True)
#         correct_classed_patterns[p-2] = missmatch(Network.activations, np.copy(selected_patterns))
#
main()


import pygame

pygame.init()
    #screen
screen = pygame.display.set_mode((700,700))
    #colors
RED = (255, 0, 0)
WHITE = (255, 255, 255)
    #variables
x = 350
y = 350
step = 20
radius = 25
clock = pygame.time.Clock()
    #events
done = False
while not done:
    for event in pygame.event.get():
            if event.type == pygame.QUIT:
                    done = True
    #keyboards
    pressed = pygame.key.get_pressed()
    if pressed[pygame.K_UP]:
        if y - step >= 25:
            y -= step
        else:
            y = 25
    elif pressed[pygame.K_DOWN]:
        if y + step <= 675:
            y += step
        else:
            y = 675
    elif pressed[pygame.K_LEFT]:
        if x - step >= 25:
            x -= step
        else:
            x = 25
    elif pressed[pygame.K_RIGHT]:
        if x + step <= 675:
            x += step
        else:
            x = 675
    screen.fill(WHITE)
    pygame.draw.circle(screen, RED, (x,y), radius) #ball

    pygame.display.flip()
    clock.tick(60) #FPS = frame per second(kak v igrah)


import bpy

projectname = bpy.path.display_name_from_filepath(bpy.data.filepath)

folderpath = "//render/" + projectname + "/"

scene = bpy.data.scenes["Scene"]

print("Rendering spritesheets for", projectname)

# copy since we modify this list mid iteration
render_objects = [bpy.data.objects.get("Root")]

i = 0

while i < len(render_objects):

    obj = render_objects[i]

    i = i + 1

    for obj_child in obj.children:
        render_objects.append(obj_child)

# Hide all objects
for obj in render_objects:
    obj.hide_render = True

# Unhide, render and hide again
for obj in render_objects:

    if obj.type != "MESH":
        continue

    obj.hide_render = False

    # Move object to origin
    location_backup = obj.location.copy()
    rotation_backup = obj.rotation_euler.copy()
    obj.location = [0,0,0]
    obj.rotation_euler = [0,0,0]

    print("Rendering part:", obj.name)

    for frame_current in range(scene.frame_start,scene.frame_end):

        filepath = folderpath + projectname + "_" + obj.name + "_" + str(frame_current) + ".png"

        scene.frame_current = frame_current

        bpy.context.scene.render.filepath = filepath

        bpy.ops.render.render(write_still=True)

    obj.hide_render = True

    obj.location = location_backup
    obj.rotation_euler = rotation_backup

scene.frame_current = scene.frame_start

print("Finished.")


from django.urls import path

from . import views

app_name = 'quotes_divination'

urlpatterns = [
    path('', views.CategoryListView.as_view(), name='category_quotes_list'),
    path('<slug:slug>/', views.RandomQuoteView.as_view(), name='random_quote'),
]


#!/usr/bin/env python

import json
import easypg
import operator
import re
import sys,traceback
from functools import cmp_to_key
from shutil import copyfile
import locale
import os
import argparse

# parser = argparse.ArgumentParser(description='Process subset of openlibrary.org "sample" data.')
# parser.add_argument('easypg config file', metavar='F', type=str, nargs='?', default='bookserver_import',
#                    help='file containing database connection information')
# parser.add_argument('limit amount imported', metavar='F', type=str, nargs='?', default='bookserver_import',
#                    help='file containing database connection information')
# parser.add_argument('--sum', dest='accumulate', action='store_const',
#                    const=sum, default=max,
#                    help='sum the integers (default: find the max)')

easypg.config_name = 'bookserver_import'

# Count the occurrences of any given key for a dataset
author_keys = {'name_too_long':0}
work_keys = {'title_too_long':0}
book_keys = {'title_too_long':0}

# Parse smaller chunks of data during some troubleshooting
# IS_LOOP_LIMIT = True
IS_LOOP_LIMIT = False
LOOP_LIMIT = 50
loop_counter = 0

LOGGING = True

log_file = open('data/sample-data/logs/load-template.log', 'w')
error_log = open('data/sample-data/logs/load-template-errors.log', 'w')

author_ids = {}
work_ids = {}
subject_ids = {}

# covers mapped to book_core.core_id for potential later use
work_covers = {}

def print_log_entry(log_file, message):
  if LOGGING:
    try:
        print >> log_file, message.encode('ascii', 'xmlcharrefreplace')
    except:
        e = sys.exc_info()[0]
        traceback.print_exc(file=error_log)
        print >> log_file, "Big time error! %s" % e

def print_key_occurrences(heading, output, sorted_keys):
    max_occurrences = sorted_keys[0][1]
    display_cutoff = max_occurrences / 2
    print >> output, "####%s Occurrences (>%s)" % (heading,display_cutoff)
    print >> output, "| Key | # | Mapping |"
    print >> output, "| ---- | ---- | ---- |"
    for x in sorted_keys:
        if x[1] > display_cutoff:
            print >> output, "| %s | %s |" % (x[0], x[1])
    print >> output, "\n"

    print >> output, "####%s Occurrences (all)" % (heading)
    print >> output, "| Key | # | Mapping |"
    print >> output, "| ---- | ---- | ---- |"
    for x in sorted_keys:
        print >> output, "| %s | %s |" % (x[0], x[1])
    print >> output, "\n"

# there are a lost of cover archives, check which one we need with out subset
def retrieve_cover_dump_names():
    # try:
    with open('data/sample-data/logs/cover_ids.json') as covers_file:
        download_list = open('data/sample-data/covers/archives/download_list.tmp', 'w')
        covers = json.load(covers_file)

        needed_files = []
        for book_id, cover in covers.iteritems():
            cover = str(cover[0])
            if len(cover) > 6:
                first_subset = "000%s" % cover[:1]
            else:
                first_subset = "0000"
            if len(cover) > 4:
                second_subset = "%s" % cover[1:3]
            else:
                second_subset = "00"
            # print "cover:%s -- first:%s -- second:%s" % (cover, first_subset, second_subset)
            needed_files.append( "_covers_%s_%s" % (first_subset,second_subset))
        needed_files_sorted = sorted(needed_files, key=cmp_to_key(locale.strcoll))
        for unique_file in set(needed_files_sorted):
            # print unique_file
            print >> download_list, "https://archive.org/download/s%s/s%s.tar" % (unique_file[:-3], unique_file)
        download_list.close()
    # except:
    #     e = sys.exc_info()[0]
    #     traceback.print_exc(file=error_log)
    #     print  "Big time error! %s" % e

def import_cover_dump(cover_size='s'):
    folder_names = {'s': 'small', 'm': 'medium'}
    if not os.path.exists("static/images/covers/"+folder_names[cover_size]):
        os.makedirs("static/images/covers/"+folder_names[cover_size])
    with open('data/sample-data/logs/cover_ids.json') as covers_file:
        covers = json.load(covers_file)
        loop_counter = 0
        download_list = open('data/sample-data/covers/'+folder_names[cover_size]+'_import_download_list.tmp', 'w')
        missing_files = open('data/sample-data/covers/'+folder_names[cover_size]+'_import_missing_file_list.tmp', 'w')
        log_file = open('data/sample-data/covers/'+folder_names[cover_size]+'_import_cover_dump.log', 'w')
        needed_files = []
        for book_id, cover in covers.iteritems():

            if IS_LOOP_LIMIT and (loop_counter > LOOP_LIMIT):
              break
            loop_counter += 1

            cover = str(cover[0])
            filename = cover.zfill(10)+"-"+cover_size.upper()+".jpg"
            # print cover
            if len(cover) > 5:
                first_subset = "000%s" % cover[:1]
            else:
                first_subset = "0000"
            if len(cover) > 4:
                second_subset = "%s" % cover[1:3]
            else:
                second_subset = "00"
            directory = cover_size+"_covers_%s_%s" % (first_subset,second_subset)
            # directory = "cover:%s -- first:%s -- second:%s" % (cover, first_subset, second_subset)
            with easypg.cursor() as cur:

                try:
                    # print "data/sample-data/covers/archives/extracted_small_covers/"+directory+"/"+filename
                    # print os.path.isfile("data/sample-data/covers/archives/extracted_small_covers/"+directory+"/"+filename)
                    # print "-------------"
                    if os.path.isfile("data/sample-data/covers/archives/extracted_"+folder_names[cover_size]+"_covers/"+directory+"/"+filename):
                        cur.execute('''
                          UPDATE books SET cover_name = %s
                          WHERE core_id = %s
                        ''', ("_covers_%s_%s/%s" % (first_subset,second_subset,cover.zfill(10)), book_id))
                        print >> log_file, "Inserting cover %s into book with core_id %s..." % (cover, book_id)
                        print >> log_file, "Moving %s to %s..." % ("data/sample-data/covers/archives/extracted_"+folder_names[cover_size]+"_covers/"+directory+"/"+filename, "static/images/covers/"+filename)
                        if not os.path.exists("static/images/covers/"+folder_names[cover_size]+"/"+directory):
                            os.makedirs("static/images/covers/"+folder_names[cover_size]+"/"+directory)
                        if not os.path.isfile("static/images/covers/"+folder_names[cover_size]+"/"+directory+"/"+filename):
                            copyfile("data/sample-data/covers/archives/extracted_"+folder_names[cover_size]+"_covers/"+directory+"/"+filename, "static/images/covers/"+folder_names[cover_size]+"/"+directory+"/"+filename)
                    else:
                        print >> missing_files, "Unable to find: %s..." % cover
                        needed_files.append( "_covers_%s_%s" % (first_subset,second_subset))
                except IOError:
                    print >> missing_files, "IOError: Unable to find: %s..." % cover
                    needed_files.append( "_covers_%s_%s" % (first_subset,second_subset))
                except:
                    e = sys.exc_info()[0]
                    traceback.print_exc(file=sys.stdout)
                    print >> log_file, "Big time error! %s" % e
        needed_files_sorted = sorted(needed_files, key=cmp_to_key(locale.strcoll))
        for unique_file in set(needed_files_sorted):
            # print unique_file
            print >> download_list, "https://archive.org/download/%s%s/%s%s.tar" % (cover_size, unique_file[:-3], cover_size, unique_file)
        download_list.close()
        missing_files.close()
        log_file.close()
        # if cur.rowcount == 1:

def generate_requests():
    with easypg.cursor() as cur:
        cur.execute('''
            SELECT book_id, is_active FROM book;
        ''')
        for book_id, is_active in cur:
            with easypg.cursor() as loop_cur:
                loop_cur.execute('''
                    INSERT INTO request (user_id, type, date_requested, priority, status, date_of_status)
                    VALUES(%s, %s, NOW(), %s, %s, NOW())
                    RETURNING request_id
                ''', (1, "Add Book", '1', "Approved"))
                request_id = loop_cur.fetchone()[0]

                loop_cur.execute('''
                    INSERT INTO request_on_book (request_id, book_id, request_type, request_text)
                    VALUES(%s, %s, %s, %s)
                    RETURNING request_on_book_id
                ''', (request_id, book_id, "Add Book", "load-template.py insertion"))
                request_on_book_id = loop_cur.fetchone()[0]

def import_all():
    try:
        with open('data/sample-data/authors.json') as af:
            loop_counter = 0
            for line in af:
                # break
                if IS_LOOP_LIMIT and (loop_counter > LOOP_LIMIT):
                  break
                loop_counter += 1
                author = json.loads(line.strip())
                author_key = author['key']
                for key in author:
                    try:
                        author_keys[key.strip()] += 1
                        # if isinstance(val, dict):
                        #     for inner_key in val:
                        #         try:
                        #             author_keys[key.strip()+"_"+inner_key] += 1
                        #         except KeyError:
                        #             author_keys[key.strip()+"_"+inner_key] = 1

                    except KeyError:
                        author_keys[key.strip()] = 1
                # print 'found author', author_key
                # put the author in your database
                with easypg.cursor() as cur:
                    # first clean up book title
                    try:
                        author['name'] = author['name'].strip()
                    except KeyError:
                        print_log_entry(error_log,"No name for this author entry (%s) ! Continuing..." % loop_counter)
                        continue

                    if len(author['name']) > 255:
                        print_log_entry(error_log,"This author's name (%s) is too long, not importing it for the moment! Continuing..." % author['name'])
                        author_keys['name_too_long'] += 1
                        continue
                    try:
                        author['personal_name'] = author['personal_name'].strip()
                        if len(author['personal_name']) > 255:
                            print_log_entry(error_log,"This author's personal_name (%s) is too long, not importing it for the moment! Continuing..." % author['key'])
                            continue
                    except KeyError:
                        author['personal_name'] = ''
                    # now check to see if we have an existing "author" entry

                    # print "Inserting author name  %s along with key %s." % (author['name'], author['key'])
                    cur.execute('''
                      INSERT INTO author (author_name, author_alias)
                      VALUES(%s, %s)
                      RETURNING author_id
                    ''', (author['name'], author['personal_name']))
                    if cur.rowcount == 1:
                        author_ids[author['key']] = cur.fetchone()[0]
                        print_log_entry(log_file,"Inserted author name  %s along with alias %s, represented by author_id: %s." % (author['name'], author['personal_name'], author_ids[author['key']]))

        book_covers = open('data/sample-data/logs/cover_ids.json', 'w')
        with open('data/sample-data/works.json') as af:

            loop_counter = 0
            for line in af:
                if IS_LOOP_LIMIT and (loop_counter > LOOP_LIMIT):
                    break
                loop_counter += 1
                work = json.loads(line.strip())
                work_key = work['key']
                #print 'found work', work_key
                # put the work in your database
                for key in work:
                    try:
                        work_keys[key.strip()] += 1
                        # if isinstance(val, dict):
                        #     for inner_key in val:
                        #         try:
                        #             work_keys[key.strip()+"_"+inner_key] += 1
                        #         except KeyError:
                        #             work_keys[key.strip()+"_"+inner_key] = 1

                    except KeyError:
                        work_keys[key.strip()] = 1

                with easypg.cursor() as cur:
                    try:
                        work['title'] = work['title'].strip()
                        if len(work['title']) > 250:
                            work_keys['title_too_long'] += 1
                            print_log_entry(error_log,"Work import: This work's title (%s) is too long, not importing it for the moment! Continuing..." % work['title'])
                            continue
                    except KeyError:
                        print_log_entry(error_log,"Work import: No title for this work (%s)! Continuing..." % loop_counter)
                        continue

                    try:
                        work['description'] = work['description'].strip()
                    except KeyError:
                        work['description'] = ""
                    except AttributeError:
                        # print to error log later.
                        work['description'] = ""
                        print_log_entry(error_log,"Work import: Can't use description, AttributeError (%s)." % loop_counter)
                        pass

                    # now check to see if we have an existing "book_core" entry
                    #print "Checking to see if a book core entry exists for %s..." % works['title']
                    cur.execute('''
                        SELECT core_id
                        FROM book_core
                        WHERE book_title = %s
                    ''', (work['title'],))

                    if cur.rowcount != 1:
                        print_log_entry(log_file,"Work import: No book core entry found, adding one now...")
                        #too many, or no, matching book_core entries found -> make a new one
                        print_log_entry(log_file,"Work import: Inserting work / book core: %s :: %s." % (work['title'], loop_counter))
                        cur.execute('''
                          INSERT INTO book_core (book_title, book_description, edition)
                          VALUES(%s, %s, %s)
                          RETURNING core_id
                        ''', (work['title'], work['description'], 1))

                    # Retrieve book_core_id for book insertion
                    book_core_id = cur.fetchone()[0]
                    work_ids[work_key] = book_core_id
                    # map to book_tag
                    # e.g., "subjects": ["Environmental aspects", "Environmental aspects of Forest fires", "Forest Hydrology",
                    # "Forest fires", "Hydrology, Forest", "Streamflow", "Forest hydrology"]
                    # work['subjects']

                    # locations related to work/book?
                    # e.g.,  "subject_places": ["Black Hills (S.D. and Wyo.)", "Custer State Park",
                    # "Custer State Park (S.D.)", "Custer State Park Region", "South Dakota"]
                    # work['subject_places']
                    # print "Work['covers']: %s" % work['covers']
                    try:
                      for cover in work['covers']:
                        try:
                          work_covers[book_core_id].append(cover)
                        except:
                          work_covers[book_core_id] = []
                          work_covers[book_core_id].append(cover)
                    except KeyError:
                        # No covers here
                        print_log_entry(error_log,"Work import: No covers found for %s" % loop_counter)
                        pass

                    # add author relationships if found
                    try:
                        position = 1
                        for author in work['authors']:
                            author = author[key]
                            # if re.match("\('(.*)'[,]*\)", author):
                            #     m = re.match("\('(.*)'[,]*\)", author)
                            #     author = m.groups()[0]
                            try:
                                print_log_entry(log_file,author)
                                author_id = author_ids[author]
                                cur.execute('''
                                INSERT INTO authorship (core_id, author_id, position)
                                VALUES(%s, %s, %s)
                                RETURNING author_id
                                ''', (book_core_id, author_id, position))
                                position += 1
                            except KeyError:
                                print_log_entry(error_log,"Work import: Couldn't find an author_id entry for author key: %s..." % author)
                    except KeyError:
                        print_log_entry(error_log,"Work import: No authors found (%s)!" % loop_counter)

        json.dump(work_covers, book_covers)
        book_covers.close()

        with open('data/sample-data/books.json') as af:
            loop_counter = 0
            for line in af:
                if IS_LOOP_LIMIT and (loop_counter > LOOP_LIMIT):
                    break
                loop_counter += 1
                book = json.loads(line.strip())
                book_key = book['key']
                for key in book:
                    try:
                        book_keys[key.strip()] += 1
                        # if isinstance(val, dict):
                        #     for inner_key in val:
                        #         try:
                        #             book_keys[key.strip()+"_"+inner_key] += 1
                        #         except KeyError:
                        #             book_keys[key.strip()+"_"+inner_key] = 1

                    except KeyError:
                        book_keys[key.strip()] = 1
                # print 'found book', book_key
                # print book
                # put the book in your database
                with easypg.cursor() as cur:
                    # first clean up book title
                    try:
                        book['title'] = book['title'].strip()
                    except KeyError:
                        # should be output to error log
                        print_log_entry(error_log,"Book import: No title for this book entry (%s) ! Continuing..." % loop_counter)
                        continue

                    if len(book['title']) > 250:
                        # log this latter
                        book_keys['title_too_long'] += 1
                        print_log_entry(error_log,"Book import: This book's title (%s) is too long, not importing it for the moment! Continuing..." % book['title'])
                        continue

                    # now check to see if we have an existing "book_core" entry
                    print_log_entry(log_file,"Book import: Checking to see if a book core entry exists for %s..." % book['title'])
                    try:
                        book_core_id = work_ids[book['work']]
                        print_log_entry(log_file,"Book import: Book core ID obtained: %s!" % book_core_id)
                    except KeyError:

                        # cur.execute('''
                        #     SELECT core_id
                        #     FROM book_core
                        #     WHERE book_title = %s
                        # ''', (book['title'],))

                        # if (cur.rowcount != 1):
                        print_log_entry(error_log,"Book import: No book core entry found (work_ids[%s]), adding one now..." % book['work'])
                        #too many, or no, matching book_core entries found -> make a new one
                        cur.execute('''
                          INSERT INTO book_core (book_title, book_description, edition)
                          VALUES(%s, %s, %s)
                          RETURNING core_id
                        ''', (book['title'], '', book['revision']))

                        # Retrieve book_core_id for book insertion
                        book_core_id = cur.fetchone()[0]

                    # check to see what type of ISBN we have to work with, go with ISBN if possible
                    # explanation of this type of structure at: http://stackoverflow.com/a/1592578/1431509
                    try:
                        book['isbn_13']
                    except KeyError:
                        try:
                            book['isbn_10']
                        except KeyError:
                            print_log_entry(error_log,"Book import: %s has no ISBN!" % book['title'])
                            book_isbn = []
                        else:
                            book_isbn = book['isbn_10']
                    else:
                        book_isbn = book['isbn_13']

                    try:
                        book['number_of_pages']
                    except KeyError:
                        page_count = None
                        print_log_entry(error_log,"Book import: %s has no page count!" % book['title'])
                    else:
                        page_count = book['number_of_pages']

                    try:
                        book['physical_format']
                    except KeyError:
                        book_type = None
                    else:
                        book_type = book['physical_format']

                    try:
                        print_log_entry(log_file,"Book import: Publish date is: %s." % book['publish_date'])
                        original_date = book['publish_date']
                    except KeyError:
                        print_log_entry(error_log,"Book import: %s has no publication date!" % book['title'])
                        publication_date = None
                        original_date = None
                    except UnicodeEncodeError:
                        print_log_entry(error_log,"Book import: UnicodeEncodeError for publish_date (%s)?" % loop_counter)
                        pass
                    else:
                        if re.match('\w* \d{1,2}, \d{4}', book['publish_date']):
                            m = re.match('(\w* \d{1,2}, \d{4})', book['publish_date'])
                            publication_date = m.groups()[0]
                        elif re.match('\w* \d{4}', book['publish_date']):
                            m = re.match('(\w*) (\d{4})', book['publish_date'])
                            publication_date = "%s 01, %s" % (m.groups()[0], m.groups()[1])
                        elif re.match('\d{4}', book['publish_date']):
                            m = re.match('(\d{4})', book['publish_date'])
                            publication_date = "January 01, %s" % m.groups()[0]
                        else :
                            publication_date = None
                    print_log_entry(log_file,"Book import: Parsed publication_date is: %s (Original date: %s)." % (publication_date, original_date))
                    # was getting output in this formatting "[u'9780110827667']" slicing off the excess
                    # until I find whats going on
                    # book_isbn = book_isbn[2:-2]
                    for isbn in book_isbn:
                        try:
                            isbn = ''.join(x for x in isbn if x.isdigit())
                            print_log_entry(log_file,"Book import: Inserting book title %s along with core_id %s (ISBN: %s - Date: %s)." % (book['title'], book_core_id, isbn, publication_date))
                            cur.execute('''
                                INSERT INTO books (core_id, publication_date, isbn, book_type, page_count)
                                VALUES(%s, %s, %s, %s, %s)
                                RETURNING book_id
                            ''', (book_core_id, publication_date, isbn, book_type, page_count))
                            book_id = cur.fetchone()[0]
                        except:
                            e = sys.exc_info()[0]
                            traceback.print_exc(file=error_log)
                            print_log_entry(error_log,"Big time error! %s" % e)
                        # add publisher relationships if found

                        try:
                            position = 1
                            for publisher in book['publishers']:
                                if len(publisher) > 250:
                                    # log this latter
                                    print_log_entry(error_log,"Book import: This book's publisher (%s) is too long, not importing it for the moment! Continuing..." % publisher)
                                    continue
                                print_log_entry(log_file,"Book import: Checking to see if a publisher entry exists for %s..." % publisher)
                                cur.execute('''
                                    SELECT publicist_id
                                    FROM publicist
                                    WHERE publicist_name = %s
                                ''', (publisher,))

                                if cur.rowcount != 1:
                                    print_log_entry(log_file,"Book import: No publisher entry found, adding one now(%s)..." % loop_counter)
                                    print_log_entry(log_file,"Book import: Inserting publisher: %s :: %s." % (publisher, loop_counter))
                                    cur.execute('''
                                      INSERT INTO publicist (publicist_name)
                                      VALUES(%s)
                                      RETURNING publicist_id
                                    ''', (publisher,))

                                publicist_id = cur.fetchone()[0]
                                cur.execute('''
                                  INSERT INTO book_publication (book_id, publicist_id, position)
                                  VALUES(%s, %s,%s)
                                ''', (book_id,publicist_id,position))
                                position += 1
                        except KeyError:
                            print_log_entry(error_log,"Book import: KeyError importing publisher(s) for (%s)!" % loop_counter)

                    try:
                        for subject in book['subjects']:
                            subject = subject.strip()
                            # if re.match("\('(.*)'[,]*\)", subject):
                            #     m = re.match("\('(.*)'[,]*\)", subject)
                            #     subject = m.groups()[0]

                            #print "Checking to see if a subject entry exists for %s..." % tag
                            cur.execute('''
                                SELECT subject_id
                                FROM subject_genre
                                WHERE subject_name = %s
                            ''', (subject,))

                            if cur.rowcount != 1:
                                print_log_entry(log_file,"Book import: No subject entry found, adding one now(%s)..." % loop_counter)
                                #too many, or no, matching book_core entries found -> make a new one
                                print_log_entry(log_file,"Book import: Inserting subject: %s :: %s." % (subject, loop_counter))
                                cur.execute('''
                                  INSERT INTO subject_genre (subject_name)
                                  VALUES(%s)
                                  RETURNING subject_id
                                ''', (subject,))

                            # Retrieve book_core_id for book insertion
                            subject_id = cur.fetchone()[0]

                            cur.execute('''
                              INSERT INTO book_categorization (core_id, subject_id)
                              VALUES(%s, %s)
                            ''', (book_core_id,subject_id))
                    except KeyError:
                        print_log_entry(error_log,"Book import: Unable to access book['subjects'] for tag creation (%s)..." % loop_counter)

                    # add author relationships if found
                    position = 1
                    try:
                        for author in book['authors']:
                            # if re.match("\('(.*)'[,]*\)", author):
                            #     m = re.match("\('(.*)'[,]*\)", author)
                            #     author = m.groups()[0]

                            try:
                                author_id = author_ids[author]
                                cur.execute('''
                                INSERT INTO authorship (core_id, author_id, position)
                                VALUES(%s, %s, %s)
                                RETURNING author_id
                                ''', (book_core_id, author_id, position))
                                position += 1
                            except KeyError:
                                print_log_entry(error_log,"Book import: KeyError: Couldn't find an author_id entry for author key: %s..." % author)
                            except TypeError:
                                print_log_entry(error_log,"Book import: TypeError: Couldn't find an author_id entry for author key: %s..." % author)
                    except KeyError:
                        print_log_entry(error_log,"Book import: No authors found!")
    except:
        e = sys.exc_info()[0]
        print_log_entry(error_log,"Big time error! %s" % e)
        traceback.print_exc(file=error_log)

    sorted_author_keys = sorted(author_keys.items(), key=operator.itemgetter(1), reverse=True)
    sorted_work_keys = sorted(work_keys.items(), key=operator.itemgetter(1), reverse=True)
    sorted_book_keys = sorted(book_keys.items(), key=operator.itemgetter(1), reverse=True)

    markdown_file = open('data/sample-data/logs/load-template-results.md', 'w')
    print_key_occurrences("Author Keys", markdown_file, sorted_author_keys)
    print_key_occurrences("Work Keys", markdown_file, sorted_work_keys)
    print_key_occurrences("Book Keys", markdown_file, sorted_book_keys)
    markdown_file.close()

# retrieve_cover_dump_names()
# import_all()
# retrieve_cover_dump_names()
# import_cover_dump('m')
generate_requests()

log_file.close()
error_log.close()


#!/usr/bin/env python3
# -*- coding: utf-8 -*-

"""
Screen Stocks
Type: Tool
Auther: Arda
"""
# Public modules
from bs4 import BeautifulSoup
import pandas as pd
import time

# My modules
import basiccrawlmethod as bcmethod
import permit2trade as p2t
import techanalysis as ta
import parmsetting as parm

# Return stocks whose amplitude is above 5%
# and match the Price & Volume conditions.
def amplitudefilter():
    AmpFilterResult = []
    for i in range(1, 92):
            urlAmp = 'https://histock.tw/stock/rank.aspx?&m=7&p=' + str(i) + '&d=1'
            soup = BeautifulSoup(bcmethod.htmlgetter().geturl(urlAmp), 'html.parser')
            Data1 = soup.find_all('table', {'class':'gvTB'})
            if len(Data1) > 0:
                Data2 = Data1[0].find_all('tr')
                for j in range(1, len(Data2)):
                    Data3 = Data2[j].find_all('td')
                    stockNum = Data3[0].text
                    stockName = Data3[1].a.text
                    stockPrice = float(Data3[2].text)
                    stockAmp = bcmethod.numtrans().strtonum(Data3[7].text)
                    stockVol = bcmethod.numtrans().strtonum(Data3[11].text)/1000.0

                    if stockAmp >= 2.0:
                        if len(stockNum) == 4:
                            if stockPrice >= 10.0 and stockPrice <= 35.0 and stockVol >= 10000:
                                AmpFilterResult.append([stockNum, stockName, stockPrice,
                                                        str(stockAmp) + '%', stockVol])
                            elif stockPrice >= 50.0 and stockPrice <= 68.0 and stockVol >= 8000:
                                AmpFilterResult.append([stockNum, stockName, stockPrice,
                                                        str(stockAmp) + '%', stockVol])
                            elif stockPrice >= 100.0 and stockPrice <= 408.0 and stockVol >= 6000:
                                AmpFilterResult.append([stockNum, stockName, stockPrice,
                                                        str(stockAmp) + '%', stockVol])
                            elif stockPrice >= 500.0 and stockVol >= 4000:
                                AmpFilterResult.append([stockNum, stockName, stockPrice,
                                                        str(stockAmp) + '%', stockVol])
                    else:
                        return AmpFilterResult

            else:
                return AmpFilterResult

def main():
    closeDay = input("Stock close day(yyyymmdd): ")
    tradeDay = input("Trade day(yyyymmdd): ")

    print('Searching.', end='')
    StockCandidate = amplitudefilter()
    print('..', end='')

    #StockCandidate = p2t.permission().sbmsbellowpar(StockCandidate, date)
    StockCandidate = p2t.permission().daytradeable(StockCandidate, tradeDay)
    print('..', end='')

    AfterRSICandidate = []
    for stock in StockCandidate:
        rsi = ta.techmethod().rsi(stock[0], closeDay, 5)
        if rsi < 99.99 and rsi > 0.01:
            stock.append(str(rsi)+'%')
            AfterRSICandidate.append(stock)
    print('..', end='')

    for stock in AfterRSICandidate:
        maParm = parm.getparm().maparm(stock[0], closeDay)
        stock.append(maParm)
        if maParm[0] < 1.20:
            stock[-1].append('Bear Only')
        elif maParm[1] < 1.20:
            stock[-1].append('Bull Only')
        else:
            stock[-1].append('Bull&Bear')

        stock.append(parm.getparm().bbandsparm(stock[0], float(stock[3][0:-1]), closeDay))
        time.sleep(5)
    print('...')

    BearCandidate = []
    for stock in AfterRSICandidate:
        if stock[6][2] == 'Bear Only':
            BearCandidate.append(stock)
    print('Filtering.....', end='')

    BearCandidate = p2t.permission().cansellb4buy(BearCandidate, tradeDay)

    DayTradeCandidate = []
    for stock in AfterRSICandidate:
        if stock[6][2] != 'Bear Only' or stock in BearCandidate:
            DayTradeCandidate.append(stock)

    (Number, Name, Price, Amplitude, Volume, MeanPrice, RSI, MA_top_parm, MA_buttom_parm,
    Trend, BBand_parm, BBand_wide) = ([], [], [], [], [], [], [], [], [], [], [], [])
    for stock in DayTradeCandidate:
        Number.append(stock[0])
        Name.append(stock[1])
        Price.append(stock[2])
        Amplitude.append(stock[3])
        Volume.append(stock[4])
        MeanPrice.append(stock[7][0])
        RSI.append(stock[5])
        MA_top_parm.append(stock[6][0])
        MA_buttom_parm.append(stock[6][1])
        Trend.append(stock[6][2])
        BBand_parm.append(stock[7][1])
        BBand_wide.append(stock[7][2])
    print('.....')

    CanDataFrame = {
                    'Number' : Number,
                    'Name' : Name,
                    'Price' : Price,
                    'Amplitude' : Amplitude,
                    'Volume' : Volume,
                    'MeanPrice' : MeanPrice,
                    'RSI' : RSI,
                    'MA_top_parm' : MA_top_parm,
                    'MA_buttom_parm' : MA_buttom_parm,
                    'Trend' : Trend,
                    'BBand_parm' : BBand_parm,
                    'BBand_wide' : BBand_wide
                   }
    CanColumns = ['Number', 'Name', 'Price', 'Amplitude', 'Volume', 'MeanPrice','RSI',
                  'MA_top_parm', 'MA_buttom_parm', 'Trend', 'BBand_parm', 'BBand_wide']
    print('Writing...', end='')

    Candidate = pd.DataFrame(CanDataFrame, columns = CanColumns)
    print('.....', end='')
    Candidate.to_csv('Candidate' + tradeDay + '.csv', index=0, encoding='big5')
    print('....')
    print('Finish')

if __name__ == '__main__':
    main()


#!/usr/bin/env python

import os
import sys
import Queue
import threading
import hashlib
import tarfile
from multiprocessing import Pool
from functools import partial
from subprocess import call

THREADS = 8

def pack_and_send(output_path, path):
    md5 = hashlib.md5()
    md5.update(path)
    tarname = md5.hexdigest()[:10] + '.tar'
    print(tarname)
    tarpath = output_path + '/' + tarname, "w"
    tar = tarfile.open(tarpath)
    tar.add(path)
    tar.close()
    call("scp %s hadoop.vls:/mnt/tmp/pszostek_pubmed" % tarpath)
    print(tarpath)

if __name__ == "__main__":
    if len(sys.argv) != 3:
        print("Usage: " + sys.argv[0] + " input_path output_path")
        exit(1)

    path = sys.argv[1]
    prefixes = ["%02x" % x for x in xrange(0,256)]
    paths = [path + '/' + prefix for prefix in prefixes]
    output_path = sys.argv[2]

    if not os.path.exists(output_path):
        os.makedirs(output_path)

    pool = Pool(processes=8)
    pool.map(partial(pack_and_send, output_path=output_path), paths)


import torchvision.transforms as transforms
from face_modules.model import Backbone
from face_modules.mtcnn import *
import PIL.Image as Image
from network.aei import *
import numpy as np
import torch
import time
import cv2

def swap_faces(Xs_raw, Xt_raw):
    detector = MTCNN()
    device = torch.device('cpu')
    G = AEI_Net(c_id=512)
    G.eval()
    G.load_state_dict(torch.load('./saved_models/G_latest.pth', map_location=device))
    G = G.cpu()

    arcface = Backbone(50, 0.6, 'ir_se').to(device)
    arcface.eval()
    arcface.load_state_dict(torch.load('./saved_models/model_ir_se50.pth', map_location=device), strict=False)

    test_transform = transforms.Compose([
        transforms.ToTensor(),
        transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))
    ])

    Xs_img = Image.fromarray(Xs_raw)
    Xs = detector.align(Xs_img, crop_size=(64, 64))

    Xs = test_transform(Xs)
    Xs = Xs.unsqueeze(0).cpu()
    with torch.no_grad():
        embeds, Xs_feats = arcface(F.interpolate(Xs, (112, 112), mode='bilinear', align_corners=True))
        embeds = embeds.mean(dim=0, keepdim=True)

    mask = np.zeros([64, 64], dtype=np.float)
    for i in range(64):
        for j in range(64):
            dist = np.sqrt((i-32)**2 + (j-32)**2)/32
            dist = np.minimum(dist, 1)
            mask[i, j] = 1-dist
    mask = cv2.dilate(mask, None, iterations=20)

    Xt_img = Image.fromarray(Xt_raw)

    Xt, trans_inv = detector.align(Xt_img, crop_size=(64, 64), return_trans_inv=True)

    Xt = test_transform(Xt)

    Xt = Xt.unsqueeze(0).cpu()
    with torch.no_grad():
        st = time.time()
        Yt, _ = G(Xt, embeds)
        Yt = Yt.squeeze().detach().cpu().numpy()
        st = time.time() - st
        print(f'inference time: {st} sec')
        Yt = Yt.transpose([1, 2, 0])*0.5 + 0.5
        Yt_trans_inv = cv2.warpAffine(Yt, trans_inv, (np.size(Xt_raw, 1), np.size(Xt_raw, 0)), borderMode=cv2.BORDER_TRANSPARENT)
        mask_ = cv2.warpAffine(mask, trans_inv, (np.size(Xt_raw, 1), np.size(Xt_raw, 0)), borderMode=cv2.BORDER_TRANSPARENT)
        mask_ = np.expand_dims(mask_, 2)
        Yt_trans_inv = mask_*Yt_trans_inv + (1-mask_)*(Xt_raw.astype(np.float)/255.)

        merge = Yt_trans_inv

        return merge


__version__ = "0.3"

import sys, math, random, copy
from lxml import etree
import inkex
from inkex import Path, CubicSuperPath, Color
from inkex.command import inkscape

def dirtyFormat(path):
    return str(path).replace('[','').replace(']','').replace(',','').replace('\'','')

def randomize(x_y, radius, norm=True, absolute=False):
    """ return x,y moved by a random amount inside a radius.
        use uniform distribution unless
         - norm = True - then use a normal distribution
        If absolute is true - ensure random is only added to x,y  """
    # if norm:
        # r = abs(random.normalvariate(0.0,0.5*radius))
    # else:
        # r = random.uniform(0.0,radius)
    x, y = x_y
    a = random.uniform(0.0,2*math.pi)
    x += math.cos(a)*radius
    y += math.sin(a)*radius
    if absolute:
        x = abs(x)
        y = abs(y)
    return [x, y]

def add_rounded_rectangle(startx, starty, radius, width, height, style, name, parent, mask=False):
    line_path = [['M', [startx, starty+radius]]]
    if radius > 0.0: # rounded corners
        line_path.append(['c', [0, -radius/2, radius/2, -radius, radius, -radius]])
        if mask == "Below":
               line_path.append(['m', [width-2*radius, 0,]])
        else:
            line_path.append(['c', [radius/2, 0, width-2*radius-radius/2, 0, width-2*radius,0 ]]) # top line
        line_path.append(['c', [radius/2, 0, radius, radius/2, radius, radius]])
        line_path.append(['c', [0, radius/2, 0, height-2*radius-radius/2, 0, height-2*radius]]) # RHS line
        line_path.append(['c', [0, radius/2, -radius/2, radius, -radius, radius]])
        line_path.append(['c', [-radius/2,0, -width+2*radius+radius/2,0, -width+2*radius,0]]) # bottom line
        line_path.append(['c', [-radius/2, 0, -radius, -radius/2, -radius, -radius]])
        if mask == "Right":
            line_path.append(['m', [0, height]])
        else:
            line_path.append(['c', [0, -radius/2, 0, -height+2*radius+radius/2, 0, -height+2*radius]]) # LHS line
    else: # square corners
        if mask == "Below":
            line_path.append(['m', [width, 0]])
            line_path.append(['l', [0, height, -width, 0, 0, -height]])
        elif mask == "Right":
            line_path.append(['l', [width, 0, 0, height, -width, 0,]])
        else: # separate
            line_path.append(['l', [width, 0, 0, height, -width, 0, 0, -height]])
    #
    #sys.stderr.write("%s\n"% line_path)
    attribs = {'style':str(inkex.Style(style)), inkex.addNS('label','inkscape'):name, 'd':dirtyFormat(line_path)}
    #sys.stderr.write("%s\n"% attribs)
    etree.SubElement(parent, inkex.addNS('path','svg'), attribs )

###----------------------
### all for intersection  from http://www.kevlindev.com/gui/index.htm

def get_derivative(polynomial):
    deriv = []
    for i in range(len(polynomial)):
        deriv.append(i* polynomial[i])
    return deriv

class LasercutJigsaw(inkex.EffectExtension):

    def add_arguments(self, pars):
        # General settings
        pars.add_argument("--tab")

        #Style
        pars.add_argument("--color_border", type=Color, default='4278190335', help="Border color")
        pars.add_argument("--color_jigsaw", type=Color, default='65535', help="Jigsaw lines color")

        #Dimensions
        pars.add_argument("--sizetype", default="boxsize")
        pars.add_argument("--width", type=float, default=50.0)
        pars.add_argument("--height", type=float, default=30.0)
        pars.add_argument("--innerradius", type=float, default=5.0, help="0 implies square corners")
        pars.add_argument("--units", default="cm", help="The unit of the box dimensions")
        pars.add_argument("--border", type=inkex.Boolean, default=False, help="Add Outer Surround")
        pars.add_argument("--borderwidth", type=float, default=10.0, help="Size of external surrounding border.")
        pars.add_argument("--outerradius", type=float, default=5.0, help="0 implies square corners")
        pars.add_argument("--pack", default="Below", help="Where to place backing piece on page")
        pars.add_argument("--pieces_W", type=int, default=11, help="How many pieces across")
        pars.add_argument("--pieces_H", type=int, default=11, help="How many pieces down")

        #Notches
        pars.add_argument("--notch_percent", type=float, default=0.0, help="Notch relative size. 0 to 1. 0.15 is good")
        pars.add_argument("--rand", type=float, default=0.1, help="Amount to perturb the basic piece grid.")
        pars.add_argument("--noknob_frequency", type=float, default=10, help="Percentage of smooth-sided edges.")
        pars.add_argument("--smooth_edges", type=inkex.Boolean, default=False, help="Allow pieces with smooth edges.")
        pars.add_argument("--use_seed", type=inkex.Boolean, default=False, help="Use the kerf value as the drawn line width")
        pars.add_argument("--seed", type=int, default=12345, help="Random seed for repeatability")
        pars.add_argument("--pieces", type=inkex.Boolean, default=False, help="Create separated pieces")
        pars.add_argument("--shift", type=float, default=0.0, help="Shifting for each piece (%)")

    def add_jigsaw_horiz_line(self, startx, starty, stepx, steps, width, style, name, parent):
        """ complex version All C smooth
            - get ctrl pt offset and use on both sides of each node (negate for smooth)"""
        line_path = []
        # starts with an M - then C with first point same as M = smooth (also last point still in C but doubled)
        line_path.append(['M', [startx, starty]])
        clist = [startx, starty] # duplicate 1st point so its smooth
        for i in range(1,steps+1):
            flip = 1
            if random.uniform(0.0,1.0) < 0.5:
                flip = -1
            do_smooth = False
            if self.smooth_edges:
                if random.uniform(0.0,100.0) < self.noknob_frequency:
                    do_smooth = True
            if do_smooth:
                pt1 = randomize((startx+i*stepx/2+stepx/2*(i-1), starty), self.random_radius/3, True)
                rand1 = randomize((0, 0), self.random_radius/4, True, True)
                # up to pt1
                ctrl1 = (-self.notch_step*1.5, self.notch_step*1.5)
                clist.extend([pt1[0]+ctrl1[0]-rand1[0], pt1[1]-ctrl1[1]*flip+rand1[1]*flip])
                clist.extend(pt1)
                # last ctrl point for next step
                clist.extend([pt1[0]-ctrl1[0]+rand1[0], pt1[1]+ctrl1[1]*flip-rand1[1]*flip])
            else:
                pt1 = randomize((startx-self.notch_step+i*stepx/2+stepx/2*(i-1), starty+self.notch_step/4*flip), self.random_radius/3, True)
                pt2 = randomize((startx-self.notch_step+i*stepx/2+stepx/2*(i-1), starty-self.notch_step*flip), self.random_radius/3, True)
                # pt3 is foor tip of the notch - required ?
                pt4 = randomize((startx+self.notch_step+i*stepx/2+stepx/2*(i-1), starty-self.notch_step*flip), self.random_radius/3, True) #mirror of 2
                pt5 = randomize((startx+self.notch_step+i*stepx/2+stepx/2*(i-1), starty+self.notch_step/4*flip), self.random_radius/3, True) # mirror of pt1
                # Create random local value for x,y of handle - then reflect to enforce smoothness
                rand1 = randomize((0, 0), self.random_radius/4, True, True)
                rand2 = randomize((0, 0), self.random_radius/4, True, True)
                rand4 = randomize((0, 0), self.random_radius/4, True, True)
                rand5 = randomize((0, 0), self.random_radius/4, True, True)
                # up to pt1
                #ctrl1_2 = (startx+i*stepx/2+(i-1)*stepx/2, starty-self.notch_step/3)
                ctrl1 = (self.notch_step/1.2, -self.notch_step/3)
                clist.extend([pt1[0]-ctrl1[0]-rand1[0], pt1[1]-ctrl1[1]*flip+rand1[1]*flip])
                clist.extend(pt1)
                # up to pt2
                clist.extend([pt1[0]+ctrl1[0]+rand1[0], pt1[1]+ctrl1[1]*flip-rand1[1]*flip])
                ctrl2 = (0, -self.notch_step/1.2)
                clist.extend([pt2[0]+ctrl2[0]-rand2[0], pt2[1]-ctrl2[1]*flip+rand2[1]*flip])
                clist.extend(pt2)
                # up to pt4
                clist.extend([pt2[0]-ctrl2[0]+rand2[0], pt2[1]+ctrl2[1]*flip-rand2[1]*flip])
                ctrl4 = (0, self.notch_step/1.2)
                clist.extend([pt4[0]+ctrl4[0]-rand4[0], pt4[1]-ctrl4[1]*flip+rand4[1]*flip])
                clist.extend(pt4)
                # up to pt5
                clist.extend([pt4[0]-ctrl4[0]+rand4[0], pt4[1]+ctrl4[1]*flip-rand4[1]*flip])
                ctrl5 = (self.notch_step/1.2, self.notch_step/3)
                clist.extend([pt5[0]-ctrl5[0]+rand5[0], pt5[1]-ctrl5[1]*flip-rand5[1]*flip])
                clist.extend(pt5)
                # last ctrl point for next step
                clist.extend([pt5[0]+ctrl5[0]-rand5[0], pt5[1]+ctrl5[1]*flip+rand5[1]*flip])
        #
        clist.extend([width, starty, width, starty]) # doubled up at end for smooth curve
        line_path.append(['C',clist])
        borderLineStyle = str(inkex.Style(style))
        attribs = { 'style':borderLineStyle, 'id':name, 'd':dirtyFormat(line_path)}
        etree.SubElement(parent, inkex.addNS('path','svg'), attribs )

    def create_horiz_blocks(self, group, gridy, style):
        path = lastpath = 0
        blocks = []
        count = 0
        for node in gridy.iterchildren():
            if node.tag == inkex.addNS('path','svg'): # which they ALL should because we just made them
                path = CubicSuperPath(node.get('d')) # turn it into a global C style SVG path
                #sys.stderr.write("count: %d\n"% count)
                if count == 0: # first one so use the top border
                    spath = node.get('d') # work on string instead of cubicpath
                    lastpoint = spath.split()[-2:]
                    lastx = float(lastpoint[0])
                    lasty = float(lastpoint[1])
                    #sys.stderr.write("lastpoint: %s\n"% lastpoint)
                    spath += ' %f %f %f %f %f %f' % (lastx,lasty-self.inner_radius, lastx,1.5*self.inner_radius, lastx,self.inner_radius)
                    spath += ' %f %f %f %f %f %f' % (self.width,self.inner_radius/2, self.width-self.inner_radius/2,0, self.width-self.inner_radius,0)
                    spath += ' %f %f %f %f %f %f' % (self.width-self.inner_radius/2,0, 1.5*self.inner_radius,0, self.inner_radius, 0)
                    spath += ' %f %f %f %f %f %f' % (self.inner_radius/2, 0, 0,self.inner_radius/2, 0,self.inner_radius)
                    spath += 'z'
                    #sys.stderr.write("spath: %s\n"% spath)
                    #
                    name = "RowPieces_%d" % (count)
                    attribs = { 'style':style, 'id':name, 'd':spath }
                    n = etree.SubElement(group, inkex.addNS('path','svg'), attribs )
                    blocks.append(n) # for direct traversal later
                else: # internal line - concat a reversed version with the last one
                    thispath = copy.deepcopy(path)
                    for i in range(len(thispath[0])): # reverse the internal C pairs
                        thispath[0][i].reverse()
                    thispath[0].reverse() # reverse the entire line
                    lastpath[0].extend(thispath[0]) # append
                    name = "RowPieces_%d" % (count)
                    attribs = { 'style':style, 'id':name, 'd':dirtyFormat(lastpath) }
                    n = etree.SubElement(group, inkex.addNS('path','svg'), attribs )
                    blocks.append(n) # for direct traversal later
                    n.set('d', n.get('d')+'z') # close it
                #
                count += 1
                lastpath = path
        # do the last row
        spath = node.get('d') # work on string instead of cubicpath
        lastpoint = spath.split()[-2:]
        lastx = float(lastpoint[0])
        lasty = float(lastpoint[1])
        #sys.stderr.write("lastpoint: %s\n"% lastpoint)
        spath += ' %f %f %f %f %f %f' % (lastx,lasty+self.inner_radius, lastx,self.height-1.5*self.inner_radius, lastx,self.height-self.inner_radius)
        spath += ' %f %f %f %f %f %f' % (self.width,self.height-self.inner_radius/2, self.width-self.inner_radius/2,self.height, self.width-self.inner_radius,self.height)
        spath += ' %f %f %f %f %f %f' % (self.width-self.inner_radius/2,self.height, 1.5*self.inner_radius,self.height, self.inner_radius, self.height)
        spath += ' %f %f %f %f %f %f' % (self.inner_radius/2, self.height, 0,self.height-self.inner_radius/2, 0,self.height-self.inner_radius)
        spath += 'z'
        #
        name = "RowPieces_%d" % (count)
        attribs = { 'style':style, 'id':name, 'd':spath }
        n = etree.SubElement(group, inkex.addNS('path','svg'), attribs )
        blocks.append(n) # for direct traversal later
        #
        return(blocks)

    def create_vert_blocks(self, group, gridx, style):
        path = lastpath = 0
        blocks = []
        count = 0
        for node in gridx.iterchildren():
            if node.tag == inkex.addNS('path','svg'): # which they ALL should because we just made them
                path = CubicSuperPath(node.get('d')) # turn it into a global C style SVG path
                #sys.stderr.write("count: %d\n"% count)
                if count == 0: # first one so use the right border
                    spath = node.get('d') # work on string instead of cubicpath
                    lastpoint = spath.split()[-2:]
                    lastx = float(lastpoint[0])
                    lasty = float(lastpoint[1])
                    #sys.stderr.write("lastpoint: %s\n"% lastpoint)
                    spath += ' %f %f %f %f %f %f' % (lastx+self.inner_radius/2,lasty, self.width-1.5*self.inner_radius,lasty, self.width-self.inner_radius, lasty)
                    spath += ' %f %f %f %f %f %f' % (self.width-self.inner_radius/2,lasty, self.width,self.height-self.inner_radius/2, self.width,self.height-self.inner_radius)
                    spath += ' %f %f %f %f %f %f' % (self.width,self.height-1.5*self.inner_radius, self.width, 1.5*self.inner_radius, self.width,self.inner_radius)
                    spath += ' %f %f %f %f %f %f' % (self.width,self.inner_radius/2, self.width-self.inner_radius/2,0, self.width-self.inner_radius,0)
                    spath += 'z'
                    #sys.stderr.write("spath: %s\n"% spath)
                    #
                    name = "ColPieces_%d" % (count)
                    attribs = { 'style':style, 'id':name, 'd':spath }
                    n = etree.SubElement(group, inkex.addNS('path','svg'), attribs )
                    blocks.append(n) # for direct traversal later
                else: # internal line - concat a reversed version with the last one
                    thispath = copy.deepcopy(path)
                    for i in range(len(thispath[0])): # reverse the internal C pairs
                        thispath[0][i].reverse()
                    thispath[0].reverse() # reverse the entire line
                    lastpath[0].extend(thispath[0]) # append
                    name = "ColPieces_%d" % (count)
                    attribs = { 'style':style, 'id':name, 'd':dirtyFormat(lastpath) }
                    n = etree.SubElement(group, inkex.addNS('path','svg'), attribs )
                    blocks.append(n) # for direct traversal later
                    n.set('d', n.get('d')+'z') # close it
                #
                count += 1
                lastpath = path
        # do the last one (LHS)
        spath = node.get('d') # work on string instead of cubicpath
        lastpoint = spath.split()[-2:]
        lastx = float(lastpoint[0])
        lasty = float(lastpoint[1])
        #sys.stderr.write("lastpoint: %s\n"% lastpoint)
        spath += ' %f %f %f %f %f %f' % (lastx-self.inner_radius,lasty, 1.5*self.inner_radius, lasty, self.inner_radius,lasty)
        spath += ' %f %f %f %f %f %f' % (self.inner_radius/2,lasty, 0,lasty-self.inner_radius/2, 0,lasty-self.inner_radius)
        spath += ' %f %f %f %f %f %f' % (0,lasty-1.5*self.inner_radius, 0,1.5*self.inner_radius, 0,self.inner_radius)
        spath += ' %f %f %f %f %f %f' % (self.inner_radius/2,0, self.inner_radius,0, 1.5*self.inner_radius, 0)
        spath += 'z'
        #
        name = "ColPieces_%d" % (count)
        attribs = { 'style':style, 'id':name, 'd':spath }
        n = etree.SubElement(group, inkex.addNS('path','svg'), attribs )
        blocks.append(n) # for direct traversal later
        #
        return(blocks)

    def create_pieces(self, jigsaw, gridx, gridy):
        """ Loop through each row """
        # Treat outer edge carefully as border runs around. So special code the edges
        # Internal lines should be in pairs - with second line reversed and appended to first. Close with a 'z'
        # Create new group
        g_attribs = {inkex.addNS('label','inkscape'):'JigsawPieces:X' + \
                     str( self.pieces_W )+':Y'+str( self.pieces_H ) }
        jigsaw_pieces = etree.SubElement(jigsaw, 'g', g_attribs)
        jigsaw_pieces_id = self.svg.get_unique_id("pieces-")
        jigsaw_pieces.attrib['id'] = jigsaw_pieces_id
        borderLineStyle = str(inkex.Style(self.borderLineStyle))

        xblocks = self.create_horiz_blocks(jigsaw_pieces, gridy, borderLineStyle)
        yblocks = self.create_vert_blocks(jigsaw_pieces, gridx, borderLineStyle)

        # for each xblock intersect it with each Y block
        puzzlePartNo = 1
        allPathPairsToIntersect = []
        allPathsToDelete = []

        for x in range(len(xblocks)):
            for y in range(len(yblocks)):
                allPathPairsToIntersect.append([copy.copy(xblocks[x]), copy.copy(yblocks[y])])
                allPathsToDelete.append(xblocks[x])
                allPathsToDelete.append(yblocks[y])

        for pair in allPathPairsToIntersect:
            pair[0].attrib['id'] = str(puzzlePartNo) + "_X"
            pair[1].attrib['id'] = str(puzzlePartNo) + "_Y"
            xId = pair[0].get('id')
            yId = pair[1].get('id')
            #self.msg("intersecting {} with {}".format(xId, yId))
            puzzlePartNo += 1
            jigsaw_pieces.append(pair[0])
            jigsaw_pieces.append(pair[1])

        for pathToDelete in allPathsToDelete:
            pathToDelete.delete()

        actions_list = []
        for pair in allPathPairsToIntersect:
                actions_list.append("select:{}".format(pair[0].attrib['id']))
                actions_list.append("select:{}".format(pair[1].attrib['id']))
                actions_list.append("SelectionIntersect")
                actions_list.append("EditDeselect")

        #self.msg(actions_list)

        #workaround to fix it (we use export to tempfile instead processing and saving again)
        tempfile = self.options.input_file + "-intersected.svg"
        with open(tempfile, 'wb') as fp:
            fp.write(self.svg.tostring())
        extra_param = "--batch-process"
        actions_list.append("export-type:svg")
        actions_list.append("export-filename:{}".format(tempfile))
        actions_list.append("export-do")
        actions = ";".join(actions_list)
        #self.msg(actions)
        cli_output = inkscape(tempfile, extra_param, actions=actions) #process recent file
        if len(cli_output) > 0:
            self.msg("Inkscape returned the following output when trying to run the file export; the file export may still have worked:")
            self.msg(cli_output)

        # replace current document with content of temp copy file
        self.document = inkex.load_svg(tempfile)
        # update self.svg
        self.svg = self.document.getroot()

        row = 1
        col = 1
        offsetW = self.options.shift / 100 * (self.options.width / self.options.pieces_W)
        offsetH = self.options.shift / 100 * (self.options.height / self.options.pieces_H)
        for jigsaw_piece in self.svg.getElementById(jigsaw_pieces_id).getchildren():
            jigsaw_piece.apply_transform()
            jigsaw_piece.set('transform', 'translate(%f,%f)' % (-col * offsetH, 0))
            jigsaw_piece.apply_transform()
            jigsaw_piece.set('transform', 'translate(%f,%f)' % (0, row * offsetW))
            jigsaw_piece.apply_transform()
            currentPiece = int(jigsaw_piece.get('id').split('_')[0])
            #self.msg("piece {} zeile {} Spalte {}".format(currentPiece, row, col))
            if currentPiece % self.options.pieces_W == 0:
                row += 1
                col -= self.options.pieces_W
            col += 1
        return jigsaw_pieces_id

    def effect(self):

        # internal useful variables
        self.stroke_width =str(self.svg.unittouu("1px")) # default for visiblity
        self.borderLineStyle = {'stroke': self.options.color_border, 'fill': 'none', 'stroke-width': self.stroke_width,
                           'stroke-linecap': 'butt', 'stroke-linejoin': 'miter'}
        self.jigsawLineStyle = {'stroke': self.options.color_jigsaw, 'fill': 'none', 'stroke-width': self.stroke_width,
                           'stroke-linecap': 'butt', 'stroke-linejoin': 'miter'}

        # document dimensions (for centering)
        docW = self.svg.unittouu(self.document.getroot().get('width'))
        docH = self.svg.unittouu(self.document.getroot().get('height'))

        # extract fields from UI
        self.width = self.svg.unittouu( str(self.options.width)  + self.options.units )
        self.height = self.svg.unittouu( str(self.options.height) + self.options.units )
        self.pieces_W = self.options.pieces_W
        self.pieces_H = self.options.pieces_H

        if self.options.sizetype == "partsize":
           self.width = self.width *  self.pieces_W
           self.height = self.height *  self.pieces_H

        average_block = (self.width/self.pieces_W + self.height/self.pieces_H) / 2
        self.notch_step = average_block * self.options.notch_percent / 3 # 3 = a useful notch size factor
        self.smooth_edges = self.options.smooth_edges
        self.noknob_frequency = self.options.noknob_frequency
        self.random_radius = self.options.rand * average_block / 5 # 5 = a useful range factor
        self.inner_radius = self.options.innerradius
        if self.inner_radius < 0.01: self.inner_radius = 0.0 # snap to 0 for UI error when setting spinner to 0.0
        self.border = self.options.border
        self.borderwidth = self.options.borderwidth
        self.outer_radius = self.options.outerradius
        if self.outer_radius < 0.01: self.outer_radius = 0.0 # snap to 0 for UI error when setting spinner to 0.0
        self.pack = self.options.pack
        # pieces
        self.pieces = self.options.pieces
        # random function
        if not self.options.use_seed:
            random.seed(self.options.seed)

        #
        # set up the main object in the current layer - group gridlines
        g_attribs = {inkex.addNS('label','inkscape'):'Jigsaw:X' + str(self.pieces_W )+':Y'+str(self.pieces_H)  + "={}Pcs)".format(self.pieces_W * self.pieces_H)}
        jigsaw_group = etree.SubElement(self.svg.get_current_layer(), 'g', g_attribs)
        #Group for X grid
        g_attribs = {inkex.addNS('label','inkscape'):'X_Gridlines'}
        gridx = etree.SubElement(jigsaw_group, 'g', g_attribs)
        #Group for Y grid
        g_attribs = {inkex.addNS('label','inkscape'):'Y_Gridlines'}
        gridy = etree.SubElement(jigsaw_group, 'g', g_attribs)

        # Draw the Border
        add_rounded_rectangle(0,0, self.inner_radius, self.width, self.height, self.borderLineStyle, 'innerborder', jigsaw_group)
        # Do the Border
        if self.border:
            add_rounded_rectangle(-self.borderwidth,-self.borderwidth, self.outer_radius, self.borderwidth*2+self.width,
                                  self.borderwidth*2+self.height, self.borderLineStyle, 'outerborder', jigsaw_group)
            # make a second copy below the jigsaw for the cutout BG
            if self.pack == "Below":
                add_rounded_rectangle(-self.borderwidth,self.borderwidth+ self.height, self.outer_radius, self.borderwidth*2+self.width,
                                      self.borderwidth*2+self.height, self.borderLineStyle, 'BG', jigsaw_group, self.pack)
            elif self.pack == "Right":
                add_rounded_rectangle(self.width+self.borderwidth,-self.borderwidth, self.outer_radius, self.borderwidth*2+self.width,
                                      self.borderwidth*2+self.height, self.borderLineStyle, 'BG', jigsaw_group, self.pack)
            else: # Separate
                add_rounded_rectangle(self.width+self.borderwidth*2,-self.borderwidth, self.outer_radius, self.borderwidth*2+self.width,
                                      self.borderwidth*2+self.height, self.borderLineStyle, 'BG', jigsaw_group)

        # Step through the Grid
        Xstep = self.width / (self.pieces_W)
        Ystep = self.height / (self.pieces_H)
        # Draw Horizontal lines on Y step with Xstep notches
        for i in range(1, self.pieces_H):
            self.add_jigsaw_horiz_line(0, Ystep*i, Xstep, self.pieces_W, self.width, self.jigsawLineStyle, 'YDiv'+str(i), gridy)
        # Draw Vertical lines on X step with Ystep notches
        for i in range(1, self.pieces_W):
            self.add_jigsaw_horiz_line(0, Xstep*i, Ystep, self.pieces_H, self.height, self.jigsawLineStyle, 'XDiv'+str(i), gridx)
            # Rotate lines into pos
            # actualy transform can have multiple transforms in it e.g. 'translate(10,10) rotate(10)'
        for node in gridx.iterchildren():
            if node.tag == inkex.addNS('path','svg'):
                node.set('transform', 'translate(%f,%f) rotate(90)' % (self.width, 0))
                node.apply_transform()
        # center the jigsaw
        jigsaw_group.set('transform', 'translate(%f,%f)' % ( (docW-self.width)/2, (docH-self.height)/2 ) )

        #inkex.utils.debug("Your puzzle consists out of {} pieces.".format(self.pieces_W * self.pieces_H))

        # pieces
        if self.pieces:
            gridx.delete() #delete the previous x generated stuff because we have single pieces instead!
            gridy.delete() #delete the previous y generated stuff because we have single pieces instead!
            jigsaw_group.getchildren()[0].delete() #delete inner border
            jigsaw_pieces_id = self.create_pieces(jigsaw_group, gridx,gridy)
            for jigsaw_piece in self.svg.getElementById(jigsaw_pieces_id).getchildren():
                jigsaw_piece.attrib['id'] =  jigsaw_pieces_id + "_" + jigsaw_piece.attrib['id']

if __name__ == '__main__':
    LasercutJigsaw().run()


from django.shortcuts import redirect, render
from django.contrib.auth.decorators import login_required
from .models import UsersLogs,Notifications
from django.utils import timezone
from .decorators import allowed_users
# Create your views here.
@login_required
def home(request):
    if request.user.groups.filter(name="Employee").exists():
        return redirect('Home')
    elif request.user.groups.filter(name="Manager").exists():
        return redirect('Dashboard')
    else:
        return redirect('logout')

@login_required
@allowed_users(allowed_roles=['Employee'])
def employee_home(request):
    UserLog = None
    try:
        UserLog = UsersLogs.objects.filter(is_logedout = False,user_id=request.user).first()
    except:
        UserLog=None
    if UserLog == None:
        new_UserLog = UsersLogs()
        new_UserLog.user_id = request.user
        new_UserLog.logedin_at = timezone.now()
        new_UserLog.save()
        UserLog = new_UserLog

    return render(request,'employee_home.html',{"CurrentLog":UserLog})

@login_required
@allowed_users(allowed_roles=['Manager'])
def manager_home(request):
    # counters
    attendants = UsersLogs.objects.filter(is_logedout = False).count()
    leave_requests = UsersLogs.objects.filter(leave_request_at__isnull=False,is_logedout = False,allow_leave=False).count()
    context = {
        "attendants":attendants,
        "leave_requests":leave_requests
        }
    return render(request,'manager_home.html',context)

@login_required
@allowed_users(allowed_roles=['Manager'])
def employees_requests(request):
    leave_req = UsersLogs.objects.filter(leave_request_at__isnull=False,allow_leave=False,is_logedout = False)
    not_read_notific = Notifications.objects.all().filter(is_readed = 0)
    for noti in not_read_notific:
        noti.is_readed = 1
        noti.save()
    return render(request,'employees_requests.html',{"leave_requests":leave_req})

def forbeddin(request):
    return render(request,"registration/forbeddin.html")


from textblob import TextBlob;
from textblob import Word;
s1= " The Game Of Thrones";
s2= " Winter is comming in thrones";
s3= " White walker are comming to kill all";
d1= TextBlob(s1);
d2= TextBlob(s2);
d3= TextBlob(s3);

word=Word("thrones");
doclist=[d1,d2,d3];
for doc in doclist:
 wordlist=doc.words;
 #noofwords=len(wordlist);

 for word in wordlist:

  tf=doc.words.count(word);

  print(tf)
  print(word+"occur"+str(tf)+"times")

#ntf=tf/noofwords;
#print(ntf)


import json
import datetime

import node

class MapGraph:
    def __init__(self, location):
        """
        :param location: int
        :return: MapGraph
        """
        with open("data/nodes.json") as json_file:
            json_file = json_file.read()
            self.nodes = json.loads(json_file, object_hook=self._decode_json_to_nodes)
        self.nodes = {node.id: node for node in self.nodes}
        self.location_id = location
        self.services = []

    def add_service(self, service):
        """

        :param service: Serivce
        """
        self.services.append(service)

    def create_time_table(self):
        time_table = []
        for srv in self.services:
            if self.location_id in srv.get_path():
                time_arrive = srv.get_time() + self._count_up_weights(srv.get_path())
                time_table.append(srv.get_name() + " " + str(time_arrive.time()))
        return time_table

    def _count_up_weights(self, path):
        len_path = datetime.timedelta(hours = 0)
        for i in range(len(path) - 1):
            if path[i] == self.location_id:
                break
            len_path = len_path + self.nodes[path[i]].get_edge_weight_from_id(path[i+1])
        return len_path

    def _decode_json_to_nodes(self, dct):
        """
        object_hook for json.loads
        :return: Node
        """
        if "__complex__" in dct:
            return node.Node(dct["id"], dct["edges"])
        return dct


import json
from azure.storage.blob import BlobServiceClient, ContainerClient
import logging
import os

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

class SourceProvider:
    def __init__(
        self
    ):
        self.cnxn_string = os.environ['AZURE_STORAGE_CONNECTION_STRING']
        self.source_config_path = os.environ.get(
            'SOURCE_CONFIG_PATH') or 'source.json'
        self.source_config = self.get_source_config()
        self.container = self.get_container_client()

    def get_source_config(self):
        with open(self.source_config_path, 'r') as file:
            return json.loads(file.read())

    def get_container_client(self):
        logger.info(f'Storage connection string: {self.cnxn_string}')

        client = BlobServiceClient.from_connection_string(
            conn_str=self.cnxn_string)
        logger.info(f'Created blob service client')

        container = client.get_container_client(
            container='build-resources')
        logger.info(f'Fetched build-resources blob container')

        return container

    def get_source_target_pair(self, data):
        return (
            data.get('source'),
            data.get('target')
        )

    def get_blob_stream(self, path):
        blob_client = self.container.get_blob_client(path)

        if not blob_client.exists():
            raise Exception(f"No blob exists at path '{path}'")

        return blob_client.download_blob()

    def handle_source(self, data):
        source, target = self.get_source_target_pair(
            data=data)
        logger.info(f'[Source -> Target]: {source} -> {target}')

        if not source:
            raise Exception("A value is required for parameter 'source'")
        if not target:
            raise Exception("A value is required for parameter 'target'")

        logger.info(f"[Source -> Target]: Fetching blob stream @ '{source}'")
        stream = self.get_blob_stream(path=source)

        logger.info(
            f"[Source -> Target]: Writing blob stream to target file buffer")
        with open(target, 'wb') as file:
            stream.readinto(file)
        logger.info(f"[Source -> Target]: Source completed successfully")

    def go(self):
        logger.info(f'[init]: {len(self.source_config)} sources defined')
        for config in self.source_config:
            self.handle_source(data=config)

util = SourceProvider()
util.go()