from functools import reduce
from itertools import count
from math import fabs
import random
import base64
import shutil
import uuid
import xlwt
import os
import exifread
from PIL import Image
from io import BytesIO
from datetime import datetime
from typing import Any
from sqlalchemy.orm import Session
from sqlalchemy import desc,and_,or_
from fastapi import APIRouter, Depends, HTTPException, status,UploadFile, File, Form
from fastapi.encoders import jsonable_encoder
from fastapi.responses import JSONResponse,StreamingResponse

from app import crud, schemas
from app.utils import utils
from app.api import deps
from app.models import User,Blue

router = APIRouter()

@router.post('/save_answer/{ans_id}/{is_ok}',dependencies=[Depends(deps.get_current_user)], response_model=Any, status_code=status.HTTP_201_CREATED)
def save_answer(db: Session = Depends(deps.get_db),user: User = Depends(deps.get_current_user),*,ans_id: str,is_ok: int) -> Any:

     if not user:
        raise HTTPException(
            status_code=400, detail="用户不存在"
        )
     answerids = user.answerids.split(',')
     answeredids = user.answeredids.split(',')
     answer_heart_value = user.answer_heart_value
     heart_value = user.heart_value
     lottery_count = user.lottery_count

     if(ans_id in answeredids or ans_id in answerids):
        raise HTTPException(
            status_code=500, detail="曾经回答过的问题无论对错已经是曾经了！"
        )

     if(answer_heart_value < 50 and not ans_id in answerids and is_ok == 1):
        answer_heart_value += 10
        heart_value += 10
        answerids.append(ans_id)
        if answer_heart_value>=50:
            lottery_count += 1

     if(not ans_id in answeredids):
        answeredids.append(ans_id)

     new_answerids = ','.join(answerids)
     new_answeredids = ','.join(answeredids)
     obj_u = schemas.UserUpdate(
        answer_heart_value=answer_heart_value,
        heart_value =heart_value,
        answerids = new_answerids,
        answeredids = new_answeredids,
        lottery_count = lottery_count
        )
     new_user = crud.user.update(db,db_obj=user,obj_in=obj_u)
     return {
        'userId':user.id,
        'userName':user.nick_name,
        'heartValue':new_user.heart_value,
        'lotteryCount':new_user.lottery_count,
        'answerId': new_user.answerids.split(','),
        'answeredIds':new_user.answeredids.split(','),
    }

#saveThumbed
@router.post('/save_thumbed/{blue_id}',dependencies=[Depends(deps.get_current_user)], response_model=Any, status_code=status.HTTP_201_CREATED)
def save_thumbed(db: Session = Depends(deps.get_db),user: User = Depends(deps.get_current_user),*,blue_id:int) -> Any:
     if not user:
        raise HTTPException(
            status_code=400, detail="用户不存在"
        )
     thumbed_blue = crud.blue.get(db,id=blue_id)
     if not thumbed_blue:
        raise HTTPException(
            status_code=400, detail="内容不存在"
        )
     thumbeds = thumbed_blue.thumbed.split(',')
     thumbe_times = thumbed_blue.thumbe_times
     if(not str(user.id) in thumbeds):
        thumbeds.append(str(user.id))
        thumbe_times += 1
     new_thumbeds= ','.join(thumbeds)
     obj_u = schemas.BlueUpdate(
        thumbed=new_thumbeds,
        thumbe_times=thumbe_times
        )
     new_blue = crud.blue.update(db,db_obj=thumbed_blue,obj_in=obj_u)
     return {
        'thumbedUserId':user.id,
        'thumbedUserName':user.nick_name,
        'thumbeUsers': new_blue.thumbed.split(','),
        'thumbeTimes':new_blue.thumbe_times
    }

@router.post('/get_prize',dependencies=[Depends(deps.get_current_user)], response_model=Any, status_code=status.HTTP_200_OK)
def get_prize(db: Session = Depends(deps.get_db),user: User = Depends(deps.get_current_user)) -> Any:
#@router.post('/get_prize', response_model=Any, status_code=status.HTTP_200_OK)
#def get_prize(db: Session = Depends(deps.get_db)) -> Any:
    # for test  start
    #randomUserId =random.sample(range(2,1912),1)
    #user = crud.user.get(db,id=randomUserId)
    # fot test end
    # if not access_user:
    #     raise HTTPException(
    #         status_code=400, detail="user not found"
    #     )
    user_updated = False
    #second_count = crud.user.get_second(db)
    with db.begin(subtransactions=True):
        # user = None
        # try:
        #     user = crud.user.locke_user(db,db_obj=access_user)
        # except Exception as e:
        #     print(f"抽奖异常:{e.__str__()}")
        if not user:
            raise HTTPException(
                status_code=400, detail="用户不存在"
            )
        lottery_count = user.lottery_count
        first_prize_time = user.first_prize_time
        second_prize_time = user.second_prize_time
        first_prize_level = user.first_prize_level
        second_prize_level = user.second_prize_level

        if lottery_count < 1:
            raise HTTPException(
                status_code=500, detail="抽奖次数不足"
            )
        if second_prize_time > 0 and first_prize_time > 0:
            raise HTTPException(
                status_code=500, detail="已经抽奖两次啦"
            )
        gifts = [1,2,2,3,3,3,4,4,4,5,5,5,6,6,6,6,7,7,7,7,8,8,8,8,9,9,9,9,9,9,9,9,9,9,9,9,9
        ,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9]
        # 如果第一次已经抽取了，就在三等奖和四等奖中抽取，且中间总额不能大于总数量 -  总人数
        has_gifts = True
        if first_prize_level > 0:
            #if second_count <= 150:
            #    gifts = [6,7,8,9,10,10,10,10,10,10,10,10,10,10,10,10,10]
            # else:
            #     has_gifts = False
            gifts = [9,9,9,9,9,9,9,9,9]
        random.shuffle(gifts)
        giftlevel = -1
        retry = 30
        while giftlevel == -1 and retry > 0 and has_gifts:
            index=random.sample(range(0,len(gifts)-1),1)
            giftlevel = gifts[index[0]]

            gift = crud.gift.get(db,id=giftlevel)
            if (gift and gift.allowance > 0 ):
                upOK =  crud.gift.reduceOneAllowance(db,db_obj=gift)
                if (not upOK):
                    giftlevel = -1
            else:
                giftlevel = -1
            retry -= 1

        #if retry < 1 or giftlevel == 10:
        if retry < 1:
            giftlevel = 9

        now_time = int(datetime.timestamp(datetime.utcnow()))
        user_updated = crud.user.update_giftlevel(db,db_obj=user,now_time=now_time,gift_level=giftlevel)
    if user_updated:
        db.commit()
        db.refresh(user)
        return {
            'userId':user.id,
            'lotteryCount':user.lottery_count,
            'lotteryNumber':giftlevel,
            'heartValue':user.heart_value,
        }
    else:
        db.rollback()
        print("user update false")
        raise HTTPException(
                status_code=500, detail="两次抽奖次数已经用完"
            )

@router.get('/get_cy',dependencies=[Depends(deps.get_current_user)],response_model=Any, status_code=status.HTTP_200_OK)
def get_cy(db: Session = Depends(deps.get_db),user: User = Depends(deps.get_current_user)) -> Any:
    cnt = crud.user.get_cy(db)
    return JSONResponse(content={"count":cnt}, status_code=status.HTTP_200_OK)

@router.post('/save_upload',
             dependencies=[Depends(deps.get_current_user)],
             response_model=Any, status_code=status.HTTP_201_CREATED)
def save_upload(
        db: Session = Depends(deps.get_db),
        user: User = Depends(deps.get_current_user),
        upload_file: UploadFile = File(...), comment: str = Form(...)) -> Any:
    if not user:
        raise HTTPException(
            status_code=400, detail="用户不存在"
        )

    ext = upload_file.filename.split('.')[-1]
    u_name = uuid.uuid4()
    file_location = f"uploads/{u_name}.{ext}"
    context_type = upload_file.content_type
    allow_types = ['image/jpeg', 'image/jpg', 'image/png','jpeg','jpg','png']
    if context_type not in allow_types:
        raise HTTPException(
            status_code=500, detail="文件类型不支持，请上传jpeg/jpg/png格式图片"
        )

    with open(file_location, "wb+") as file_object:
        shutil.copyfileobj(upload_file.file, file_object)

    img_file_size = os.path.getsize(file_location)/1000/1000
    if img_file_size >= 5:
        raise HTTPException(
            status_code=500, detail="上传图片不能大于5M"
        )
    if img_file_size < 1:
        img_file_size = 1
    file_location_c = f"uploads/{u_name}_c.{ext}"
    try:
        f = open(file_location, 'rb')
        tags = exifread.process_file(f)
        need_ori_L = 0
        need_ori_R = 0
        need_ori_180 = 0
        if 'Image Orientation' in tags.keys():
            if 'Rotated' in str(tags['Image Orientation']):
                if 'Rotated 90 CW' in str(tags['Image Orientation']): # right, top
                    need_ori_L = 1
                elif 'Rotated 90 CCW' in str(tags['Image Orientation']): # left, bottom
                    need_ori_R = 1
                elif 'Rotated 180' in str(tags['Image Orientation']): #
                    need_ori_180 = 1

                # 还有Horizontal(normal)为正常情况

                # 还有些情况未考虑到， 比如镜像等， 由于数量少，就偷个懒暂时忽略了

        f.close()

        sImg=Image.open(file_location)
        if need_ori_L == 1:
            sImg = sImg.transpose(Image.ROTATE_270)
        elif need_ori_R == 1:
            sImg = sImg.transpose(Image.ROTATE_90)
        elif need_ori_180 == 1:
            sImg = sImg.transpose(Image.ROTATE_180)

        w,h=sImg.size
        dImg=sImg.resize((int(w/img_file_size),int(h/img_file_size)),Image.ANTIALIAS)
        dImg.save(file_location_c)
        #print (file_location_c +" successful.")
    except Exception as e:
        raise HTTPException(
            status_code=500, detail=f"图片处理异常，{e.__str__()}"
        )

    blue_in = schemas.BlueCreate(user_id=user.id, upload_comment=comment,upload_file_url=f"/upload/{u_name}_c.{ext}")
    new_blue = crud.blue.create(db, obj_in=blue_in)

    upload_heart_value = user.upload_heart_value
    lottery_count = user.lottery_count
    heart_value = user.heart_value
    if (upload_heart_value > 0 or lottery_count > 1):
        return {
        'userId':user.id,
        'userName':user.nick_name,
        'heartValue':user.heart_value,
        'lotteryCount':user.lottery_count,
        'fileUrl':user.upload_file_url,
        'comment':user.upload_comment,
        'uploadTime':user.upload_time,
        'isFirst':False
    }

    upload_heart_value = 50
    lottery_count += 1
    heart_value += 50

    user_up = schemas.UserUpdate(
        upload_heart_value=upload_heart_value,heart_value=heart_value,lottery_count=lottery_count,
    )
    new_user = crud.user.update(db,db_obj=user,obj_in=user_up)
    return {
        'userId':new_user.id,
        'userName':new_user.nick_name,
        'heartValue':new_user.heart_value,
        'lotteryCount':new_user.lottery_count,
        'fileUrl':new_user.upload_file_url,
        'comment':new_user.upload_comment,
        'uploadTime':new_user.upload_time,
        'isFirst':True
    }

@router.get('/upload_list',
             dependencies=[Depends(deps.get_current_user)],
             response_model=Any, status_code=status.HTTP_200_OK)
def upload_list(
        db: Session = Depends(deps.get_db),
        user: User = Depends(deps.get_current_user),*,page: int = 1, limit: int = 12,isFirst:bool = False) -> Any:

    uids = crud.blue.get_uploaded_uids(db)
    ids = [u["id"] for u in uids]
    if len(ids) > 12:
        if isFirst:
            max = ids[-4:]
            max.reverse()
            max.extend(random.sample(ids[0:-4], 8) )
            print(max)
            ids = max
            print(ids)
        else:
            ids = random.sample(ids, 12)
    else:
        ids.reverse()
    filters = (and_(Blue.id.in_(tuple(ids))),) # 逗号不能少，如果只有一个条件的时候
    order_by =desc(Blue.thumbe_times)
    data = crud.blue.get_uploads(db,order_by=order_by,filters=filters,page=page,limit=limit)
    return JSONResponse(content=data, status_code=status.HTTP_200_OK)

@router.post('/result',
             dependencies=[Depends(deps.get_current_active_admin)],
             response_model=Any, status_code=status.HTTP_200_OK)
def get_results(
        db: Session = Depends(deps.get_db), *,searchKey: str = Form(''), gift:int =Form(...), page: int = 1, limit: int = 2500) -> Any:
    filters = [] #  如果是 tuple逗号不能少，如果只有一个条件的时候
    if (searchKey) :
        filters.append(or_(User.username.like(f'%{searchKey}%'),User.nick_name.like(f'%{searchKey}%')))
    if(gift > 0) :
        filters.append(or_(User.first_prize_level == gift, User.second_prize_level == gift)) # 逗号不能少，如果只有一个条件的时候
    else:
        filters.append(or_(User.first_prize_level > 0, User.second_prize_level > 0)) # 逗号不能少，如果只有一个条件的时候
    filters = tuple(filters)
    order_by = User.username
    data = crud.user.get_results(db,order_by=order_by,filters=filters,page=page,limit=limit)
    return JSONResponse(content=data, status_code=status.HTTP_200_OK)

@router.post('/export',dependencies=[Depends(deps.get_current_active_admin)], response_model=Any, status_code=status.HTTP_200_OK)
def fl_query(db: Session = Depends(deps.get_db), *,searchKey: str = Form(''), gift:int =Form(...), page: int = 1, limit: int = 2500):
     header = ['工号', '姓名', '部门', "奖品一", "奖品二"]
     """
     以流的形式导出到excel     """

     def set_style():
         """
         设置样式
         :return:
         """
         # 居中设置
         alignment = xlwt.Alignment()
         alignment.horz = xlwt.Alignment.HORZ_CENTER
         alignment.vert = xlwt.Alignment.VERT_CENTER

         # 设置表头字体样式
         head_style = xlwt.XFStyle()
         font = xlwt.Font()
         font.name = 'Times New Roman'  # 字体
         font.bold = True  # 字体加粗
         head_style.font = font  # 设置字体
         head_style.alignment = alignment  # Add Alignment to Style

         # 设置表中内容样式
         cont_style = xlwt.XFStyle()
         font = xlwt.Font()
         font.name = 'Times New Roman'  # 字体
         font.bold = False  # 字体加粗
         cont_style.font = font  # 设置字体
         cont_style.alignment = alignment  # Add Alignment to Style

         # 设置单元格边界
         borders = xlwt.Borders()
         borders.left = xlwt.Borders.THIN
         borders.right = xlwt.Borders.THIN
         borders.top = xlwt.Borders.THIN
         borders.bottom = xlwt.Borders.THIN
         head_style.borders = borders
         cont_style.borders = borders
         return head_style, cont_style

     def get_sheet(_book, _index):
         """
         创建sheet页
         :param _book:
         :param _index:
         :return:
         """
         _name = "sheet_{}".format(str(_index))
         _sheet = _book.add_sheet(_name)
         return _sheet

     def write_head(_head, _sheet, _head_style):
         """
         写入表头
         :param _head:
         :param _sheet:
         :param _head_style:
         :return:
         """
         for head in range(len(header)):
             context = str(header[head])
             need_width = (1 + len(context)) * 556 * 2
             table_sheet.col(head).width = need_width
             # table_sheet.write(0, head, context, style=_head_style)
             table_sheet.write(0, head, context, style=_head_style)

     sheet_index = 1
     book = xlwt.Workbook(encoding='utf-8')  # 创建 Excel 文件
     table_sheet = get_sheet(book, sheet_index)  # 添加sheet表
     h_style, c_style = set_style()
     write_head(header, table_sheet, h_style)

     # 获取数据
     filters = [] #  如果是 tuple逗号不能少，如果只有一个条件的时候
     if (searchKey) :
        filters.append(or_(User.username.like(f'%{searchKey}%'),User.nick_name.like(f'%{searchKey}%')))
     if(gift > 0) :
        filters.append(or_(User.first_prize_level == gift, User.second_prize_level == gift)) # 逗号不能少，如果只有一个条件的时候
     else:
        filters.append(or_(User.first_prize_level > 0, User.second_prize_level > 0)) # 逗号不能少，如果只有一个条件的时候
     filters = tuple(filters)
     order_by = User.username
     fls = crud.user.get_results(db,order_by=order_by,filters=filters,page=page,limit=limit)
     # 插入数据
     row = 1
     gifts = ['未中奖','AVATR户外座椅-灰','AVATR定制保温杯','AVATR城市画展系列T恤衫',
      'AVATR户外折叠整理箱-灰','AVATR户外超声波防潮野餐地垫-灰','AVATR环保束口包','AVATR精品帆布包','AVATR杜邦电脑包','E值']
     for f_log in fls:
         table_sheet.write(row, 0, str(f_log['username']), style=c_style)
         table_sheet.write(row, 1, str(f_log['nick_name']), style=c_style)
         table_sheet.write(row, 2, str(f_log['dept_name']), style=c_style)
         table_sheet.write(row, 3, str(gifts[f_log['first_prize_level']]) if f_log['first_prize_level'] > 0 else '--', style=c_style)
         table_sheet.write(row, 4, str(gifts[f_log['second_prize_level']]) if f_log['second_prize_level'] > 0 else '--', style=c_style)
         row += 1
         if row > 50000:  # 单表数量超过 65535 条 添加新的表
             row = 1
             sheet_index += 1
             table_sheet = get_sheet(book, sheet_index)  # 添加sheet表
             write_head(header, table_sheet, h_style)
     sio = BytesIO()  # 返回文件流到浏览端下载，浏览端必须以form提交方式方能下载成功！
     book.save(sio)  # 这点很重要，传给save函数的不是保存文件名，而是一个StringIO流
     sio.seek(0)  # 保存流
     # 组装header
     headers = {"content-type": "application/vnd.ms-excel", "content-disposition": 'attachment;filename=download.xls'}
     # 以流的形式返回浏览器
     return StreamingResponse(sio, media_type="xls/xlsx", headers=headers)


"""
https://leetcode.com/problems/odd-even-linked-list/
https://leetcode.com/problems/odd-even-linked-list/solutions/2881889/python-o-n-o-1-short-lbyl-and-eafp-examples/
https://leetcode.com/problems/odd-even-linked-list/solutions/2881668/daily-leetcoding-challenge-december-day-6/comments/1706876
"""

from typing import Optional

from .. import ListNode

def odd_even_list(head: Optional[ListNode]) -> Optional[ListNode]:
  """
  EAFP style
  O(n) O(1)
  """
  if not head:
    return head
  odd, even, even_head = head, head.next, head.next
  while True:
    try:
      prev_odd = odd
      odd.next = odd = even.next
      even.next = even = odd.next
    except AttributeError:
      break
  odd = odd or prev_odd
  odd.next = even_head
  return head

def odd_even_list_2(head: Optional[ListNode]) -> Optional[ListNode]:
  """
  LBYL
  O(n) O(1)
  """
  if not head:
    return head
  odd, even, even_head = head, head.next, head.next
  while True:
    if not even:
      break
    prev_odd = odd
    odd.next = odd = even.next
    if not odd:
      odd = prev_odd
      break
    even.next = even = odd.next
  odd.next = even_head
  return head


from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

import argparse
import itertools
import os
import json
import codecs
import operator
import cPickle
import numpy as np

def parse_args():
    parser = argparse.ArgumentParser(
        description="Translate using existing NMT models",
        usage="translator.py [<args>] [-h | --help]"
    )

    # input files
    # parser.add_argument("--input", type=str, required=True,
    #                     help="Path of input file")

    # input files
    parser.add_argument("--source", type=str, default= None, required=False,
                        help="Path of source corpus")
    parser.add_argument("--output", type=str, required=True,
                        help="Path of output file")
    return parser.parse_args()

def main(args):
    source_sen = None
    with open(args.source, "r") as input_file:
        source_sen = [line.strip().split() for line in input_file]  # if line.strip()

    for word in source_sen[0]:
        print(word)
    # read file
#    restored_alignment = []
#    with open(args.align_file, "r") as align_file:
#        line = align_file.readline()
#        count = int(line)
#        alignment = cPickle.load(align_file)
#        while 1:
#            restored_alignment.append(alignment)
#            # count = int(align_file.readline())
#            # alignment = cPickle.load(align_file)
#            try:
#                count = int(align_file.readline())
#                alignment = cPickle.load(align_file)
#                #print(count, len(alignment))
#            except ValueError as ex:
#                #print(ex)
#                break
#    max_index_list = []
#    for i, alignment in enumerate(restored_alignment):
#        sens_max_index = []
#        for word_align in alignment:  # 每一句的每个target词对的align
#            layer_align = np.zeros([0, word_align["layer_0"].shape[2]])
#            for layerid in range(0, 6):
#                one_layer_align = word_align["layer_%d" % layerid]
#                one_layer_align = np.squeeze(one_layer_align, 0)  # 1 8 Sl remove the 1
#                one_layer_align = np.mean(one_layer_align, 0, keepdims=True)  # average on head
#                layer_align = np.concatenate([layer_align, one_layer_align], 0)
#            layer_align = np.mean(layer_align, 0)
#            layer_align = layer_align[:-1]  # remove eos
#            # sen = source_sen[i]
#            # # if sen[-1] == '。' and layer_align.shape > 2:
#            #     layer_align = layer_align[:-1]  # remove 。
#
#            max_index = np.argmax(layer_align)
#            max_v = layer_align[max_index]
#            sens_max_index.append((max_index, max_v))
#
#
#            # layer_align = word_align["layer_%d" % args.encdec_att_layer]
#            # layer_align = np.squeeze(layer_align, 0)  # 1 8 Sl remove the 1
#            # layer_align = np.mean(layer_align, 0)  # average on head
#            # layer_align = layer_align[:-1]  # remove eos
#            # max_index = np.argmax(layer_align)
#            # max_v = layer_align[max_index]
#            # sens_max_index.append((max_index, max_v))
#        max_index_list.append(sens_max_index)
#    constraints = None
#    if args.constraints is not None:
#        constraints = json.loads(codecs.open(args.constraints, encoding='utf8').read())
#
#
    file_output = open(args.output, "w")
    for i, sen in enumerate(target_sen):
        # if i ==25:
        #     print(i)
        # sp = ' '* (max_len+1)
        # print cons and source
        # first print cons x
        cons_src_list = []
        for word in source_sen[i]:
            cons_src_list.append(word)

        # for word in source_sen[i]:  # 空格无法与显示的汉字对齐
        #     cons_src_list.append(' '*len(word))
        if len(constraints[i]) != 0:
            sen_cons_tgt = ""
            for cons in constraints[i]:
                cons_tgt = " ".join(cons["tgt"])
                sen_cons_tgt = sen_cons_tgt + cons_tgt
                start = cons["src_pos"][0]
                end = cons["src_pos"][1]-1
                cons_src_list[start] = '[' + cons_src_list[start]
                cons_src_list[end] = cons_src_list[end] +']'
                # for pos in range(cons["src_pos"][0],cons["src_pos"][1]):
                #     cons_src_list[pos] = '[' + cons_src_list[pos][1:]
            print(sen_cons_tgt)

        cons_src = " ".join(cons_src_list)
        print("----------------------")
        print("%d   %s" % (i, cons_src))
        #  开始的打印target
        tgt_out_line = sen[:]
        sens_max_index = max_index_list[i]
        if len(sen) == 0:
            continue

        lens = [len(word) for word in sen]
        max_len = max(lens)

        for j, word in enumerate(tgt_out_line):
            try:
                max_index, _ = sens_max_index[j]
                tgt_out_line[j] = " "*(max_len-len(word)) + word + ":" + source_sen[i][max_index]
            except IndexError as ex:
                print(ex)
        # for cons in constraints[i]:
        #     src_start = cons["src_pos"][0]
        #     src_end = cons["src_pos"][1]
            #
            # start = cons["tgt_pos"][0]
            # end = cons["tgt_pos"][1]
            # for pos in range(start, end):
            #     tgt_out_line[pos] = tgt_out_line[pos]+'*'
            # tgt_out_line[start] = tgt_out_line[start] +"|   "+" ".join(cons["src"])
        for line in tgt_out_line:
            print(line)

    file_output.close()

        #
        #     count = 0
        #     for output, score, ratio in zip(restored_outputs, restored_scores, restored_ratio):
        #         decoded = []
        #         for idx in output:
        #             if idx == params.mapping["target"][params.eos]:
        #                 break
        #             decoded.append(vocab[idx])
        #         decoded = " ".join(decoded)
        #
        #         if not args.verbose:
        #             outfile.write("%s\n" % decoded)
        #         else:
        #             pattern = "%d ||| %s ||| %s ||| %f ||| %f ||| %d\n"
        #             source = restored_inputs[count]
        #             cons = restored_constraints[count]
        #             cons_token_num = 0
        #             for cons_item in cons:
        #                 cons_token_num+=cons_item["tgt_len"]
        #             values = (count, source, decoded, score, ratios[0], cons_token_num)
        #             outfile.write(pattern % values)
        #         count += 1
        #
        # with open(args.output+".alignment", "w") as outfile:
        #     count = 0
        #     for alignment in restored_alignment:
        #         outfile.write("%d\n" % count)
        #         cPickle.dump(alignment, outfile)
        #         count += 1
if __name__ == "__main__":
    main(parse_args())

        # for i, sen in enumerate(target_sen):
        #     print(i)
        #     lens = [len(word) for word in sen]
        #     max_len = max(lens)
        #     sp = ' '* (max_len+1)
        #     # print cons and source
        #     # first print cons x
        #     cons_src_list=[]
        #     for word in source_sen[i]:  # 空格无法与显示的汉字对齐
        #         cons_src_list.append(word)
        #
        #     # for word in source_sen[i]:  # 空格无法与显示的汉字对齐
        #     #     cons_src_list.append(' '*len(word))
        #     if len(constraints[i]) == 0:
        #         continue
        #     for cons in constraints[i]:
        #         start = cons["src_pos"][0]
        #         end = cons["src_pos"][1]-1
        #         cons_src_list[start] = '[' + cons_src_list[start]
        #         cons_src_list[end] = cons_src_list[end] +']'
        #         # for pos in range(cons["src_pos"][0],cons["src_pos"][1]):
        #         #     cons_src_list[pos] = '[' + cons_src_list[pos][1:]
        #     cons_src = sp + " ".join(cons_src_list)
        #     print(cons_src)
        #
        #     # src = " ".join(source_sen[i])
        #     # print(src)
        #     tgt_out_line = sen[:]
        #     for cons in constraints[i]:
        #         src_start = cons["src_pos"][0]
        #         src_end = cons["src_pos"][1]
        #
        #         start = cons["tgt_pos"][0]
        #         end = cons["tgt_pos"][1]
        #         for pos in range(start, end):
        #             tgt_out_line[pos] = tgt_out_line[pos]+'*'
        #         tgt_out_line[start] = tgt_out_line[start] +"    |   "+" ".join(cons["src"])
        #     for line in tgt_out_line:
        #         print(line)


import pickle
import numpy as np
from types import SimpleNamespace
from skimage import io
from scipy.ndimage import label

from segtools import nhl_tools, track_tools, trackmeasure
import networkx as nx
import matplotlib.pyplot as plt

import ipdb
from matplotlib.colors import ListedColormap

from glob import glob
import os
import ctypes

from numpy.ctypeslib import ndpointer

def loadlib():
  # base = "/Users/broaddus/Desktop/phd/thesis/src/zig/"
  base = "/Users/broaddus/Desktop/work/zig-tracker/"
  files = glob(base + "zig-cache/o/*/libtrack.dylib")
  files.sort(key=lambda x: os.path.getmtime(x))
  return ctypes.CDLL(files[-1])

lib = loadlib()

def strain_track(va,vb):
  va = va.astype(np.float32)
  vb = vb.astype(np.float32)
  va_ = va.ctypes.data_as(ctypes.POINTER(ctypes.c_float))
  vb_ = vb.ctypes.data_as(ctypes.POINTER(ctypes.c_float))
  parents = np.zeros(len(vb), dtype=np.int32)
  res_ = parents.ctypes.data_as(ctypes.POINTER(ctypes.c_int))
  # ipdb.set_trace()
  err = lib.strain_track2d(va_ , len(va) , vb_ , len(vb) , res_)
  if (err!=0): print("ERRORRRRRROROR")
  return parents

def greedy_track(va,vb):
  va = va.astype(np.float32)
  vb = vb.astype(np.float32)
  va_ = va.ctypes.data_as(ctypes.POINTER(ctypes.c_float))
  vb_ = vb.ctypes.data_as(ctypes.POINTER(ctypes.c_float))
  parents = np.zeros(len(vb), dtype=np.int32)
  res_ = parents.ctypes.data_as(ctypes.POINTER(ctypes.c_int))
  # err = lib.greedy_track2d.restype = ndpointer(dtype=ctypes.c_int32, shape=(len(vb),))
  err = lib.greedy_track2d(va_,len(va),vb_,len(vb), res_)
  if (err!=0): print("ERRORRRRRROROR")
  return parents

def build_S():

  img     = io.imread('data-raw/img003.tif')
  imgmean = img.mean((1,2), keepdims=True)
  img     = img/imgmean
  pimg    = np.load('data-raw/img003_Probabilities.npy')[...,0]
  lab     = np.array([label(x > 0.5)[0] for x in pimg])
  nhls    = nhl_tools.labs2nhls(lab, img)

  S = SimpleNamespace()
  S.img = img
  S.lab = lab
  S.pimg = pimg
  S.nhls = nhls
  S.ltps = [np.array([n['centroid'] for n in nhl]) for nhl in nhls]
  return S

## Build a GT true-branching from our special annotation labels
def add_gt_from_viewer(S,viewer=None):
  if viewer:
    gt = viewer.layers["img003-labels"].data
  else:
    gt = np.load("data-anno/img003-gt.npy")
  print(np.unique(gt))

  S.gt  = gt

  ## first build graphs
  G = SimpleNamespace()
  G.pts = dict()
  G.edges = dict()
  for t,lab_t in enumerate(S.gt):
    nhl = nhl_tools.hyp2nhl(lab_t,)
    for n in nhl:
      l = n['label']
      if t!=0:
        G.edges[(t,l)] = (t-1,l)
      G.pts[(t,l)] = n['centroid']

  G.tb = nx.from_edgelist(list(G.edges.items()), create_using=nx.DiGraph)
  G.tb = G.tb.reverse()

  for n in G.tb.nodes:
    G.tb.nodes[n]["pt"] = G.pts[n]
    print(G.tb.nodes[n])

  track_tools._tb_add_track_labels(G.tb)
  S.gt_G = G

## Compute the proposed tracking by using TbA on the ilastik detections
def add_tba_tracking(S):
  nhls = S.nhls
  def vertcost(vert): return -1
  def edgecost(vert1,vert2):
    # return -1
    u0 = np.array(vert1['centroid'])
    u1 = np.array(vert2['centroid'])
    return np.linalg.norm((u1-u0)/30)**2 - 1.0
    # return 0
  def straincost(u0, u1, v0, v1):
    du  = np.array(u1) - np.array(u0)
    dv  = np.array(v1) - np.array(v0)
    res = (np.linalg.norm(du - dv)/20) - 1.0
    return res

  factory = track_tools.TrackFactory(vertcost=vertcost, edgecost=edgecost, straincost=None, knn_n=10, allow_exit=True, allow_appear=True, neib_edge_cutoff=70, allow_div=True)
  # alltracks = [factory.nhls2tracking(nhls[i:i+2]) for i in range(len(nhls)-1)]
  tr = factory.nhls2tracking(nhls)
  # tr = track_tools.compose_trackings(factory, alltracks, nhls)
  # alltracksrev = [track_tools.nhls2tracking(nhls[i:i+2][::-1]) for i in range(len(nhls)-2)]
  track_tools.stats_tr(tr)

  ltpmap = [{v['label'] : v['centroid'] for v in nhl} for nhl in S.nhls]
  for n in tr.tb.nodes:
    tr.tb.nodes[n]['time'] = n[0]
    tr.tb.nodes[n]['pt']   = ltpmap[n[0]][n[1]]
  track_tools._tb_add_track_labels(tr.tb)

  S.test = tr
  """
  || name             || knn || vert || edge        || strain           || extra
  || test             || 10  || -1   || |d/30|^2 -1 || None             || in-place updates
  || tr_10            || 10  || -1   || |d/20|^2 -1 || None             || (identical to tr_4)
  || * tr_9           || 10  || -1   || -1          || |dx/20| - 1      || neib_edge_cutoff=70 (default)
  || tr_8             || 10  || -1   || -1          || |dx/40| - 1      || neib_edge_cutoff=70
  || tr_7             || 10  || -1   || -1          || |dx/70| - 1      || neib_edge_cutoff=70
  || tr_6             || 20  || -1   || |d/50|^2 -1 || None             ||
  || tr_5             || 10  || -1   || |d/20|^2 -1 || |d/40| -1        ||
  || tr_4             || 10  || -1   || |d/20|^2 -1 || None             ||
  || tr_3             || 10  || -1   || |d/80|^2 -1 || None             ||
  || tr_2             || 10  || -1   || |d/40|^2 -1 || None             ||
  || tr_1             || 10  ||  0   || 0           || (dx/40)^2 - 1    ||
  || tr_knn10_e2      || 10  || -1   || -1          || (dx/40)^2 - 1    ||
  || tr_knn10_novg    || 10  || -1   || -1          || None             ||
  || tr_knn10         || 10  || -1   || -1          || |dx/40| - 1      ||
  || tr_knn4          || 4   || -1   || -1          || |dx/40| - 1      ||
  || tr_knn6          || 6   || -1   || -1          || |dx/40| - 1      || exit=False enter=False
  || tr               || 2   || -1   || -1          || |dx/40| - 1      || exit=False enter=False

  !!! orig strain cost may have been |dx/20| - 1 with neib_edge_cutoff=40
  !!! [^1]: i'm not sure about these. may have been |dx/20| which was the original
  """

## Compute Nearest Neighbour tracking with distance-upper-bound
def add_nn_tracking(S):
  S.nn_tb = track_tools.nn_tracking_on_ltps(S.ltps,scale=[1,1],dub=50)

import napari

def viewer_add_tb(viewer,tb, name='kt_1'):
  nap = track_tools.tb2nap(tb)
  nap.properties['const'] = np.ones(nap.tracklets.shape[0])
  # nap.properties['const'][:-1] = 1
  # nap.properties['time'] = nap.tracklets[:,1]

  # ipdb.set_trace()
  # cmap = np.zeros([100,3])
  # cmap[:] = (255,255,0) ## yellow
  # cmap = ListedColormap(cmap)
  # cmap = napari.utils.colormaps.Colormap(cmap)
  # cmap = 'red'
  cmap = 'gray_r'
  # cmap = napari.utils.colormaps
  # cmap = napari.utils.colormaps.label_colormap()
  # cmap = napari.utils.colormaps.Colormap([(1, 1, 1, 1)]*(nap.tracklets.shape[0]+1), interpolation="zero")
  # cmap_dict = {'time':cmap}
  # cmap = 'blue'
  viewer.add_tracks(nap.tracklets,
                    graph=nap.graph,
                    properties=nap.properties,
                    name=name,
                    colormap=cmap,
                    blending='opaque',
                    tail_length=1,
                    tail_width=5,
                    # colormaps_dict=cmap_dict,
                    )

  # e0 = np.array([tb.nodes[e[0]]["pt"] for e in tb.edges])
  # e1 = np.array([tb.nodes[e[1]]["pt"] for e in tb.edges])
  # vecs = np.stack([e0,e1],axis=1)
  # ipdb.set_trace()
  # viewer.add_vectors(vecs)

def add_greedy_boring(S):
  parents_list = []
  for i in range(len(S.ltps)-1):
    va = S.ltps[i]
    vb = S.ltps[i+1]

    const = va.mean()
    va = va/const
    vb = vb/const

    parents = greedy_track(va,vb)
    parents_list.append(parents)

  ## fast, boring
  S.fb_tb = track_tools._parents2tb(parents_list,S.ltps)

def add_greedy_strain(S):
  parents_list = []
  for i in range(len(S.ltps)-1):
    va = S.ltps[i]
    vb = S.ltps[i+1]

    const = va.mean()
    va = va/const
    vb = vb/const

    parents = strain_track(va,vb)
    parents_list.append(parents)

  ## greedy, strain
  S.gs_tb = track_tools._parents2tb(parents_list,S.ltps)

def plot_compare_link_scores_over_time(S,viewer=None):
  gt_splits = []
  for i in range(8-1): ## t0
    g0 = S.gt_G.tb.subgraph([n for n in S.gt_G.tb.nodes if n[0] in {i,i+1}])
    gt_splits.append(g0)

  tbs = [
         (S.gs_tb,              "GreedyStrain",) ,
         (S.fb_tb,              "Fast Boring",) ,
         (S.nn_tb,              "NN",) ,
         # (S.tr_9.tb,            "TbA + Strain",) ,
         # (S.tr.tb,            "strain-2",) ,
         # (S.tr_knn6.tb,       "strain-6",) ,
         # (S.tr_knn4.tb,       "strain-4",) ,
         # (S.tr_knn10.tb,      "pure strain orig",) ,
         # (S.tr_knn10_novg.tb, "10 - no vg",) ,
         # (S.tr_knn10_e2.tb,   "10 - Quad",) ,
         # (S.tr_1.tb,          "0 V/E cost",) ,
         # (S.tr_4.tb,            "dist costs 20",) ,
         # (S.tr_3.tb,            "dist costs 80",) ,
         # (S.tr_2.tb,            "dist costs 40",) ,
         # (S.tr_6.tb,            "dist costs 50",) ,
         # (S.tr_5.tb,          "strain+dist costs",) ,
         # (S.tr_7.tb,          "pure strain 70",) ,
         # (S.tr_8.tb,          "pure strain 40",) ,
         # (S.tr_10.tb,           "dist costs 20 (2)"),
         (S.test.tb,            "TbA"),
         ]

  plt.figure()
  for k,(tb,label) in enumerate(tbs):
    scores = []
    for i in range(8-1):
      g = tb.subgraph([n for n in tb.nodes if n[0] in {i,i+1}])
      scores.append(trackmeasure.compare_tb(gt_splits[i], g)[3].recall_tra)
      # if label=="dist costs 20":
      #   plt.plot([s+0.01 for s in scores], '-o', alpha=1-0.05*k, label=label)
      # else:
    scores = [s + np.random.rand()*0.01 - 0.005 for s in scores]
    plt.plot(scores, '-o', alpha=1-0.05*k, label=label)
    if viewer:
      viewer_add_tb(viewer, tb, label)

  plt.legend()

def rerun():
  S = build_S()
  add_gt_from_viewer(S)
  # add_nn_tracking(S)
  # add_tba_tracking(S)
  add_greedy_strain(S)
  # add_greedy_boring(S)
  return S

if __name__=="__main__":
  S = rerun()


total_time = int(input())
scenes_count = int(input())
scene_duration = int(input())

shooting_time = scenes_count * scene_duration + 0.15 * total_time

diff = round(abs(total_time - shooting_time))
if shooting_time <= total_time:
    print(f"You managed to finish the movie on time! You have {diff} minutes left!")
else:
    print(f"Time is up! To complete the movie you need {diff} minutes.")


import pandas as pd
import chip2probe.modeler.plotlib as plot
import matplotlib.pyplot as plt
import numpy as np

import chip2probe.training_gen.arranalysis as arr

def plot_sctr(df, col1, col2, path, title, xlab, ylab, coop_x, coop_y):
    plt.clf()
    ax = plt.axes()
    df['label_x'] = df['label_x'].replace({'cooperative': coop_x})
    coop_df = df[df["label_y"] == "cooperative"]
    arr.plot_classified_labels(df, col1=col1, col2=col2, labelcol="label_x",  title=title, xlab=xlab, ylab=ylab, labelnames=[coop_x,"independent","anticoop"],axes=ax)
    x, y = np.log(coop_df[col1].values), np.log(coop_df[col2].values)
    ax.scatter(x, y, color="blue", s=1, label=coop_y)
    ax.legend(loc="lower right")
    plt.savefig(path)

def combine_ch_intensity(df1, df2):
    one_df = df1[["Name","ch1","label"]].merge(df2[["Name","ch2","label"]], on="Name")
    two_df = df1[["Name","ch1","label"]].merge(df2[["Name","ch2","label"]], on="Name")
    plot_sctr(one_df, "ch1", "ch2", "corr_one.png", "Main TF only", "Ets1 only", "Runx1 only", "ER-coop", "RE-coop")
    plot_sctr(two_df, "ch1", "ch2", "corr_two.png", "Main TF + cooperator", "Ets1-Runx1", "Runx1-Ets1", "ER-coop", "RE-coop")

if __name__ == "__main__":
    pd.set_option('display.max_columns', None)
    basepath = "/Users/vincentiusmartin/Research/chip2gcPBM/chip2probe/output/heterotypic/EtsRunx_v1"

    df1_label = pd.read_csv("%s/ch1_ch2/coop_ch1_vs_ch2/tables/both_ori_plt.csv" % basepath) \
            .rename(columns={"Alexa488Adjusted_x":"ch12_x","Alexa488Adjusted_y":"ch12_y"})[["Name","label"]]
    df2_label = pd.read_csv("%s/ch3_ch4/coop_ch3_vs_ch4/tables/both_ori_plt.csv" % basepath) \
            .rename(columns={"Alexa488Adjusted_x":"ch34_x","Alexa488Adjusted_y":"ch34_y"})[["Name","label"]]

    df1_er = pd.read_csv("%s/ch1_ch2/coop_ch1_vs_ch2/tables/probes_labeled_er.csv" % basepath)[["Name", "ch1", "ch2", "ori"]]
    df1_re = pd.read_csv("%s/ch1_ch2/coop_ch1_vs_ch2/tables/probes_labeled_re.csv" % basepath)[["Name", "ch1", "ch2", "ori"]]
    df1 = pd.concat([df1_er, df1_re]).groupby(["Name","ori"]).median().reset_index().merge(df1_label, on="Name")

    df2_er = pd.read_csv("%s/ch3_ch4/coop_ch3_vs_ch4/tables/probes_labeled_er.csv" % basepath)[["Name", "ch1", "ch2", "ori"]]
    df2_re = pd.read_csv("%s/ch3_ch4/coop_ch3_vs_ch4/tables/probes_labeled_re.csv" % basepath)[["Name", "ch1", "ch2", "ori"]]
    df2 = pd.concat([df2_er, df2_re]).groupby(["Name","ori"]).median().reset_index().merge(df2_label, on="Name")

    arr.plot_classified_labels(df2, path="aaa.png", col1="ch1", col2="ch2", labelcol="label",  title="Ets_Runx1", xlab="Ch1", ylab="Ch2", labelnames=["cooperative","independent","anticoop"], )

    #combine_ch_intensity(df1, df2)

    """
    train_ch1 = pd.read_csv("%s/ch1_ch2/training_pwm.tsv" % basepath, sep="\t")
    train_ch2 = pd.read_csv("%s/ch3_ch4/training_pwm.tsv" % basepath, sep="\t")

    print("Chamber 1-2")
    print(df1.groupby("label")["ets_score"].count())

    print("Chamber 3-4")
    print(df2.groupby("label")["runx_score"].count())

    df2_additive_names = df2[df2["label"] == "independent"][["Name"]]
    df_both_add = df1[df1["label"] == "independent"].merge(df2_additive_names, on=["Name"])
    df2_coop = df2[df2["label"] == "cooperative"]
    df1_coop = df1[df1["label"] == "cooperative"]

    dft = pd.concat([df1_coop, df2_coop, df_both_add]).drop_duplicates()
    print(dft.groupby("label")["ets_score"].count())
    dft.to_csv("train_all.tsv",sep="\t",index=False)

    plot.plot_stacked_categories(dft, "distance", path="distance_bar.png", title="Distance distribution", ratio=True)
    plot.plot_stacked_categories(dft, "orientation", path="ori_bar.png", title="Relative sites orientation\ndistribution", ratio=True)
    plot.plot_box_categories(dft, incols=["runx_score","ets_score"], alternative="smaller")
    """


#Reto Empleados Unal

#Igresar el nombre

"""
nombreTrabajador = " "

nombreTrabajador = input("Por favor ingrese su nombre: ")

valorBruto = int(input("Por favor ingrese el valor bruto devengado"))

tipoDeContrato = input("Por favor especifique su tipo de contrato, contratista o de planta: ")

if tipoDeContrato is True:
    tipoDeContrato == "contratista"
        tipoHonorarios = input("Su contrato es por Honorarios o Servicios?")
        if tipoHonorarios is True:
            tipoHonorarios == "Honorarios"
            print("Usted es contratista por honorarios")

"""
#Solucion profesor
SALARIO_MINIMO_LEGAL_VIGENTE = 908526
def calcularparafiscalesEmpresa(contratista,salario):
    sena=0
    ICBF = 0
    ccf = 0
    salud = 0
    pension = 0
    subsidioTransporte = 0.0
    if contratista == 2:
        sena = salario * 2/100
        ICBF = salario * 3/100
        ccf = salario * 4/100
        salud = salario * 8.5/100
        pension = salario * 12/100
        if salario <= SALARIO_MINIMO_LEGAL_VIGENTE*2:
            subsidioTransporte = 106453.0
    return [sena,ICBF,ccf,salud,pension,subsidioTransporte]

def calcularparafiscalesEmpleado (contratista, salario):
    salud = 0
    pension = 0
    if contratista == 1:
        baseGravable = salario * 40/100
        if (baseGravable <SALARIO_MINIMO_LEGAL_VIGENTE):
            baseGravable = SALARIO_MINIMO_LEGAL_VIGENTE
        salud = baseGravable * 12.5 /100
        pension = baseGravable * 16/100
    else:
        salud = salario * 4/100
        pension = salario * 4/100
    return [salud,pension]

def calcularretencionFuente(declarante,honoriarios,salario):
    retencion = 0
    if declarante:
        if honorarios:
            retencion = salario * 11/100
        else:
            retencion = salario * 4/100

    else:
        if honorarios:
            retencion = salario *10/100
        else:
            retencion = salario *6/100

parafiscalesEmpresa = [0,0,0,0,0,0]
parafiscalesEmpleado = [0,0]
retencionDeFuente = 0

nombreTrabajador = ""
salario = 0.0
contratista = 0
valorTotalARetener = 0.0
total = 0.0

arregloTotal = ()

while True:
    for trabajador in arregloTotal:
        print(trabajador)
        nombreTrabajador = input("Ingrese el nombre del trabajador: ")
        salario = float(input("Salario a devengar del trabajador: "))
        contratista = int(input("Ingrese 1 para contratista, 2 para personal de planta: "))
        if contratista == 1:
            declarante = input("A. Declarante de Renta, B. No declarante de renta")
            honorarios = input("1. Honorarios, 2. Servicios")
            if declarante == "A":
                declarante = True
            else:
                declarante = False

            if honorarios == "1":
                honorarios = True
            else:
                honorarios = False
                retencionDeFuente = calcularretencionFuente(declarante,honorarios,salario)
        else:
            retencion = 0

        parafiscalesEmpresa = calcularparafiscalesEmpresa(contratista,salario)
        parafiscalesEmpleado = calcularparafiscalesEmpleado(contratista,salario)
        retencionDeFuente = calcularretencionFuente(declarante,honorarios,salario)

        dataTrabajador = {"nombre":nombreTrabajador,"salario":salario,"parafiscalesEmpresa": parafiscalesEmpresa, "parafiscalesEmpleado":parafiscalesEmpleado}
        arregloTotal.append(dataTrabajador)
        print("El trabajador: ",nombreTrabajador,", con salario de: ", salario,", a la empresa le corresponde: ",  )


from django.db import models
from django.core.validators import MaxLengthValidator
from rest_framework.validators import UniqueValidator

class SongModel(models.Model):
    song_id = models.IntegerField(unique=True,primary_key=True)
    song_name = models.CharField(blank=False,max_length=100, validators=[MaxLengthValidator])
    song_duration = models.PositiveIntegerField(blank=False)
    upload_time = models.DateTimeField(auto_now_add=True)

class PodcastModel(models.Model):
    podcast_id = models.IntegerField(unique=True, primary_key=True,blank=False)
    podcast_name = models.CharField(blank=False,max_length=100,validators=[MaxLengthValidator])
    podcast_duration = models.PositiveIntegerField(blank=False)
    upload_time = models.DateTimeField(auto_now_add=True)
    podcast_host = models.CharField(max_length=100,validators=[MaxLengthValidator], blank=False)
    podcast_participant = models.TextField(null=True, blank=True)

class AudioBookModel(models.Model):
    audiobook_id = models.IntegerField(unique=True,primary_key=True)
    audiobook_title = models.CharField(max_length=100,validators=[MaxLengthValidator], blank=False)
    title_author = models.CharField(max_length=100,validators=[MaxLengthValidator],blank=False)
    audiobook_narrator = models.CharField(max_length=100, validators=[MaxLengthValidator],blank=False)
    upload_time = models.DateTimeField(auto_now_add=True)


from django.contrib import admin
#from SocialNetworkModels.models import Author, Posts
from SocialNetworkModels.models import Author, Posts, Friends, FriendManager, Follows, FollowManager, FriendManager,Nodes, Comments
from django.contrib.auth.models import User
from django.contrib.auth.admin import UserAdmin

class AuthorInLine(admin.StackedInline):
    model = Author
    list_display = ('approved')

class UserAdmin(admin.ModelAdmin):
    inlines = [AuthorInLine]
    list_display = ('username', 'email', 'first_name', 'last_name', 'approved')

    def approved(self, obj):
        return obj.post_author.approved
    approved.admin_order_field = 'approved'
    approved.boolean = True

admin.site.unregister(User)
admin.site.register(User, UserAdmin)
admin.site.register(Author)
admin.site.register(Follows)
admin.site.register(Posts)
admin.site.register(Friends)
admin.site.register(Nodes)
admin.site.register(Comments)


#%%
names_list = ['Arie' ,'Jimmy', 'John', 'Marco', 'Danny', 'Peter']

new_names_list = []

vowels = 'aeouiy'

for name in names_list:
    for vowel in vowels:
        if vowel in name:
            name = name.replace(vowel, "")

    new_names_list.append(name)

#%%
new_names_list

# %%
names_list = ['Arie' ,'Jimmy', 'John', 'Marco', 'Danny', 'Peter']

new_names_list = []

vowels = 'aeouiy'

for name in names_list:
    new_name = ""
    for letter in name:
        if letter.lower() not in vowels:
            new_name += letter

    new_names_list.append(new_name)

# %%
from datetime import date, timedelta

current_date = date.today()

for day_num in range(1, 11):
    next_date = current_date + timedelta(days=day_num)
    next_day = next_date.strftime(f"Over {day_num} dagen is het: %A")
    print(next_day)

# %%


from gensim.models import Doc2Vec
import pickle

from tqdm import tqdm

def save_data_from_doc2vec(filename, model):
    data_csv = open(filename + '.csv', 'w', encoding='utf-8')
    print('Save file: {}'.format(filename + '.csv'))
    data_csv_string = ''
    for index, one_vector in tqdm(enumerate(model.docvecs.vectors_docs)):
        row_result = ','.join([str(value) for value in one_vector])
        data_csv_string += row_result + '\n'

    data_csv.write(data_csv_string[:-1])
    data_csv.close()
    print('Save file: {} DONE'.format(filename + '.csv'))

if __name__ == "__main__":
    print('Loading processed documents...')
    fullDatasetDocs = pickle.load(open('preparation4doc2vec.pkl', 'rb'))
    print('Loading processed documents... DONE')

    search_params = {'vector_size' : [50,100,150],
                     'window' : [5,10,15],
                     'min_count' : [1,3,5,10],
                     'negative' : [5,10]}

    current_params = {'min_count' : 1,
                      'negative' : 5 ,
                      'workers' : 4}

    for vector_size in search_params['vector_size']:
        for window_size in search_params['window']:
            current_params['vector_size'] = vector_size
            current_params['window'] = window_size
            model = Doc2Vec(**current_params)
            print('Model declaration: {}'.format(model))
            print('Building vocabulary for model...')
            model.build_vocab(fullDatasetDocs)
            print('Building vocabulary for model... DONE')
            print('Training model...')
            model.train(fullDatasetDocs, epochs=20, total_examples=len(fullDatasetDocs))
            print('Training model... DONE')
            save_data_from_doc2vec('doc2vec_data_size_{}_window_{}'.format(vector_size, window_size), model)


# Created by rahman at 11:06 2020-02-22 using PyCharm
import tensorflow as tf
tf.random.set_seed(3)

#if tf.test.is_built_with_cuda or tf.__version__ == '2.1.0':
from tensorflow import keras

k_init = tf.keras.initializers.Constant(value=0.1)
b_init = keras.initializers.Constant(value=0)
r_init = keras.initializers.Constant(value=0.1)

from tensorflow.keras import backend as K
from tensorflow.keras.callbacks import EarlyStopping, ModelCheckpoint
from tensorflow.keras.layers import Dropout, Dense, Conv1D, MaxPooling1D, Flatten , LSTM, Bidirectional, Reshape

from tensorflow.keras import Sequential, utils, Input, Model

#if tf.__version__ != '2.1.0':
    #import keras.layers.CuDNNLSTM

"""import keras
from keras.callbacks import EarlyStopping, ModelCheckpoint
from keras.layers import Dropout, Dense, Conv1D, MaxPooling1D, Flatten, Reshape, LSTM
from keras import Sequential, utils, Input, Model"""

from keras.utils.vis_utils import plot_model

import logging
import math

class BinaryDNN:

    def __init__(self, num_layers = 2, layer_params=[[0.5, 0.2], [0.25, 0]], num_epochs=100, batch_size=64, verbose=0):
        """

        :param num_layers: just for a sanity check
        :param layer_params: list of size 2 lists, containing [layer size factor, dropout] for each layer
        :param num_epochs:
        :param batch_size:
        """

        assert(num_layers == len(layer_params))

        self.num_layers = num_layers
        self.layer_params = layer_params
        self.num_epochs = num_epochs
        self.batch_size = batch_size
        self.verbose = verbose

        self.logger = logging.getLogger("DnnClassifier")

    def fit(self, X_train, y_train):

        dim = X_train.shape[1]

        self.model = Sequential()

        for factor, dropout in self.layer_params:

            self.model.add(Dense(int(dim * factor if dim * factor > 1 else 1), input_dim=dim, activation='relu'))
            self.model.add(Dropout(dropout))

        self.model.add(Dense(1, activation='sigmoid'))
        self.model.compile(optimizer='adam', loss='binary_crossentropy',  metrics=['accuracy'])

        if self.verbose!=0:

            self.model.summary()

        #y_keras= utils.to_categorical(y_train, 2)
        es = EarlyStopping(monitor='val_loss', mode='auto', verbose=1, patience=30, restore_best_weights=True)
        self.model.fit(X_train, y_train, epochs = self.num_epochs, batch_size = self.batch_size, verbose=self.verbose, callbacks=[es])

    def predict(self, X_test):

        y_pred = self.model.predict(X_test, verbose=True)

        return (y_pred > 0.5)

class SiameseClassifier:

    def __init__(self, shape, regu, combi, time_dim=0):

        self.time_dim = time_dim
        self.regu =  keras.regularizers.l2(regu)
        self.combi = combi

        #self.l_a and self.l_b will be defined in the child constructors
        if len(shape)==3:

            assert(self.time_dim==1)
            self.num_features = shape[2]
            self.num_timesteps = shape[1]

            self.sample_a = Input(shape=(self.num_timesteps, self.num_features))
            self.sample_b = Input(shape=(self.num_timesteps, self.num_features))

        elif len(shape)==2: #it is an old style vecframe

            self.num_features = shape[1]-2

            self.sample_a = Input(shape=(self.num_features,))
            self.sample_b = Input(shape=(self.num_features,))

    def combine(self, plot=False):

        if self.combi=='l1':

            difference = keras.layers.subtract([self.l_a, self.l_b])
            combined = keras.layers.Lambda(tensorabs)(difference)  # in general: absolute value: abs(<tensor>)

        elif self.combi=='mul':

            combined = keras.layers.multiply([self.l_a, self.l_b])
            #combined = keras.layers.Lambda(tensorabs)(difference)  # in general: absolute value: abs(<tensor>)

        elif self.combi == 'avg':

            combined = keras.layers.average([self.l_a, self.l_b])
            #combined = keras.layers.Lambda(tensorabs)(difference)  # in general: absolute value: abs(<tensor>)

        elif self.combi == 'sql2':

            #combined = keras.layers.average([l_a2, l_b2])
            combined = keras.layers.Lambda(lambda x: (x[0] - x[1]) ** 2 )([self.l_a, self.l_b])

        predictions = Dense(1, activation='sigmoid')(combined)

        self.model = tf.keras.Model(inputs=[self.sample_a, self.sample_b], outputs=predictions)

        self.model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy', tf.keras.metrics.AUC()])

        print(self.model.summary())

        if plot:
            plot_model(self.model, to_file='siam.png', show_shapes=True, show_layer_names=True)

    def fit_predict(self, link, batchsize, epochs, verbose=0):

        self.model.fit([link.vecframe.loc[link.tr_pairs.i].iloc[:, 2:], link.vecframe.loc[link.tr_pairs.j].iloc[:, 2:]],
                           link.tr_pairs.label,
                           batch_size=batchsize, epochs=epochs,
                           validation_data=([link.vecframe.loc[link.te_pairs.i].iloc[:, 2:], link.vecframe.loc[link.te_pairs.j].iloc[:, 2:]],
                           link.te_pairs.label), verbose=verbose)

        y_pred = self.model.predict([link.vecframe.loc[link.te_pairs.i].iloc[:, 2:], link.vecframe.loc[link.te_pairs.j].iloc[:, 2:]],
                                        verbose=verbose)

        from sklearn.metrics import roc_auc_score

        auc = roc_auc_score(link.te_pairs.label, y_pred)

        return auc

    def fit_predict_callback(self, link, batchsize, epochs, patience, verbose=0):

        es = EarlyStopping(monitor='val_loss', mode='auto', verbose=1, patience=patience, restore_best_weights=True)
        #mc = ModelCheckpoint('best_model.h5', monitor='val_acc', mode='max', verbose=1, save_best_only=True)
        print (self.model.layers)

        if self.time_dim: #link.vecframe is actually just a 3d arrary, not dataframe
            self.model.fit([link.vecframe[link.tr_pairs.i][:, :], link.vecframe[link.tr_pairs.j][:, :]],
                           link.tr_pairs.label,
                           batch_size=batchsize, epochs=epochs,
                           validation_data=(
                           [link.vecframe[link.te_pairs.i][:, :], link.vecframe[link.te_pairs.j][:, :]],
                           link.te_pairs.label), verbose=verbose,
                           callbacks=[es]) #, mc
            y_pred = self.model.predict(
                [link.vecframe[link.te_pairs.i][:, :], link.vecframe[link.te_pairs.j][:, :]],
                verbose=verbose)

        else:

            self.model.fit([link.vecframe.loc[link.tr_pairs.i].iloc[:, 2:], link.vecframe.loc[link.tr_pairs.j].iloc[:, 2:]],
                       link.tr_pairs.label,
                       batch_size=batchsize, epochs=epochs,
                       validation_data=(
                       [link.vecframe.loc[link.te_pairs.i].iloc[:, 2:], link.vecframe.loc[link.te_pairs.j].iloc[:, 2:]],
                       link.te_pairs.label), verbose=verbose,
                       callbacks=[es]) #, mc
            y_pred = self.model.predict(
                [link.vecframe.loc[link.te_pairs.i].iloc[:, 2:], link.vecframe.loc[link.te_pairs.j].iloc[:, 2:]],
                verbose=verbose)

        #layer_name = 'attention' its layer 8
        """for layer in self.model.layers[2:]:  # all layer outputs

            print(layer)

            intermediate_layer_model = keras.Model(inputs=self.model.input,
                                               outputs=layer.output)

            test_a = tf.ones((1,12))
            test_b = tf.ones((1,12))
            intermediate_output = intermediate_layer_model.predict([test_a, test_b])

            print (intermediate_output[0])"""

        #saved_model = load_model('best_model.h5')

        from sklearn.metrics import roc_auc_score

        auc = roc_auc_score(link.te_pairs.label, y_pred)

        return auc

class Dense_siameseClassifier(SiameseClassifier):

    def __init__(self, shape, regu, combi, dense_params):

        super().__init__(shape, regu, combi)

        half_num_features = int(math.floor(self.num_features * dense_params[0]) if self.num_features>=2 else 1)
        shared_dense1 = Dense(half_num_features, input_shape=(self.num_features,),
                              activation='relu') #, kernel_initializer=k_init, bias_initializer=b_init

        if self.regu != None:
            shared_dense1.kernel_regularizer = self.regu

        l_a = shared_dense1(self.sample_a)
        l_b = shared_dense1(self.sample_b)

        quater_num_features = int(math.floor(self.num_features * dense_params[1]) if self.num_features>=4 else 1)
        shared_dense2 = Dense(quater_num_features, input_shape=(half_num_features,),
                              activation='relu') #, kernel_initializer=k_init, bias_initializer=b_init

        if self.regu != None:
            shared_dense2.kernel_regularizer = self.regu

        l_a2 = shared_dense2(l_a)
        l_b2 = shared_dense2(l_b)

        self.l_a = l_a2
        self.l_b = l_b2

class LSTMsiameseClassifier(SiameseClassifier):

    def __init__(self, num_timesteps, regu, combi, time_dim, lstm_params, fixed_units=True):
        super().__init__(num_timesteps, regu, combi, time_dim)

        shared_nn = Sequential()

        shared_nn.add(Reshape((num_timesteps, 1), input_shape=(num_timesteps,)))

        if len(lstm_params)==2:

            param_0 = lstm_params[0]

            units = param_0[0]

            shared_nn.add(LSTM(units, return_sequences=True, input_shape=(num_timesteps, 1),\
                               kernel_initializer=k_init, bias_initializer=b_init, recurrent_initializer=r_init))
            shared_nn.add(Dropout(param_0[1]))

            param_1 = lstm_params[1]
            units = param_1[0]

            shared_nn.add(LSTM(units, kernel_initializer=k_init, bias_initializer=b_init, recurrent_initializer=r_init))
            shared_nn.add(Dropout(param_1[1]))

        elif len(lstm_params)==1:

            param_0 = lstm_params[0]

            units = param_0[0] if fixed_units else (int(math.floor(num_timesteps * param_0[0])) if num_timesteps >= 4 else 1)

            shared_nn.add(LSTM(units,input_shape=(num_timesteps, 1), \
                               kernel_initializer=k_init, bias_initializer=b_init, recurrent_initializer=r_init))
            shared_nn.add(Dropout(param_0[1]))

        self.l_a = shared_nn(self.sample_a)
        self.l_b = shared_nn(self.sample_b)

class BiLSTMsiameseClassifier(SiameseClassifier):

    def __init__(self, num_timesteps, regu, combi, lstm_params, fixed_units=True):
        super().__init__(num_timesteps, regu, combi)

        shared_nn = Sequential()

        shared_nn.add(Reshape((num_timesteps, 1), input_shape=(num_timesteps,)))

        if len(lstm_params)==2:

            param_0 = lstm_params[0]

            units = param_0[0]

            shared_nn.add(Bidirectional(LSTM(units, return_sequences=True, input_shape=(num_timesteps, 1),\
                               kernel_initializer=k_init, bias_initializer=b_init, recurrent_initializer=r_init)))
            shared_nn.add(Dropout(param_0[1]))

            param_1 = lstm_params[1]
            units = param_1[0]

            shared_nn.add(Bidirectional(LSTM(units, kernel_initializer=k_init, bias_initializer=b_init, recurrent_initializer=r_init)))
            shared_nn.add(Dropout(param_1[1]))

        elif len(lstm_params)==1:

            param_0 = lstm_params[0]

            units = param_0[0] if fixed_units else (int(math.floor(num_timesteps * param_0[0])) if num_timesteps >= 4 else 1)

            shared_nn.add(Bidirectional(LSTM(units,input_shape=(num_timesteps, 1), \
                               kernel_initializer=k_init, bias_initializer=b_init, recurrent_initializer=r_init)))
            shared_nn.add(Dropout(param_0[1]))

        self.l_a = shared_nn(self.sample_a)
        self.l_b = shared_nn(self.sample_b)

"""class Attention(tf.keras.Model):

    def __init__(self, units):
        super(Attention, self).__init__()

        self.W1 = tf.keras.layers.Dense(units)
        self.W2 = tf.keras.layers.Dense(units)
        self.V = tf.keras.layers.Dense(1)

    def call(self, features, hidden):

        hidden_with_time_axis = tf.expand_dims(hidden, 1)
        score = tf.nn.tanh(self.W1(features) + self.W2(hidden_with_time_axis))
        attention_weights = tf.nn.softmax(self.V(score), axis=1)
        context_vector = attention_weights * features
        context_vector = tf.reduce_sum(context_vector, axis=1)
        return context_vector, attention_weights

max_len = 200
rnn_cell_size = 128
vocab_size=250"""

#https://medium.com/@sanjivgautamofficial/lstm-in-keras-56a59264c0b2
#https://www.coursera.org/lecture/nlp-sequence-models/attention-model-lSwVa
#The original idea of attention uses the output of the decoder as h_t, representing "current decoding state".
# If you think of the "many-to-one" problem as a special case of the "many-to-many" problem, h_t becomes the last hidden state of the encoder.
#https://github.com/tensorflow/tensorflow/issues/39332
"""class AttentionBiLSTMClassifier(SiameseClassifier):

    def __init__(self, num_timesteps, regu, combi, lstm_params, fixed_units=True):
        super().__init__(num_timesteps, regu, combi)

        units, dropout = lstm_params[0][0],  lstm_params[0][1]
        shared = []

        for sample in [self.sample_a, self.sample_b]:

            sample = tf.keras.layers.Reshape((num_timesteps, 1), input_shape=(num_timesteps,))(sample)

            lstm, forward_h, forward_c, backward_h, backward_c = tf.keras.layers.Bidirectional \
                (tf.keras.layers.LSTM
                 (units,
                  dropout= dropout,
                  return_sequences=True,
                  return_state=True,
                  recurrent_activation='relu',
                  recurrent_initializer='glorot_uniform'))(sample)

            state_h = tf.keras.layers.Concatenate()([forward_h, backward_h])
            #state_c = tf.keras.layers.Concatenate()([forward_c, backward_c])

            # Query-value attention of shape [batch_size, Tq, filters].
            query_value_attention_seq = tf.keras.layers.Attention()([lstm, state_h])

            query_value_attention = tf.keras.layers.GlobalAveragePooling1D()(
                query_value_attention_seq)

            #output = keras.layers.Dense(1, activation='sigmoid')(context_vector)

            #model = keras.Model(inputs=sequence_input, outputs=output)

            # summarize layers
            #print(model.summary())
            shared.append(query_value_attention)

        self.l_a = shared[0]
        self.l_b = shared[1]
"""

class AttentionBiLSTMClassifier(SiameseClassifier):

    def __init__(self, shape, regu, combi, time_dim, lstm_params, fixed_units=True):
        super().__init__(shape, regu, combi, time_dim)

        units, dropout = lstm_params[0][0],  lstm_params[0][1]

        shared = []

        for sample in [self.sample_a, self.sample_b]:

            sample = tf.keras.layers.Reshape((self.num_timesteps, self.num_features), input_shape=(self.num_timesteps, self.num_features))(sample)

            lstm, forward_h, forward_c, backward_h, backward_c = tf.keras.layers.Bidirectional(LSTM(units,input_shape=(self.num_timesteps, self.num_features), \
                               kernel_initializer=k_init, bias_initializer=b_init, recurrent_initializer=r_init, return_sequences=True, return_state=True))(sample)

            state_h = tf.keras.layers.Concatenate()([forward_h, backward_h])
            # state_c = tf.keras.layers.Concatenate()([forward_c, backward_c])

            # Query-value attention of shape [batch_size, Tq, filters].
            query_value_attention_seq = tf.keras.layers.Attention()([state_h, lstm])

            query_value_attention = tf.keras.layers.GlobalAveragePooling1D()(
                query_value_attention_seq)

            shared.append(query_value_attention)

        self.l_a = shared[0]
        self.l_b = shared[1]

def GlobalAttention(hidden_states):
    # hidden_states.shape = (batch_size, time_steps, hidden_size)
    hidden_size = int(hidden_states.shape[2])
    # Inside dense layer
    #              hidden_states            dot               W            =>           score_first_part
    # (batch_size, time_steps, hidden_size) dot (hidden_size, hidden_size) => (batch_size, time_steps, hidden_size)
    # W is the trainable weight matrix of attention
    # Luong's multiplicative style score
    score_first_part = Dense(hidden_size, use_bias=False, name='attention_score_vec')(hidden_states)
    #            score_first_part           dot        last_hidden_state     => attention_weights
    # (batch_size, time_steps, hidden_size) dot   (batch_size, hidden_size)  => (batch_size, time_steps)
    h_t = tf.keras.layers.Lambda(lambda x: x[:, -1, :], output_shape=(hidden_size,), name='last_hidden_state')(
        hidden_states)
    score = tf.keras.layers.Dot([score_first_part, h_t], [2, 1], name='attention_score')
    attention_weights = tf.keras.layers.Activation('softmax', name='attention_weight')(score)
    # (batch_size, time_steps, hidden_size) dot (batch_size, time_steps) => (batch_size, hidden_size)
    context_vector = tf.keras.layers.Dot([hidden_states, attention_weights], [1, 1], name='context_vector')
    pre_activation = tf.keras.layers.Concatenate([context_vector, h_t], name='attention_output')
    attention_vector = Dense(128, use_bias=False, activation='tanh',
                             name='attention_vector')(
        pre_activation)
    return attention_vector

class GlobalAttentionBiLSTMClassifier(SiameseClassifier):

    def __init__(self, num_timesteps, regu, combi, lstm_params, fixed_units=True):
        super().__init__(num_timesteps, regu, combi)

        units, dropout = lstm_params[0][0],  lstm_params[0][1]

        shared = []

        for sample in [self.sample_a, self.sample_b]:

            sample = tf.keras.layers.Reshape((num_timesteps, 1), input_shape=(num_timesteps,))(sample)

            lstm_out = tf.keras.layers.Bidirectional(LSTM(units,input_shape=(num_timesteps, 1), \
                               kernel_initializer=k_init, bias_initializer=b_init, recurrent_initializer=r_init, return_sequences=True))(sample)

            # Query-value attention of shape [batch_size, Tq, filters].
            attention = tf.keras.layers.GlobalAttention(lstm_out)

            shared.append(attention)

        self.l_a = shared[0]
        self.l_b = shared[1]

def tensorabs(t):
    return abs(t)

class CNNsiameseClassifier(SiameseClassifier):

    def __init__(self, shape, regu, combi, cnn_params):

        super().__init__(shape, regu, combi)

        (filt1, ker1), (filt2, ker2), pool, num_maxpools = cnn_params

        assert (num_maxpools in [1, 2])

        shared_conv1 = Sequential()

        shared_conv1.add(Reshape((self.num_features, 1), input_shape=(self.num_features,)))

        shared_conv1.add(Conv1D(filters=filt1, kernel_size=ker1, activation='relu', kernel_regularizer=self.regu, padding='same'))

        if num_maxpools==2:

            shared_conv1.add(MaxPooling1D(pool_size=pool))

        shared_conv1.add(Conv1D(filters=filt2, kernel_size=ker2, activation='relu', kernel_regularizer=self.regu, padding='same'))

        shared_conv1.add(MaxPooling1D(pool_size=pool))

        shared_conv1.add(Flatten())

        shared_conv1.add(Dense(100, activation='relu'))

        self.l_a = shared_conv1(self.sample_a)
        self.l_b = shared_conv1(self.sample_b)


import sqlite3
import jieba
import numpy as np
from wordcloud import WordCloud
from PIL import Image
from matplotlib import pyplot as plt

con = sqlite3.connect('../database/douban_top250.db')
cur = con.cursor()
sql = 'select introduction from douban250'
data = cur.execute(sql)
text = ""
for item in data:
    text = text + item[0]
cur.close()
con.close()

cut = jieba.cut(text)
cut_text = ' '.join(cut)

img_array = np.array(Image.open(r'./static/assets/img/mask.jpg'))
wc = WordCloud(
    background_color='white',
    mask=img_array,
    font_path="msyhl.ttc"
).generate_from_text(cut_text)

fig = plt.figure(1)
plt.imshow(wc)
plt.axis('off')
# plt.show()
plt.savefig(r'./static/assets/img/wordcloud.jpg', dpi=500)


from random import choice  # импорт функции выбора случайного слова

def get_jokes(n, flag=False):
    """Функция возвращает n шуток, сформированных из трех случайных слов,
    взятых из трёх списков (по одному из каждого). Если аргумент flag = True, то запрещается повтор в шутках
    (каждое слово может использоваться только один раз)"""
    jokes_list = []
    for i in range(n):  # выбираем по одному слову из списков и формируем строку
        random_index = choice(nouns)
        random_index_1 = choice(adverbs)
        random_index_2 = choice(adjectives)
        joke = f'{random_index} {random_index_1} {random_index_2}'
        if flag:  # Если flag=True проверяем слова шуток на совпадения
            list_2 = joke.split()
            for noun in nouns:
                for fun in list_2:
                    if noun == fun:
                        nouns.remove(noun)

            for adverb in adverbs:
                for fun in list_2:
                    if adverb == fun:
                        adverbs.remove(adverb)

            for adjective in adjectives:
                for fun in list_2:
                    if adjective == fun:
                        adjectives.remove(adjective)
        jokes_list.append(joke)  # добавляем строку в список
    return jokes_list

nouns = ["автомобиль", "лес", "огонь", "город", "дом"]
adverbs = ["сегодня", "вчера", "завтра", "позавчера", "ночью"]
adjectives = ["веселый", "яркий", "зеленый", "утопичный", "мягкий"]
result = get_jokes(n=2, flag=True)
print(result)


# by Richi Rod AKA @richionline / falken20

import os
import logging
from django.shortcuts import render
from django.utils.timezone import now
from django.http import HttpResponse, HttpResponseRedirect

from .utils import scrap_web
from .models import CountryItem, CityItem, WeatherDataItem

URL_WEATHER = 'http://meteomad.net/estaciones/cercedilla/cercedilla.htm'

def weather_view(request):
    """ For getting temperature data from scrapping climate web and showing."""

    logging.info(f'{os.getenv("ID_LOG", "")} Showing the weather screen')

    # Getting a dataframe with the all data weather
    df_weather = scrap_web(URL_WEATHER)

    dict_weather = df_weather.to_dict(orient='records')

    # TODO: In some momment the city should be choosed by the user
    city = 'Cercedilla'

    return render(request, 'house/weather.html', {'data_weather': dict_weather, 'city': city, 'time': now()})

def country_form(request):
    """ Show the form for adding countries """

    logging.info(f'{os.getenv("ID_LOG", "")} Showing the country form')

    queryset_country = CountryItem.objects.all().order_by('country_name')
    template_name = 'house/country_form.html'

    # If it comes for adding another item
    message = ''
    if request.GET.get('status', None) == 'OK':
        message = 'Country successfully saved!!'

    return render(request, template_name, {'countries': queryset_country, 'message': message})

def add_country(request):
    """ Insert a new country in DB """

    logging.info(f'{os.getenv("ID_LOG", "")} Starting to add a country in the DB')

    country_item = CountryItem(country_name=request.POST['country_name']).save()

    logging.info(f'{os.getenv("ID_LOG", "")} Country "{country_item}" successfully saved in the DB')

    return HttpResponseRedirect('/house/new_country?status=OK')

def city_form(request):
    """ Show the form for adding cities """

    logging.info(f'{os.getenv("ID_LOG", "")} Showing the cities form')

    template_name = 'house/city_form.html'
    queryset_country = CountryItem.objects.all().order_by('country_name')
    queryset_city = CityItem.objects.all().order_by('city_name')

    # If it comes for adding another item
    message = ''
    if request.GET.get('status', None) == 'OK':
        message = 'Country successfully saved!!'

    return render(request, template_name, {'countries': queryset_country,
                                           'cities': queryset_city,
                                           'message': message})

def add_city(request):
    """ Insert a new city in DB """

    logging.info(f'{os.getenv("ID_LOG", "")} Starting to add a city in the DB')

    # Get the country item
    country_item = CountryItem.objects.get(id=request.POST['country_id'])

    city_item = CityItem(city_name=request.POST['city_name'],
                         country_name=country_item,
                         weather_url=request.POST['weather_url']).save()

    logging.info(f'{os.getenv("ID_LOG", "")} City "{city_item}" successfully saved in the DB')

    return HttpResponseRedirect('/house/new_city?status=OK')

def weather_report_view(request):
    """ Show last weather data in the DB """

    logging.info(f'{os.getenv("ID_LOG", "")} Starting to show weather data day')

    template_name = 'house/weather_report.html'
    today = now()
    queryset = WeatherDataItem.objects.filter(weather_date__year=today.year,
                                              weather_date__month=today.month,
                                              weather_date__day=today.day).order_by('-weather_date')
    if queryset:
        city = queryset[0].city_name
    else:
        city = 'No data for today'

    return render(request, template_name, {'weather_data': queryset, 'city': city})


# -*- coding: utf-8 -*-
"""
Created on Fri Oct 16 14:33:34 2020

@author: d.nguyen
"""

import dask.dataframe as dd
from dask import compute
from dask.distributed import Client, LocalCluster
from dask.diagnostics import ProgressBar
import os.path
import re
from pathlib import Path
from glob import glob
from timeit import default_timer as timer
from datetime import timedelta
import numpy as np
import tkinter as tk
from tkinter import filedialog
import pandas as pd
userhome = os.path.expanduser('~')
save_path = os.path.join( userhome,'Desktop')
save_path = os.path.join(save_path,'RESULT')
Path(save_path).mkdir(parents=True, exist_ok=True)
os.chdir(save_path)

root = tk.Tk()
root.withdraw()
filepath = filedialog.askopenfilename(title="Select ANNONCES data")
root.update()
annonces = dd.read_csv(filepath, header=0, sep='|', quoting=3, dtype='object', encoding='utf-8', na_values=([' ','']))

root = tk.Tk()
root.withdraw()
filepath = filedialog.askopenfilename(title="Select PROS data")
root.update()
df_pros = pd.read_csv(filepath, header=0, sep='|', quoting=3, dtype='str', encoding='utf-8', na_values=([' ',''])).fillna('')

#annonces = dd.read_csv(r'D:\25. Requests\IMMO_FR processing script\ANNONCES_2020_08.csv', header=0, sep='|', quoting=3, dtype='object', encoding='utf-8', na_values=([' ','']))
#df_pros = pd.read_csv(r'D:\25. Requests\IMMO_FR processing script\PRO_2020_08.csv', header=0, sep='|', quoting=3, dtype='str', encoding='utf-8', na_values=([' ',''])).fillna('')

start = timer()

print("Start exporting")
#EXPORT PERCENTAGE OF NULL/MISSING VALUES PER WEBSITES
print("Export: emptiness_per_website.xlsx")
column_list = annonces.columns.tolist()

websites = annonces['SITE_ANNONCE'].unique().compute().tolist()
print("There are {} websites".format(len(websites)))
pct_missing_per_website = pd.DataFrame()
with ProgressBar():
    for website in websites:
        print(website)
        temp_df = annonces[annonces['SITE_ANNONCE']==website].compute()
        temp_null_count = temp_df.isnull().sum()
        temp_site_count = len(temp_df.index)
        pct_missing_per_website[website] = round(temp_null_count/temp_site_count*100,2)
pct_missing_per_website.to_excel(os.path.join(save_path ,'emptiness_per_website.xlsx'))

#EXPORT PERCENTAGE OF TOTAL NULL/MISSING VALUES
print("Export: emptiness_total.xlsx")
with ProgressBar():
    null_count_total = annonces.isnull().sum().compute()
    total_length = len(annonces.index)
    null_percent_total = round(null_count_total/len(annonces.index),2)
total_missing = pd.concat([null_count_total, null_percent_total], axis = 1)
total_missing.columns = ['Empty_Count','Empty_pct']
total_missing.to_excel(os.path.join(save_path ,'emptiness_total.xlsx'))

#EXPORT GENERAL REPORT
print("Export: seloger_reporting_check_results.xlsx")
writer = pd.ExcelWriter(os.path.join(save_path, 'seloger_reporting_check_results.xlsx'), engine='xlsxwriter')
with ProgressBar():
    df_1 = annonces.groupby(["SITE_ANNONCE","TYPE_ANNONCEUR","TYPE_TRANSACTION","CATEGORIE_BIEN"])['URL_ANNONCE'].count().compute()
    df_2 = annonces["SITE_ANNONCE"].value_counts().compute()
    df_3 = annonces[annonces['ID_AUTOBIZ']!='0'].groupby('SITE_ANNONCE')['ID_AUTOBIZ'].nunique().compute()
    df_4 = df_pros["ACTIVITE_PRO"].value_counts()
df_1.to_excel(writer,sheet_name='ads_detailed_repartition')
df_2.to_excel(writer,sheet_name="nb_ads_per_website")
df_3.to_excel(writer,sheet_name="nb_dealers_per_website")
df_4.to_excel(writer,sheet_name="pros_activities")
writer.save()

#FUNCTIONS
def fix_utf8(line):
    if not pd.isnull(line):
        try: line=line.encode('latin-1').decode('utf-8')
        except: line=line.encode('ascii', 'ignore').decode('utf-8')
    else: line=''
    return line

def fix_encoding_error(df, columns):
    for column in columns:
        df[column] = df[column].apply(lambda x: fix_utf8(x))

def fix_encoding_error_dask(df, columns):
    for column in columns:
        df[column] = df[column].apply(lambda x: fix_utf8(x), meta=('str'))

def fix_general(df,column,arg,meta=None):
    if meta: return df[column].apply(lambda x: "" if eval(arg) else x, meta=meta)
    else: return df[column].apply(lambda x: "" if eval(arg) else x)

def write_to_excel(write_engine, sheetnames):
    for sheetname in sheetnames:
        (eval(sheetname)).to_excel(write_engine,sheet_name=sheetname)

def adresse_fix(name):
    try:
        if "www." in name: return ""
        else: return name
    except TypeError: return ""

def fix_digit(dd, columns):
    for column in columns:
        dd[column] = dd[column].apply(lambda x : np.int64(int(x)) if not pd.isnull(x) else "" ,meta=('np.int64'))

def DATE_CRAWL_ANNONCE(name):
    if re.match(r'10/[0-1][0-9]/2[0-9]',name) or re.match(r'15/[0-1][0-9]/2[0-9]',name):
        return name
    else: return name.replace(r'^\d{2}','15')
#PROCESSING PROS FILE
print("\n" + "Begin processing PROS")
'''
• ID_TIERS_AUTOBIZ : count if the variable has values=0 and show the line of the db
• colonne DATE_MAJ_FICHE_PRO : count if values = null or = 00/00/00 and show the line of the db
• ADRESSE1_PRO : count if something starts by www. or http. If yes, show the values and show the line of the db.
• ADRESSE2_PRO : idem
• CP_PRO : count the cells with values which have more than 5 Numbers. Show these values and show the line of the db.
• DEPT_PRO : we sometimes do have incoherent values (ve, th, su...) so we need to count them if something is different than 2 Numbers and show the line of the db.
• VILLE_PRO : check if there are Numbers. If yes, show the values and show the line of the db.
• TEL_PRO : Check if there is something different than Numbers. If yes, show the values and show the line of the db.
• EMAIL_PRO : Count if there are url (www.promoca.fr) or numbers (503676421). If yes, show the line of the db.
• SITE_WEB_PRO : Check if Something starts by Something different than "www". If yes, show the values and show the line of the db.
• CODE_NAF_PRO : Check if string is other than format of 3-4 numbers with 1 last character (3235A, 245C) If yes, show the values and show the line of the db.
*output delivery:
-If id_tiers_autobiz=0 delete the line
-When found errors as the ones mentioned above, substitute the value by na.
'''
list_champ_pros=['ADRESSE1_PRO', 'ADRESSE2_PRO', 'VILLE_PRO','REGION_PRO','NOUVELLE_REGION_PRO','RAISON_SOCIALE','NOM_COMMERCIAL','ACTIVITE_PRO','NOM_CONTACT','PRENOM_CONTACT']
fix_encoding_error(df_pros,list_champ_pros)
id_tiers_autobiz = df_pros[df_pros['ID_TIERS_AUTOBIZ']=="0"]
adresse1_pro_error = df_pros['ADRESSE1_PRO'][df_pros['ADRESSE1_PRO'].str.contains("www.|http",na=False)]
adresse2_pro_error = df_pros['ADRESSE2_PRO'][df_pros['ADRESSE2_PRO'].str.contains("www.|http",na=False)]
cp_pro_error = df_pros['CP_PRO'][df_pros['CP_PRO'].str.len()>6]
dept_pro_error = df_pros['DEPT_PRO'][(df_pros['DEPT_PRO'].str.match('^\"[0-9]{2}$') == False) & (df_pros['DEPT_PRO'] != "")]
ville_pro_error = df_pros['VILLE_PRO'][df_pros['VILLE_PRO'].str.match(r'.*[0-9]')]
tel_pro_error = df_pros['TEL_PRO'][df_pros['TEL_PRO'].str.match(r'.*[a-zA-Z]')]
email_pro_error = df_pros['EMAIL_PRO'][(df_pros['EMAIL_PRO'].str.match(r'.*www')) | (df_pros['EMAIL_PRO'].str.match(r'^.*[0-9]{5,}$'))]
site_web_pro_error = df_pros['SITE_WEB_PRO'][(df_pros['SITE_WEB_PRO'].str.match(r'^.*[.com,.fr]')==False) & (df_pros['SITE_WEB_PRO'] != "")]
code_naf_pro_error = df_pros['CODE_NAF_PRO'][(df_pros['CODE_NAF_PRO'].str.match(r'^[0-9]{3,4}[A-Z]{1}$')==False) & (df_pros['CODE_NAF_PRO'] != "")]

writer_pro = pd.ExcelWriter(os.path.join(save_path, 'pro_check_results.xlsx'), engine='xlsxwriter', options={'strings_to_urls': False})  # assign excel file to write result
pro_check_list = ['id_tiers_autobiz', 'adresse1_pro_error', 'adresse2_pro_error', 'cp_pro_error', 'dept_pro_error',
                  'ville_pro_error', 'tel_pro_error', 'email_pro_error', 'site_web_pro_error', 'code_naf_pro_error']
write_to_excel(writer_pro,pro_check_list)
writer_pro.save()
print("pro_check_results.xlsx has been written in RESULT folder")
df_pros['DATE_MAJ_FICHE_PRO'] = fix_general(df_pros,'DATE_MAJ_FICHE_PRO',"x == '00/00/00'")
df_pros['ADRESSE1_PRO'] = fix_general(df_pros,'ADRESSE1_PRO','("www." in x) or ("http" in x)')
df_pros['ADRESSE2_PRO'] = fix_general(df_pros,'ADRESSE2_PRO','("www." in x) or ("http" in x)')
df_pros['CP_PRO'] = fix_general(df_pros,'CP_PRO','len(x)>6')
df_pros['DEPT_PRO'] = fix_general(df_pros,'DEPT_PRO',"not re.match(r'^\"[0-9]{2}$',x)")
df_pros['VILLE_PRO'] = fix_general(df_pros,'VILLE_PRO',"re.match(r'.*[0-9]',x)")
df_pros['TEL_PRO'] = fix_general(df_pros,'TEL_PRO',"re.match(r'.*[a-zA-Z]',x)")
df_pros['EMAIL_PRO'] = fix_general(df_pros,'EMAIL_PRO',"(re.match(r'.*www',x)) or (re.match(r'^.*[0-9]{5,}$',x))")
df_pros['SITE_WEB_PRO'] = fix_general(df_pros,'SITE_WEB_PRO',"not re.match(r'^.*[.com,.fr]',x)")
df_pros['CODE_NAF_PRO'] = fix_general(df_pros,'CODE_NAF_PRO',"not re.match(r'^[0-9]{4}[A-Z]{1}$',x)")
#EXPORT PRO FILE
df_pros.to_csv('PROS_preventif.csv',sep="|",quoting=3,index=False)
print("PROS_preventif.csv has been saved in {}.".format(save_path) + "\n")
del df_pros

#PROCESSING ANNONCES FILE
print("\n" + "Begin processing ANNONCES")
'''
DATE_CRAWL_ANNONCE -> We must only have variables 10/mm/20 or 15/mm/20 . If Something different, transform to 15/mm/20
DESCRIPTION_ANNONCE-> substitute special characters for readeable ones
CP_ANNONCE -> if Something different to a number, substitute by emptyness
VILLE_ANNONCE-> substitute special characters for readeable ones. If something different to a name, make empty.
ADRESSE_ANNONCE-> substitute special characters for readeable ones. If there is www. Substitute by empty.
REGION_ANNONCE-> substitute special characters for readeable ones. If something different to a name, make empty.
NOUVELLE_REGION_ANNONCE-> substitute special characters for readeable ones. If something different to a name, make empty.
PRIX ;surface_terrain ;surface_bien ;nb_photos ;nb_pieces -> only digits format X and not X.XX
'''
annonces['DATE_CRAWL_ANNONCE'] = annonces['DATE_CRAWL_ANNONCE'].apply(lambda x: DATE_CRAWL_ANNONCE(x),meta=('object'))
annonces['CP_ANNONCE'] = fix_general(annonces,'CP_ANNONCE',"not re.match(r'^[\"]{0,1}[0-9]+$',str(x))", meta=('object'))
annonces['ADRESSE_ANNONCE'] = annonces['ADRESSE_ANNONCE'].apply(lambda x : adresse_fix(x), meta=('object'))
columns_to_fix_encoding = ['DESCRIPTION_ANNONCE','VILLE_ANNONCE','ADRESSE_ANNONCE','REGION_ANNONCE','NOUVELLE_REGION_ANNONCE']
columns_to_fix_digit = ['PRIX','SURFACE_TERRAIN','SURFACE_BIEN','NB_PHOTOS','NB_PIECES']
fix_encoding_error_dask(annonces, columns_to_fix_encoding)
fix_digit(annonces, columns_to_fix_digit)

#EXPORT ANNONCES FILE
print("Start writing ANNONCES final")
print("Length of original ANNONCES: " + str(total_length))
annonces = annonces.repartition(npartitions=50)
print("Numbers of partitions: " + str(annonces.npartitions))
print("Write partitions to RESULT folder")

with ProgressBar():
    annonces.to_csv(os.path.join(save_path,'ANNONCES_PREVENTIF*.csv'),sep="|",index=False)
print("Start concatenating {} partitions into 1 ANNONCES file".format(str(annonces.npartitions)))
filenames = glob(os.path.join(save_path,'ANNONCES_PREVENTIF*.csv'))
n=0
with open('ANNONCES_PREVENTIF_final.csv','a',encoding='utf-8') as out_file:
    for in_file in filenames:
        n+=1
        with open(in_file,'r',encoding='utf-8') as infile:
            if n>1:
               next(infile)
            for line in infile:
                if line[-1] != '\n': line += '\n'
                out_file.write(line)
        os.remove(os.path.join(save_path,in_file))
out_file.close()
print("ANNONCES_preventif_final.csv has been saved in {}.".format(save_path))
print("Checking if lengh of final matches with total length of {} partitions".format(str(annonces.npartitions)))
re_check = dd.read_csv('ANNONCES_PREVENTIF_final.csv', header=0, sep='|', quoting=3, dtype='object', encoding='utf-8', na_values=([' ','']))
print("Length of final output is:", len(re_check.index))

del re_check
del annonces
end = timer()
print("Total running time: ", timedelta(seconds=end-start))


#!/usr/bin/python3
"""Square class"""

class Square:
    """define size
    Arguments:
        size: size of a square
    """
    def __init__(self, size=0, position=(0, 0)):
        if type(size) is not int:
            raise TypeError("size must be an integer")
        elif size < 0:
            raise ValueError("size must be >= 0")
        elif type(position) is not tuple or len(position) != 2:
            raise TypeError("position must be a tuple of 2 positive integers")
        elif type(position[0]) is not int or position[0] < 0:
            raise TypeError("position must be a tuple of 2 positive integers")
        elif type(position[1]) is not int or position[1] < 0:
            raise TypeError("position must be a tuple of 2 positive integers")

        self.__size = size
        self.__position = position

    def area(self):
        """area of square"""
        return self.__size ** 2

    def my_print(self):
        if self.size > 0:
            if self.position[1] > 0:
                for newline in range(self.position[1]):
                    print("")
            for row in range(self.size):
                if self.position[0] > 0:
                    for spaces in range(self.position[0]):
                        print(" ", end="")
                for collumn in range(self.size):
                    print("#", end="")
                print("")
        else:
            print("")

    @property
    def size(self):
        """getter function"""
        return self.__size

    @size.setter
    def size(self, value):
        """setter size function"""
        if type(value) is not int:
            raise TypeError("size must be an integer")
        elif value < 0:
            raise ValueError("size must be >= 0")
        self.__size = value

    @property
    def position(self):
        """positional value"""
        return self.__position

    @position.setter
    def position(self, value):
        """position setter"""
        if type(value) is not tuple or len(value) != 2:
            raise TypeError("position must be a tuple of 2 positive integers")
        elif type(value) is not int or value[0] < 0:
            raise TypeError("position must be a tuple of 2 positive integers")
        elif type(value) is not int or value[1] < 0:
            raise TypeError("position must be a tuple of 2 positive integers")
        else:
            self.__position = value


import sys
import collections
input = sys.stdin.readline

N = int(input())
answer = N*100

que = collections.deque([])

for i in range(N):
    x,y  = map(int, input().split(" "))
    x2 = x + 10
    y2 = y + 10
    que.append([x,x2,y,y2])

while que :
    x , x2 , y, y2 = que.popleft()
    for i in que :
        check_x = abs(x - i[0]) + abs(x2- i[1])
        check_y = abs(y -i[2]) + abs(y2-i[3])
        if check_x <= 18 and check_y <= 18 :
            answer -= (10 -check_x//2)*(10 -check_y//2)

print(answer)


"""klubpilkarski URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/1.8/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  url(r'^$', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  url(r'^$', Home.as_view(), name='home')
Including another URLconf
    1. Add a URL to urlpatterns:  url(r'^blog/', include('blog.urls'))
"""
from django.conf.urls import include, url
from django.conf.urls.i18n import i18n_patterns
from django.contrib import admin
from django.contrib.auth import views
from django.template import context
from club.forms import LoginForm
from club.views import *

urlpatterns = [
    url(r'^i18n/', include('django.conf.urls.i18n')),
    url(r'^admin/', include(admin.site.urls))
]

urlpatterns += i18n_patterns(
    url(r'^$', home, name='home'),
    url(r'^players$', PlayersView.as_view(), name='players'),
    url(r'^players/filter-players$', PlayersView.filter_players, name='filter-players'),
    url(r'^players/(?P<player_slug>[a-zA-Z0-9\-]+)$', PlayerDetailsView.as_view(), name='player-details'),
    url(r'^employees$', EmployeesView.as_view(), name='employees'),
    url(r'^employees/filter-employees$', EmployeesView.filter_employees, name='filter-employees'),
    url(r'^employees/(?P<employee_slug>[a-zA-Z0-9\-]+)$', EmployeeDetailsView.as_view(), name='employee-details'),
    url(r'^trophies$', TrophiesView.as_view(), name='trophies'),
    url(r'^trophies/filter-trophies$', TrophiesView.filter_trophies, name='filter-trophies'),
    url(r'^lineups$', LineupsView.as_view(), name='lineups'),
    url(r'^lineups/(?P<pk>\d+)/$', LineupDetailsView.as_view(), name='lineup-details'),
    url(r'^games/(?P<season_id>\d+)/(?P<fixture_id>\d+)/$', GamesView.as_view(), name='games'),
    url(r'^games/(?P<season_id>\d+)/(?P<fixture_id>\d+)/filter-games$', GamesView.filter_games,
        name='filter-games'),
    url(r'^games/(?P<game_slug>[a-zA-Z0-9\-]+)$', GameDetailsView.as_view(), name='game-details'),
    url(r'^login/$', views.login, {'template_name': 'login.html', 'authentication_form': LoginForm,
                                   'extra_context': {'page': 'login'}}, name='login'),
    url(r'^logout/$', views.logout, {'next_page': '/login'}, name='logout')
)

INF/Inżynieria Systemów Baz Danych/klubpilkarski/urls.py