from django.shortcuts import render

from .database import connect_db
from .config import *

import datetime
import json
import numpy as np

# Controller Views
class RecommendFacebook:
    '''
    generate recommendations for Facebook ads
    '''

    def __init__(self):
        self.db = connect_db('diana')
        self.fbadaccounts = self.db['fbadaccounts']
        self.fbads = self.db['fbads']
        self.fbinsights = self.db['fbinsights']
        self.config = self.db['config'].find_one({"for": "recommend"})
        self.contents = []
        self.content = {}

    def recommend_for_report(self):
        users = list(self.db['users'].find(
            {"type": "facebook"}
        ))
        for user in users:

            user_member_true = self.db['members'].find_one(
                {
                    "user_id": user['user_id'],
                    "receive_notifications": True,
                }
            )
            if not user_member_true:
                continue

            ## for test ##
            # user['email'] = 'tony.hwang@wizpace.com'

            if not user['email']:
                user['email'] = 'tony.hwang@wizpace.com'
            self.content = {
                "user_id": user['user_id'],
                "network_id": user['network_id'],
                "username": user['name'],
                "user_email": [user_member_true['email']],
                "facebook": {
                    "ads": [],
                },
                "lang": 'en',
            }

            # long access token expiry check
            # if long access token will be expired within 7 days

            adaccounts = self.get_adaccounts()

            for adaccount in adaccounts:
                self.content['lang'] = self.get_lang(adaccount)
                ads = self.get_ads(adaccount)

                if ads:
                    for ad in ads:
                        self.recommend_ad(ad)

            self.contents.append(self.content)
            # print(self.content)

        print(self.contents)
        print("recommend_for_report done: {}".format(datetime.datetime.now()))
        return self.contents

    def get_adaccounts(self):
        adaccounts = list(self.fbadaccounts.find(
            {
                "user_id": self.content['user_id'],
                "yesterday.spend": {"$gt": 0},
            }
        ))
        return adaccounts

    def get_ads(self, adaccount):
        ads = list(self.fbads.find(
            {
                "account_id": adaccount['account_id'],
                "yesterday.spend": {"$gt": 0},
            }
        ))
        self.content['facebook']['ads'] += ads
        return ads

    def recommend_ad(self, ad):
        ad['recos'] = []
        data_7days = list(self.fbinsights.find(
            {
                "ad_id": ad['ad_id'],
                "publisher_platform": "facebook",
                "date_stop": {"$gte": datetime.datetime.now() - datetime.timedelta(days=7)}
            }
        ))[-7:]

        # for yesterday
        if len(data_7days) >= 1:
            data = data_7days[-1:]
            self.ctr_check(data, ad)
            self.limit_check(data, ad)
            print("yesterday check done")

        # for at most last 7days
        if len(data_7days) >= 3:
            data = data_7days[-7:]
            self.frequency_check(data, ad)
            print("last 7days check done")

        # for at least last 3days
        if len(data_7days) >= 2:
            data = data_7days[-3:]
            self.spend_check(data, ad)
            self.cpm_check(data, ad)
            self.cpc_check(data, ad)
            self.relevance_score_check(data, ad)
            print("last 3days check done")

        print("recommend_ad done: {}".format(datetime.datetime.now()))
        return ad['recos']

    def ctr_check(self, data, ad):
        score = 0
        if 'relevance_score' in data[0]:
            if 'score' in data[0]['relevance_score']:
                score = int(data[0]['relevance_score']['score'])
        ctr = round(data[0]['ctr'], 2)
        bound_clicks_ctr = 0
        if 'inline_link_click_ctr' in data[0]:
            bound_clicks_ctr = round(
                data[0]['inline_link_click_ctr'], 2)
        if 'outbound_clicks_ctr' in data[0]:
            bound_clicks_ctr = round(
                data[0]['outbound_clicks_ctr'], 2)

        if ctr < self.config['conditions']['ctr'] and score <= 5:
            # 전체 클릭률 4% 이하이고, 관련성 점수가 5 이하일 때,
            reco = self.config['recos'][self.content['lang']]['ctr_bad']
            self.append_reco(reco, ad)

        if bound_clicks_ctr:
            if bound_clicks_ctr < self.config['conditions']['bound_clicks_ctr'] and score <= 5:
                # 바운드 클릭률 2% 이하이고, 관련성 점수가 5 이하이면,
                if data[0]['canvas_avg_view_percent']:
                    # 캔버스 기능이 있으면,
                    reco = self.config['recos'][self.content['lang']
                                 ]['bound_clicks_ctr_bad_with_canvas']
                    self.append_reco(reco, ad)
                    return self.content
                # 캔버스가 없으면,
                reco = self.config['recos'][self.content['lang']
                             ]['bound_clicks_ctr_bad_no_canvas']
                self.append_reco(reco, ad)

        print("ctr_check done: {}".format(datetime.datetime.now()))
        return self.content

    def limit_check(self, data, ad):
        cpm = data[0]['cpm']
        if cpm > self.config['conditions']['cpm_limit']:
            reco = self.config['recos'][self.content['lang']]['cpm_limit']
            self.append_reco(reco, ad)

        print("limit_check done: {}".format(datetime.datetime.now()))
        return self.content

    def frequency_check(self, data, ad):
        frequencies = [_data['frequency'] for _data in data]
        avg_frequency = np.mean(frequencies)

        if avg_frequency > self.config['conditions']['frequency_limit']:
            reco = self.config['recos'][self.content['lang']]['frequency_limit']
            self.append_reco(reco, ad)

        print("frequency_check done: {}".format(datetime.datetime.now()))
        return self.content

    def spend_check(self, data, ad):
        spends = [_data['spend'] for _data in data]

        # 전날 대비 지출의 급격한 상승 체크
        if spends[-1] >= spends[-2] * self.config['conditions']['spend_times_for_boom'] and spends[-1] >= self.config['conditions']['spend_min_for_check']:
            reco = self.config['recos'][self.content['lang']]['spend_boom']
            self.append_reco(reco, ad)

        # 지출 급격한 변화 체크에는 최소 3일간 데이터가 필요
        if len(spends) < self.config['conditions']['spend_length']:
            print("not enough spends data: {}".format(len(spends)))
            return self.content

        avg_spend = np.mean(spends)
        std_spend = np.std(spends)

        # 평균과 지출의 변화 정도를 비교
        if std_spend > avg_spend:
            # 지출의 변동이 심하면, (평균 이상이면)
            if spends[-3] > spends[-2] and spends[-2] > spends[-1]:
                reco = self.config['recos'][self.content['lang']]['spend_down']
            elif spends[-3] < spends[-2] and spends[-2] < spends[-1]:
                reco = self.config['recos'][self.content['lang']]['spend_up']
            else:
                reco = self.config['recos'][self.content['lang']]['spend_unstable']
            self.append_reco(reco, ad)

        print("spend_check done: {}".format(datetime.datetime.now()))
        return self.content

    def cpm_check(self, data, ad):
        cpms = [_data['cpm'] for _data in data]

        if len(cpms) < self.config['conditions']['cpm_length']:
            print("not enough cpms data: {}".format(len(cpms)))
            return self.content

        avg_cpm = np.mean(cpms)

        for cpm in cpms:
            # 하루 cpm이 최근 n일간 cpm 평균의 1.5배를 넘으면,
            if cpm > avg_cpm * self.config['conditions']['cpm_avg_limit']:
                reco = self.config['recos'][self.content['lang']]['cpm_avg_limit']
                self.append_reco(reco, ad)
            # 가장 최근일의 cpm이 cpm 평균의 2.0배를 넘으면,
            elif cpms[-1] > avg_cpm * self.config['conditions']['cpm_limit']:
                reco = self.config['recos'][self.content['lang']]['cpm_limit']
                self.append_reco(reco, ad)
            else:
                pass

        print("cpm_check done: {}".format(datetime.datetime.now()))
        return self.content

    def cpc_check(self, data, ad):
        cpcs = [_data['cost_per_inline_link_click'] for _data in data]

        if len(cpcs) < self.config['conditions']['cpc_length']:
            print("not enough cpcs data: {}".format(len(cpcs)))
            return self.content

        avg_cpc = np.mean(cpcs)

        # 지출은 있으나, 모든 cpc가 0일 경우 = 링크 클릭이 발생하지 않을 경우,
        if not any(cpcs):
            reco = str(len(cpcs)) + \
                self.config['recos'][self.content['lang']]['no_link_click']
            self.append_reco(reco, ad)
        else:
            # 가장 최근일의 cpm이 cpm 평균의 2.0배를 넘으면,
            if cpcs[-1] > avg_cpc * self.config['conditions']['cpc_limit']:
                reco = self.config['recos'][self.content['lang']]['cpc_limit']
                self.append_reco(reco, ad)

        print("cpc_check done: {}".format(datetime.datetime.now()))
        return self.content

    def relevance_score_check(self, data, ad):
        if 'relevance_score' in data[-1]:
            if 'score' in data[-1]['relevance_score']:
                relevance_score = data[-1]['relevance_score']['score']
                if relevance_score in ['1', '2', '3']:
                    reco = self.config['recos'][self.content['lang']]['relevance_score']
                    self.append_reco(reco, ad)

        print("relevance_score_check done: {}".format(datetime.datetime.now()))
        return self.content

    def append_reco(self, reco, ad):
        recos = ad['recos']
        if not reco in recos:
            recos.append(reco)
        return ad

    def get_lang(self, adaccount):
        lang = 'en'
        if adaccount['currency'] == 'KRW':
            lang = 'kr'
        return lang

    def update_recommendations(self):
        '''
        update recommendations of every keyword with data of 7days and yesterday
        '''
        self.content = {
            "facebook": {
                "recos": [],
            },
            "lang": 'en',
        }

        # 지난 1주일 동안 0원 이상 사용했던 ads 리스트
        ads = self.fbads.find({"last_week.spend": {"$gt": 0}})
        for ad in ads:
            adaccount = self.fbadaccounts.find_one(
                {"account_id": ad['account_id']})
            self.content['lang'] = self.get_lang(adaccount)
            recos = self.recommend_ad(ad)
            self.fbads.update_one(
                {
                    "user_id": ad['user_id'],
                    "ad_id": ad['ad_id'],
                },
                {"$set": {"recommendation": recos}}
            )
            print(recos)
        print("update_recommendations done: {}".format(datetime.datetime.now()))
        return self.content['facebook']['recos']

class RecommendNaver:
    '''
    generate recommendations for daily report
    '''

    def __init__(self):
        self.db = connect_db('diana')
        self.members = self.db['members']
        self.nvkeywords = self.db['nvkeywords']
        self.nvaccounts = self.db['nvaccounts']
        self.nvstats = self.db['nvstats']
        self.config = self.db['config']
        self.config_for_recommend = self.config.find_one({"for": "recommend"})
        self.contents = []
        self.content = {}

    def recommend_for_report(self):
        users = list(self.db['users'].find(
            {"type": "naver"},
        ))
        for user in users:

            user_member_true = self.members.find_one(
                {
                    "user_id": user['user_id'],
                    "receive_notifications": True,
                }
            )
            if not user_member_true:
                continue

            # default email value
            # user_email = "tony.hwang@wizpace.com"
            user_email = ""
            if user_member_true:
                user_email = user_member_true['email']

            adaccounts = self.nvaccounts.find(
                {"user_id": user['user_id']},
            )

            for adaccount in adaccounts:
                self.content = {
                    "user_id": user['user_id'],
                    "username": user['name'],
                    "user_email": [user_email],
                    "customer_id": adaccount['client_customer_id'],
                    "naver": {},
                }
                # username이 기존에 없던 계정인 경우, config에 새로 추가
                username = self.content['username']
                if not username in self.config_for_recommend['client']['naver']:

                    self.config.update_one(
                        {"for": "recommend"},
                        {"$addToSet": {"client.naver": username}},
                    )
                    self.config.update_one(
                        {"for": "recommend"},
                        {"$set": {
                            "threshold.spend.{}".format(username): 500000,
                            "threshold.no_ccnt_spend.{}".format(username): 50000,
                            "threshold.avg_cpc_times.{}".format(username): 3,
                            "threshold.avg_cpm_times.{}".format(username): 3,
                            "threshold.avg_imp_times.{}".format(username): 3,
                        }
                        },
                    )
                    self.config_for_recommend = self.config.find_one(
                        {"for": "recommend"})

                self.fetch_by_customer_id()
                self.contents.append(self.content)

        print(self.contents)
        print("recommend_for_report done: {}".format(datetime.datetime.now()))
        return self.contents

    def fetch_by_customer_id(self):
        '''
        fetch campaign & adgroup data from DB by customer_id
        '''

        # 오늘 status가 ELIGIBLE(ON)인 캠페인들
        campaigns_on_today = list(self.db['nvcampaigns'].find(
            {
                "user_id": self.content['user_id'],
                "customer_id": self.content['customer_id'],
                "status": "ELIGIBLE",
            }
        ))

        if campaigns_on_today:
            campaigns_on_today = sorted(
                campaigns_on_today, key=lambda campaign_today: campaign_today['name'])

        self.content['naver'] = {
            "campaigns": campaigns_on_today,
            "adgroups": [],
            "recos": [],
        }

        # 오늘 status가 ELIGIBLE(ON), 어제 stat이 있는 광고그룹들
        adgroups_on_today = list(self.db['nvadgroups'].find(
            {
                "user_id": self.content['user_id'],
                "customer_id": self.content['customer_id'],
                "status": "ELIGIBLE",
                "status_reason": "ELIGIBLE",
                "yesterday": {'$ne': {}}
            }
        ))
        if adgroups_on_today:
            adgroups_on_today = sorted(
                adgroups_on_today, key=lambda adgroup_today: adgroup_today['name'])
        self.content['naver']['adgroups'] = adgroups_on_today

        self.recommend_entity()

        print("fetch_naver_data done: {}".format(datetime.datetime.now()))
        return self.content

    def recommend_entity(self):
        '''
        '''
        threshold = self.config_for_recommend['threshold']
        # 현재까지 1000원 이상 사용한 키워드 리스트
        keyword_list = list(self.nvkeywords.find(
            {
                "user_id": self.content['user_id'],
                "customer_id": self.content['customer_id'],
                "last_month.spend": {'$gte': threshold['spend'][self.content['username']]},
            },
        ))

        for keyword in keyword_list:
            self.recommend_keyword(keyword)

        print("recommend_entity done: {}".format(datetime.datetime.now()))
        return self.content

    def recommend_keyword(self, keyword):
        '''
        '''
        threshold = self.config_for_recommend['threshold']
        # 7일전부터 어제까지의 데이터
        data_7days = list(self.nvstats.find(
            {
                'res_id': keyword['keyword_id'],
                'type': 'keyword',
                'date_end': {'$gte': (datetime.datetime.now() - datetime.timedelta(days=7))}
            }
        ))
        # 지난 7일간 1000원 이상 사용했지만, 전환이 전혀 없는 키워드 검출
        sum_ccnts = sum([data['ccnt']
                         for data in data_7days if 'ccnt' in data])
        sum_spends = sum([data['spend']
                          for data in data_7days if 'spend' in data])
        if sum_ccnts == 0 and sum_spends >= threshold['no_ccnt_spend'][self.content['username']]:
            self.content['naver']['recos'].append(
                {
                    "keyword_id": keyword['keyword_id'],
                    "name": keyword['name'],
                    "reco": "7일간 소진 비용({}원) 대비 전환이 전혀 없습니다.".format(sum_spends, ','),
                }
            )
        # 지난 7일간 CPC 대비 CTR이 가장 좋은 순위를 추천
        ctr_by_cpc = []
        for data in data_7days:
            if 'ctr' in data and 'cpc' in data:
                if data['ctr'] * data['cpc']:
                    ctr_by_cpc.append(data['ctr']/data['cpc'])
        if ctr_by_cpc:
            max_index = ctr_by_cpc.index(max(ctr_by_cpc))
            best_rank = data_7days[max_index]['average_rank']
            if best_rank:
                self.content['naver']['recos'].append(
                    {
                        'keyword_id': keyword['keyword_id'],
                        'name': keyword['name'],
                        'reco': '7일간 최적 효율 순위는 {}위 입니다'.format(best_rank),
                    }
                )
        # 지난 7일간 평균 CPC 대비 어제 CPC가 급상승(2배 이상)한 키워드 검출 (CPC가 0인 데이터는 제외)
        if data_7days:
            cpc_for_7days = []
            for data in data_7days:
                if 'cpc' in data:
                    if data['cpc']:
                        cpc_for_7days.append(data['cpc'])
            avg_cpc_for_7days = np.mean(cpc_for_7days)

            if all([avg_cpc_for_7days, 'cpc' in data_7days[-1]]):
                if data_7days[-1]['cpc'] > avg_cpc_for_7days * threshold['avg_cpc_times'][self.content['username']]:
                    self.content['naver']['recos'].append(
                        {
                            'keyword_id': keyword['keyword_id'],
                            'name': keyword['name'],
                            'reco': '7일간 평균({}원)에 비해 CPC({}원)가 급상승 했습니다'.format(round(avg_cpc_for_7days, 2), data_7days[-1]['cpc']),
                        }
                    )
        # 지난 7일간 평균 CPM 대비 어제 CPM이 급상승(2배 이상)한 키워드 검출 (CPM이 0인 데이터는 제외)
        if data_7days:
            cpm_for_7days = []
            for data in data_7days:
                if 'impressions' in data and 'spend' in data:
                    if data['impressions'] * data['spend']:
                        cpm_for_7days.append(data['spend']/data['impressions'])
            avg_cpm_for_7days = np.mean(cpm_for_7days)

            if all([avg_cpm_for_7days, 'spend' in data_7days[-1], 'impressions' in data_7days[-1]]):
                if data_7days[-1]['spend'] * data_7days[-1]['impressions']:
                    if data_7days[-1]['spend']/data_7days[-1]['impressions'] > avg_cpm_for_7days * threshold['avg_cpm_times'][self.content['username']]:
                        self.content['naver']['recos'].append(
                            {
                                'keyword_id': keyword['keyword_id'],
                                'name': keyword['name'],
                                'reco': '7일간 평균({}원)에 비해 노출 경쟁(CPM, {}원)이 급상승 했습니다'.format(round(avg_cpm_for_7days, 2), round(data_7days[-1]['spend']/data_7days[-1]['impressions'], 2)),
                            }
                        )
        # 지난 7일간 평균 Impressions 대비 어제 Impressions 급상승(2배 이상)한 키워드 검출 (Impressions이 0인 데이터는 제외)
        if data_7days:
            imp_for_7days = []
            for data in data_7days:
                if 'impressions' in data:
                    if data['impressions']:
                        imp_for_7days.append(data['impressions'])
            avg_imp_for_7days = np.mean(imp_for_7days)

            if all([avg_imp_for_7days, 'impressions' in data_7days[-1]]):
                if data_7days[-1]['impressions'] > avg_imp_for_7days * threshold['avg_imp_times'][self.content['username']]:
                    self.content['naver']['recos'].append(
                        {
                            'keyword_id': keyword['keyword_id'],
                            'name': keyword['name'],
                            'reco': '7일간 평균({}회)에 비해 노출({}회)이 급상승 했습니다'.format(round(avg_imp_for_7days, 2), data_7days[-1]['impressions']),
                        }
                    )

        print("recommend_keyword done: {}".format(datetime.datetime.now()))
        return self.content

    def update_recommendations(self):
        '''
        update recommendations of every keyword with data of 7days and yesterday
        '''
        threshold = self.config_for_recommend['threshold']
        clients = self.config_for_recommend['client']
        keyword_list = self.nvkeywords.find({"status": "ELIGIBLE"})

        for keyword in keyword_list:
            print("Keyword: {}".format(keyword['name']))

            recos = []
            username = self.nvaccounts.find_one(
                {
                    "client_customer_id": keyword['customer_id'],
                    "user_id": keyword['user_id'],
                }
            )['client_login_id']
            # 만약 username이 Me 일 때는, users collection에서 이름을 가져옴
            if username == 'Me':
                username = self.db['users'].find_one(
                    {
                        "user_id": keyword['user_id'],
                        "type": "naver",
                    }
                )['name']
            if not username in clients['naver']:
                ### 여기도 처리해줘야함 ###
                username = "default"
                ### -------------- ###

            # 7일간 데이터 체크
            if not 'last_week' in keyword:
                return recos
            last_week = keyword['last_week']

            # 지난 7일간 최적 효율 순위
            if 'best_rank' in last_week:
                if last_week['best_rank']:
                    reco = "7일간 최적 효율 순위는 {}위 입니다".format(
                        last_week['best_rank'])
                    recos.append(reco)

            # 지난 7일간 1000원 이상 사용했지만, 전환이 전혀 없는 키워드 검출
            if last_week['ccnt'] == 0 and last_week['spend'] >= threshold['no_ccnt_spend'][username]:
                reco = "7일간 소진 비용({}원) 대비 전환이 전혀 없습니다.".format(
                    format(last_week['spend'], ','))
                recos.append(reco)

            # 어제 데이터 체크
            if not 'yesterday' in keyword:
                return recos
            yesterday = keyword['yesterday']

            # 지난 7일간 평균 CPC 대비 어제 CPC가 급상승(2배 이상)한 키워드 검출 (CPC가 0인 데이터는 제외)
            if yesterday['cpc'] > last_week['cpc'] * threshold['avg_cpc_times'][username]:
                last_week_cpc = format(round(last_week['cpc']), ',')
                yesterday_cpc = format(round(yesterday['cpc']), ',')
                reco = "7일간 평균({}원) 대비 1일 전 CPC({}원)가 급상승했습니다.".format(
                    last_week_cpc, yesterday_cpc)
                recos.append(reco)

            # 지난 7일간 평균 CPM 대비 어제 CPM이 급상승(2배 이상)한 키워드 검출 (CPM이 0인 데이터는 제외)
            if yesterday['cpm'] > last_week['cpm'] * threshold['avg_cpc_times'][username]:
                last_week_cpm = format(round(last_week['cpm']), ',')
                yesterday_cpm = format(round(yesterday['cpm']), ',')
                reco = "7일간 평균({}원) 대비 1일 전 CPM({}원)이 급상승했습니다.".format(
                    last_week_cpm, yesterday_cpm)
                recos.append(reco)

            # 지난 7일간 평균 Impressions 대비 어제 Impressions 급상승(2배 이상)한 키워드 검출 (Impressions이 0인 데이터는 제외)
            if yesterday['impressions'] > last_week['impressions'] * threshold['avg_cpc_times'][username]:
                last_week_imp = format(round(last_week['impressions']), ',')
                yesterday_imp = format(round(yesterday['impressions']), ',')
                reco = "7일간 평균({}회) 대비 1일 전 노출({}회)이 급상승했습니다.".format(
                    last_week_imp, yesterday_imp)
                recos.append(reco)

            # update recos for each keyword
            self.nvkeywords.update_one(
                {
                    "user_id": keyword['user_id'],
                    "keyword_id": keyword['keyword_id'],
                },
                {"$set": {"recommendation": recos}}
            )
            print(recos)
        print("update_recommendations done: {}".format(datetime.datetime.now()))
        return recos


#!/usr/bin/python
#coding:utf8

__author__ = ['fuyadong']

from setuptools import setup, find_packages

setup(
    name='mymoduel_fuyd',
    version="1.0.0",
    url='http://www.osforce.cn',
    license='MIT',
    author='fuyadong',
    author_email='fuyadong2011@163.com',
    description='a distributed test framework',
    classifiers=[
        "Programming Language :: Python",
    ],
    platforms='any',
    keywords='framework nose testing',
    packages=find_packages(exclude=['test']),
    install_requires=[]
)


from odoo import api, fields, models, tools, _
from odoo.modules import get_module_resource
from odoo.exceptions import ValidationError
from odoo.exceptions import UserError, AccessError
import logging

class Liquidacion(models.Model):
    _name = "account_gt.liquidacion"
    _inherit = ['mail.thread', 'mail.activity.mixin']
    _description = 'Liquidacion'
    _order = 'id desc'

    name = fields.Char('Nombre', required=True, copy=False, readonly=True, index=True, default=lambda self: _('New'))
    descripcion = fields.Char('Descripcion',tracking=True)
    fecha = fields.Date('Fecha',tracking=True)
    factura_ids = fields.One2many('account_gt.liquidacion_factura','liquidacion_id','Facturas')
    pago_ids = fields.One2many('account_gt.liquidacion_pago','liquidacion_id','Pagos')
    company_id = fields.Many2one('res.company', 'Company', required=True, default=lambda self: self.env.company)
    currency_id = fields.Many2one('res.currency','Moneda',default=lambda self: self.env.company.currency_id.id)
    diario_id = fields.Many2one('account.journal', 'Diario', required=True,tracking=True)
    cuenta_id = fields.Many2one('account.account', 'Cuenta de desajuste',tracking=True)
    move_id = fields.Many2one('account.move', 'Movimiento',tracking=True)
    state = fields.Selection([
        ('borrador', 'Borrador'),
        ('conciliado', 'Conciliado'),
        ('cancelado', 'Cancelado'),], string='Estado', readonly=True, copy=False, index=True, tracking=3, default='borrador')

    @api.model
    def create(self, vals):
        if vals.get('name', _('New')) == _('New'):
            seq_date = None
            if 'company_id' in vals:
                vals['name'] = self.env['ir.sequence'].with_context(force_company=vals['company_id']).next_by_code(
                    'account_gt.liquidacion', sequence_date=seq_date) or _('New')
            else:
                vals['name'] = self.env['ir.sequence'].next_by_code('account_gt.liquidacion', sequence_date=seq_date) or _('New')

        result = super(Liquidacion, self).create(vals)
        return result

    def conciliar_liquidacion(self):
        move = False
        moneda_factura = False
        moneda_pago= False
        for dato in self:
            lineas = []

            total = 0
            if dato.factura_ids:
                moneda_factura = dato.factura_ids[0].currency_id
                for linea in dato.factura_ids:
                    # logging.warn(f.number)
                    # logging.warn(f.amount_total)
                    for l in linea.factura_id.line_ids:
                        if l.account_id.reconcile:
                            if not l.reconciled:
                                total += l.credit - l.debit
                                lineas.append(l)
                                logging.warn(l.credit - l.debit)
                            else:
                                raise UserError('La factura %s ya esta conciliada' % (linea.factura_id.name))
            logging.warn('PASA FACTURA')
            logging.warn(lineas)

            if dato.pago_ids:
                moneda_pago = dato.pago_ids[0].currency_id
                for linea in dato.pago_ids:
                    # logging.warn(c.name)
                    # logging.warn(c.amount)
                    for l in linea.pago_id.move_line_ids:
                        if l.account_id.reconcile:
                            if not l.reconciled :
                                total -= l.debit - l.credit
                                lineas.append(l)
                                logging.warn(l.debit - l.credit)
                            else:
                                raise UserError('El Pago %s ya esta conciliado' % (linea.pago_id.name))

            logging.warn('PASA PAGO')
            logging.warn(lineas)

            if (moneda_pago.name=="GTQ" and moneda_factura.name=="GTQ") and moneda_factura.id == moneda_pago.id and round(total) != 0:
                logging.warn('TOTAL')
                logging.warn(total)
                break

            lineas_conciliares = []
            nuevas_lineas = []
            for linea in lineas:
                nuevas_lineas.append((0, 0, {
                    'name': linea.name,
                    'debit': linea.credit,
                    'credit': linea.debit,
                    'account_id': linea.account_id.id,
                    'partner_id': linea.partner_id.id,
                    'journal_id': dato.diario_id.id,
                    'date_maturity': dato.fecha,
                }))

            if total != 0 and moneda_factura.id != moneda_pago.id:
                nuevas_lineas.append((0, 0, {
                    'name': 'Diferencia de ' + dato.name,
                    'debit': -1 * total if total < 0 else 0,
                    'credit': total if total > 0 else 0,
                    'account_id': dato.cuenta_id.id,
                    'date_maturity': dato.fecha,
                }))

            if total != 0 and moneda_factura.name== 'USD' and moneda_pago.name=='USD':
                logging.warn('DOLAR')
                nuevas_lineas.append((0, 0, {
                    'name': 'Diferencia de ' + dato.name,
                    'debit': -1 * total if total < 0 else 0,
                    'credit': total if total > 0 else 0,
                    'account_id': dato.cuenta_id.id,
                    'date_maturity': dato.fecha,
                }))

            move = self.env['account.move'].create({
                'line_ids': nuevas_lineas,
                'ref': dato.name,
                'date': dato.fecha,
                'journal_id': dato.diario_id.id,
            });
            #
            indice = 0
            for linea in lineas:
                lineas_conciliar = linea | move.line_ids[indice]
                lineas_conciliar.reconcile()
                indice += 1

            move.post()
            self.write({'move_id': move.id})

        if move:
            for linea in dato.factura_ids:
                linea.factura_id.write({'liquidacion_id': dato.id})
            for linea in dato.pago_ids:
                linea.pago_id.write({'liquidacion_id': dato.id})
            self.write({'state': 'conciliado'})

        return True

    def cancelar_liquidacion(self):
        for dato in self:
            for l in dato.move_id.line_ids:
                if l.reconciled:
                    l.remove_move_reconcile()
            dato.move_id.button_draft()
            dato.move_id.button_cancel()
            # dato.move_id.unlink()

            if dato.move_id:
                for linea in dato.factura_ids:
                    linea.factura_id.write({'liquidacion_id': False})
                for linea in dato.pago_ids:
                    linea.pago_id.write({'liquidacion_id': False})
                self.write({'state': 'cancelado'})

        return True

    def cambiar_borrador(self):
        self.write({'state': 'borrador'})
        return True

class LiquidacionFactura(models.Model):
    _name = "account_gt.liquidacion_factura"
    _rec_name = "liquidacion_id"

    liquidacion_id = fields.Many2one('account_gt.liquidacion','Liquidacion')
    factura_id = fields.Many2one('account.move','Factura')
    currency_id = fields.Many2one('res.currency',string='moneda', related='factura_id.currency_id')
    total = fields.Monetary('Total',related='factura_id.amount_total')

class LiquidacionPago(models.Model):
    _name = "account_gt.liquidacion_pago"
    _rec_name = "liquidacion_id"

    liquidacion_id = fields.Many2one('account_gt.liquidacion','Liquidacion')
    pago_id = fields.Many2one('account.payment','Pago')
    currency_id = fields.Many2one('res.currency',string='moneda', related='pago_id.currency_id')
    total = fields.Monetary('Total',related='pago_id.amount')


import os
from flask import Flask , render_template, request
app=Flask(__name__)

def form_string(r):
    temp=""
    for key, value in r.items():
        temp=temp+"{},{} <br>".format(key, value)
    return temp

@app.route('/', methods=["GET", "POST"])
def main_index():
    if request.method =="GET":
        return render_template("form_basic.html")
    elif request.method == "POST":
        result=request.form
        output = form_string(result)
        return output

if __name__ == '__main__':
    app.run(debug=True)


import os
import sys
import numpy as np
from datetime import datetime
import time

"gzip file must be read and write in binary/bytes"
def myopenfile(fnm, mode):
    f = None
    if 'w' in mode:
        if isgzfile(fnm):
            import gzip
            mode = mode+'b' if 'b' != mode[-1] else mode
            f = gzip.open(fnm, mode)
        else:
            f = open(fnm, mode)
    else:
        if 'r' not in mode and 'a' not in mode:
            mode = 'r' + mode
        if os.path.isfile(fnm):
            if not isgzfile(fnm):
                f = open(fnm, mode)
            else:
                import gzip
                mode = 'rb'
                f = gzip.open( fnm, mode )
        elif os.path.isfile(fnm+'.gz'):
            'file @fnm does not exists, use fnm.gz instead'
            print(
                '==file {} does not exists, read {}.gz instead'.format(fnm,
                                                                       fnm))
            import gzip
            mode = 'rb'
            f = gzip.open(fnm+'.gz', mode)
        else:
            print('file: {} or its zip file does NOT exist'.format(fnm))
            sys.exit(1)
    return f

def isgzfile( filename ):
    return filename.endswith(".gz")

# delim must be str
def saveSimpleDictData(simdict, outdata, delim=':', mode='w'):
    if isgzfile(outdata):
        mode = mode + 'b' if mode[-1] != 'b' else mode
    # write bytes
    ib = True if 'b' in mode else False

    with myopenfile(outdata, mode) as fw:
        for k, val in simdict.items():
            k = k.decode() if isinstance(k, bytes) else str(k)
            val = val.decode() if isinstance(val, bytes) else str(val)
            outstr = "{}{}{}\n".format(k, delim,  val)
            x = outstr.encode() if ib else outstr
            fw.write(x)
        fw.close()

def loadSimpleDictData(indata, delim=':', mode='r', dtypes=[int, int]):
    if isgzfile(indata):
        mode = 'rb'
    # bytes
    ib = True if 'b' in mode else False

    simdict={}
    with myopenfile(indata, mode) as fr:
        for line in fr:
            line = line.decode() if ib else str(line)
            line = line.strip().split(delim)
            ktype, vtype = dtypes
            simdict[ktype(line[0])] = vtype(line[1])
        fr.close()
    return simdict

def saveDictListData(dictls, outdata, delim=':', mode='w'):
    if isgzfile(outdata):
        'possible mode is ab'
        mode = mode + 'b' if mode[-1] != 'b' else mode
    # write bytes
    ib = True if 'b' in mode else False

    with myopenfile(outdata, mode) as fw:
        i=0
        for k, l in dictls.items():
            if not isinstance(l,(list, np.ndarray)):
                print("This is not a dict of value list.", type(l))
                break
            if len(l)<1:
                continue
            k = k.decode() if isinstance(k, bytes) else str(k)
            ostr = "{}{}".format(k,delim)
            if len(l)<1:
                i += 1
                continue
            l = [ x.decode() if isinstance(x,bytes) else str(x) for x in l ]
            ostr = ostr + " ".join(l) + '\n'
            fw.write(ostr.encode() if ib else ostr)
        fw.close()
        if i > 0:
            print( "Warn: total {} empty dict lists are removed".format(str(i)) )

def loadDictListData(indata, ktype=str, vtype=str, delim=':', mode='r'):
    if isgzfile(indata):
        mode = 'rb'
    # bytes
    ib = True if 'b' in mode else False

    dictls={}
    with myopenfile(indata, mode) as fr:
        for line in fr:
            line = line.decode() if ib else line
            line = line.strip().split(delim)
            lst=[]
            for e in line[1].strip().split(' '):
                lst.append(vtype(e))
            dictls[ktype(line[0].strip())]=lst
        fr.close()
    return dictls

def convert_to_db_type(basic_type):
    basic_type_dict = {
        int: "INT",
        str: "TEXT",
        float: "REAL"
    }
    if basic_type in basic_type_dict.keys():
        return basic_type_dict[basic_type]
    else:
        return "TEXT"

def renumberids(indir, outdir, fnm, ofnm, delimeter=' ', comments='#', nodetype=str):
    users, msgs = {}, {}
    if not os.path.exists(outdir):
        os.makedirs(outdir, exist_ok=True)
    filepath = os.path.join(indir, fnm)
    ofilepath = os.path.join(outdir, ofnm)
    with myopenfile(filepath, 'r') as f, myopenfile(ofilepath, 'w') as outf:
        for line in f:
            line = line.strip()
            if line.startswith(comments):
                continue
            elems = line.split(delimeter)
            uid = nodetype(elems[0])
            bid = nodetype(elems[1])
            if uid not in users:
                users[uid] = len(users)
            if bid not in msgs:
                msgs[bid] = len(msgs)
            #t = int(elems[2])
            #label = int(elems[3])
            pos = line.find(delimeter)
            pos = line.find(delimeter, pos+1)
            outf.write('{} {} {}\n'.format(
                users[uid], msgs[bid], line[pos+1:]))
        outf.close()
        f.close()

    with open(os.path.join(outdir, 'userid.dict'), 'w') as f1,\
            open(os.path.join(outdir, 'msgid.dict'), 'w') as f2:
        for u, val in users.items():
            f1.write("{},{}\n".format(u, val))
        for m, val in msgs.items():
            f2.write("{},{}\n".format(m, val))
        f1.close()
        f2.close()
    return len(users), len(msgs)

'''
  @nodetype is the assumed type of node id, which used for saving the space of
  dict keys
  hdfs default delimeter is '\x01'
  If dicts exists , then reuse this dicts, and append new kyes when necessary.
'''
def renumberids2(infiles, outdir, delimeter =' ', isbyte=False,
        comments ='#', nodetype=str, colidx =[0, 1], dicts=None):
# for python >= 3.7
#def renumberids2(infiles, outdir, delimeter:str =' ', isbyte=False,
#        comments:str='#', nodetype=str, colidx:list =[0, 1], dicts:list=None):
    mode = 'b' if isbyte else ''
    numids = len(colidx)
    nodes = []
    if dicts is  None:
        nodes = [ {} for i in range(numids) ]
    elif len(dicts)==numids:
        for i in range(numids):
            if type(dicts[i]) is str:
                nodes.append(loadSimpleDictData(dicts[i], mode=mode,
                        dtypes=[nodetype, int]))
            elif type(dicts[i]) is dict:
                nodes.append(dicts[i])
            else:
                print("Error:\tincorrect type of dicts element: str or dict.")
                print("\tuse empty dict instead")
                nodes.append({})
    else:
        print("Error: incorrect input of dicts, {}".format(dicts))
        sys.exit(1)

    delimeter = delimeter.decode() if type(delimeter) is bytes else \
            str(delimeter)
    comments = comments.decode() if type(comments) is bytes else \
            str(comments)

    #=users, msgs = {}, {}
    if not os.path.exists(outdir):
        os.makedirs(outdir, exist_ok=True)

    #import ipdb; ipdb.set_trace()
    import glob
    files = glob.glob(infiles)
    for filepath in files:
        fnm = os.path.basename(filepath)
        #print('\tprocessing file {}'.format(fnm), flush=True)
        print('\tprocessing file {}'.format(fnm))
        sys.stdout.flush()
        j = fnm.find('.')
        nfnm = fnm[:j]+'.reid'+fnm[j:] if j!=-1 else fnm+'.reid'
        ofilepath = os.path.join(outdir, nfnm)
        with myopenfile(filepath, 'r'+mode) as f, myopenfile(ofilepath,
                                                             'w'+mode) as outf:
            for line in f:
                line = line.decode() if 'b' in mode else line
                line = line.strip()
                if line.startswith(comments):
                    continue
                elems = line.split(delimeter)
                nelems = elems.copy()
                for i in range(numids):
                    nodedict = nodes[i] # e.g. users
                    elemidx = colidx[i]
                    orgid = elems[elemidx].encode() if nodetype is bytes \
                            else nodetype(elems[elemidx])
                    if orgid not in nodedict:
                        nodedict[orgid] = len(nodedict)
                    nelems[elemidx] = str(nodedict[orgid])
                outstr = delimeter.join(nelems) + '\n'
                outx = outstr.encode() if 'b' in mode else outstr
                outf.write(outx)
            outf.close()
            f.close()

    for i in range(numids):
        nodedict = nodes[i]
        elemidx = colidx[i]
        outnm = os.path.join(outdir, "col{}ids.dict".format(elemidx))
        saveSimpleDictData(nodedict, outnm, delim=':', mode='b')
    return [ len(nodes[i]) for i in range(numids) ]

'''
    extract time stamps in log files or edgelist tensor
    @groupids the group col idx used for aggregating timestamps
    '\x01'
'''
def extracttimes(infile, outfile, timeidx=0, timeformat='%Y-%m-%d %H:%M:%S', delimeter=' ',
        isbyte=False, comments='#', nodetype=str, groupids=[]):
    mode = 'b' if isbyte else ''
    aggts = {} # final dict list for aggregating time series.
    import glob
    files = glob.glob(infile)
    for filepath in files:
        fnm = os.path.basename(filepath)
        #print('\tprocessing file {}'.format(fnm), flush=True)
        print('\tprocessing file {}'.format(fnm))
        sys.stdout.flush()
        with myopenfile(filepath, 'r'+mode) as f:
            for line in f:
                line = line.decode() if isinstance(line, bytes) else line
                if line.startswith(comments):
                    continue
                elems = line.split(delimeter)
                # todo: convert time string to ts
                if timeformat != 'int':
                    date = datetime.strptime(elems[timeidx], timeformat)
                    ts = int(time.mktime(date.timetuple()))
                # group by groupid
                if len(groupids) == 1:
                    key = elems[groupids[0]]
                else:
                    key = ','.join(np.array(elems)[groupids])
                if key not in aggts:
                    aggts[key] = []
                aggts[key].append(ts)
    if outfile is not None:
        saveDictListData(aggts, outfile)
    return aggts

'''
time\x01uid\x01...
e.g.: uid:t1,t2,t3
e.g.: uid,msg:t1,t2,t3
'''


from flask import request, Response, render_template, make_response, jsonify
import simplejson as json

class JSONResponse(Response):
    @classmethod
    def force_type(cls, rv, environ=None):
        if isinstance(rv, dict):
            best = request.accept_mimetypes.best_match(['application/json', 'text/html'])
            if best == 'text/html' and request.accept_mimetypes[best] > request.accept_mimetypes['application/json']:
                rv = make_response(render_template('api/json.html', response=json.dumps(rv, sort_keys=True, indent=2)))
            else:
                rv = jsonify(rv)
        return super(JSONResponse, cls).force_type(rv, environ)


"""IGenWebServer URL Configuration

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

urlpatterns = [
	path('admin/', admin.site.urls),
	path('', core_views.home, name = 'landing'),
	path('home/', core_views.home, name = 'home'),
	path('signup/', core_views.signup, name = 'signup'),
	path('login/', core_views.login, name = 'login'),
	path('logout/', core_views.logout, name = 'logout'),
	path('upload', core_views.upload_dna, name = 'upload'),
	path('dashboard', core_views.dashboard, name = 'dashboard'),
	path('status', core_views.check_status, name = 'status'),
	path('about', core_views.about, name = 'about'),
	path('resources', core_views.resources, name = 'resources'),
	path('results', core_views.show_results, name = 'results'),
	path('howitworks', core_views.howitworks, name = 'howitworks'),
]


import json
import time

import adafruit_dht
import board

from logger.Logger import Logger, LOG_LEVEL
from sensors.linux.sensor import Sensor

class HumiditySensor(Sensor):
    sensor = adafruit_dht.DHT11

    def __init__(self, pin, name=None, key=None, model='11', redis_conn=None):
        super().__init__(pin, name=name, key=key, redis_conn=redis_conn)
        self.pin_obj = getattr(board, pin)
        self.type = model
        return

    def init_sensor(self):
        """
        Initialize the sensor here (i.e. set pin mode, get addresses, etc)
        this gets called by the worker
        """
        sensor_types = {
            '11': adafruit_dht.DHT11,
            '22': adafruit_dht.DHT22,
            '2302': adafruit_dht.DHT22
        }  # AM2302 = DHT22

        if self.type in sensor_types:
            self.sensor = sensor_types[self.type]

        else:
            Logger.log(
                LOG_LEVEL["warning"],
                'Sensor Model Error: Defaulting to DHT11'
            )
        return

    def read(self):
        """
        Read the sensor(s), parse the data and store it in redis if redis
        is configured
        """
        # Set values just in case we never set them up.

        humidity = None
        temperature_c = None

        # read_retry() not implemented in new lib
        for i in range(15):
            dht_device = self.sensor(self.pin_obj)
            time.sleep(2)

            try:
                dht_device.measure()
                temperature_c = dht_device.temperature
                humidity = dht_device.humidity
                if humidity is not None and temperature_c is not None:
                    break

            except RuntimeError:
                # Errors happen fairly often, DHT's are hard to read,
                # just keep going:
                continue

            finally:
                dht_device.exit()

        if humidity is not None and temperature_c is not None:
            self.r.set(
                self.key + '_temperature',
                round(temperature_c * 1.8 + 32, 2)
            )
            self.r.set(
                self.key + '_humidity', humidity
            )
            readings = {
                'temperature': round(temperature_c * 1.8 + 32, 2),
                'humidity': round(humidity, 2)
            }
            self.r.set(self.key, json.dumps(readings))
            return readings

        else:
            Logger.log(
                LOG_LEVEL["error"],
                'DHT Reading was Invalid. Trying again next cycle.'
            )
            return None

    def read_raw(self):
        """
        Read the sensor(s) but return the raw data, useful for debugging

        Returns:

        """
        return self.read()


import argparse
import sys
from typing import Dict, List, Tuple

from OpenSSL import SSL, crypto
from OpenSSL.crypto import TYPE_DH, TYPE_DSA, TYPE_EC, TYPE_RSA

class Cert:
    """
    A class representing a certificate. It would be equivalent to the following command:
        $openssl req -x509 -out localhost.crt -keyout localhost.key \
            -newkey rsa:2048 -nodes -sha256 \
            -subj '/CN=localhost' -extensions EXT -config <( \
            printf "[dn]\nCN=localhost\n[req]\ndistinguished_name = dn\n[EXT]\nsubjectAltName=DNS:localhost\nkeyUsage=digitalSignature\nextendedKeyUsage=serverAuth")
    """
    type_map: Dict = {
        "RSA": TYPE_RSA,
        "DSA": TYPE_DSA,
        "DH": TYPE_DH,
        "EC": TYPE_EC
    }
    def __init__(
        self,
        cn: str = "localhost",
        c: str = None,
        l: str = None,
        st: str = None,
        o: str = None,
        ou: str = None,
        emailAddress: str = None,
        serialNumber: str = 0,
        validityStartInSeconds: str = 0,
        validityEndInSeconds: str = 10*365*24*60*60,
        distinguishedName: str = "localhost",
        subjectAltName: str = "DNS:localhost",
        keyUsage: str = "digitalSignature",
        extendedKeyUsage: str = "serverAuth",
        cryptoType: str = "RSA",
        bits: str = 4096,
        digest: str = "sha512",
        **kwargs
    ) -> None:

        # create a key pair
        self.key = crypto.PKey()
        self.key.generate_key(self.type_map.get(cryptoType, TYPE_RSA), bits)
        # create the certificate
        self.cert = crypto.X509()
        subj = self.cert.get_subject()
        subj.CN = cn
        if c is not None:
            subj.C = c
        if st is not None:
            subj.ST = st
        if l is not None:
            subj.L = l
        if o is not None:
            subj.O = o
        if ou is not None:
            subj.OU = ou
        if emailAddress is not None:
            subj.emailAddress = emailAddress
        extensions = [
            crypto.X509Extension(b"subjectAltName", False, subjectAltName.encode()),
            crypto.X509Extension(b"keyUsage", False, keyUsage.encode()),
            crypto.X509Extension(b"extendedKeyUsage", False, extendedKeyUsage.encode())
        ]
        self.cert.add_extensions(extensions)
        self.cert.set_serial_number(serialNumber)
        self.cert.gmtime_adj_notBefore(0)
        self.cert.gmtime_adj_notAfter(validityEndInSeconds)
        self.cert.set_issuer(subj)
        self.cert.set_pubkey(self.key)
        self.cert.sign(self.key, digest)

    def save(
        self,
        key_file: str,
        cert_file: str
    ) -> None:
        """
        Method to save the certificate and key.
        Can be checked afterwards with:
            $openssl x509 -in selfsigned.crt -text
        """
        with open(cert_file, "w") as f:
            f.write(crypto.dump_certificate(crypto.FILETYPE_PEM, self.cert).decode("utf-8"))
        with open(key_file, "w") as f:
            f.write(crypto.dump_privatekey(crypto.FILETYPE_PEM, self.key).decode("utf-8"))

class ArgParser(argparse.ArgumentParser):
    def __init__(self):
        super().__init__()
        self.add_argument("-cn", type=str, help="CN (Common Name)", default=argparse.SUPPRESS)
        self.add_argument("-c", type=str, help="C (Country Name)", default=argparse.SUPPRESS)
        self.add_argument("-l", type=str, help="L (Locality)", default=argparse.SUPPRESS)
        self.add_argument("-st", type=str, help="ST (State or Province)", default=argparse.SUPPRESS)
        self.add_argument("-o", type=str, help="O (Organization)", default=argparse.SUPPRESS)
        self.add_argument("-ou", type=str, help="OU (Organization Unit)", default=argparse.SUPPRESS)
        self.add_argument("-emailAddress", "-e", type=str, help="emailAddres", default=argparse.SUPPRESS)
        self.add_argument("-serialNumber", "-sn", type=int, help="serialNumber", default=argparse.SUPPRESS)
        self.add_argument("-validityStartInSeconds", "-vs", type=int, help="validityStart in seconds", default=argparse.SUPPRESS)
        self.add_argument("-validityEndInSeconds", "-ve", type=int, help="validityEnd in seconds", default=argparse.SUPPRESS)
        self.add_argument("-distinguishedName", "-dn", type=str, help="DN (Distinguished Name)", default=argparse.SUPPRESS)
        self.add_argument("-subjectAltName", "-san", type=str, help="SAN (Subject Alt Name)", default=argparse.SUPPRESS)
        self.add_argument("-keyUsage", "-ku", type=str, help="KU (Key Usage)", default=argparse.SUPPRESS)
        self.add_argument("-extendedKeyUsage", "-eku", type=str, help="EKU (Extended Key Usage)", default=argparse.SUPPRESS)
        self.add_argument("-cryptoType", "-t",type=str, help="Crypto Type", default=argparse.SUPPRESS)
        self.add_argument("-bits", "-b", type=int, help="Crypto number of bits", default=argparse.SUPPRESS)
        self.add_argument("-digest", "-dig", type=str, help="Digest", default=argparse.SUPPRESS)
        self.add_argument("-key", "-key-file", type=str, help="Key filename to be created", default="private.key")
        self.add_argument("-cert", "-cert-file", type=str, help="Cert filename to be creted", default="selfsigned.crt")

    def parse_args(self) -> argparse.Namespace:
        if len(sys.argv)==1:
            self.print_help(sys.stderr)
            sys.exit(1)
        return super().parse_args()

if __name__ == "__main__":
    parser = ArgParser()
    args = parser.parse_args()
    args_dict = vars(args)
    print("Create certificate with the following arguments:")
    for k, v in args_dict.items():
        print(f"{k} = {v}")
    cert = Cert(**args_dict)
    cert.save(args.key, args.cert)


import tensorflow as tf
import os
import xml.etree.ElementTree as etree
import numpy as np
import csv
from datetime import datetime
import math
os.environ["CUDA_DEVICE_ORDER"] = "PCI_BUS_ID"
os.environ["CUDA_VISIBLE_DEVICES"] = "0"

NUM_PER_EPOCH_FOR_TRAIN = 24147
NUM_PER_EPOCH_FOR_VAL = 7984
NUM_PER_EPOCH_FOR_TEST = 8007

BATCH_SIZE = 32
IMAGE_SIZE = 112
MOMENTUM = 0.9

MAX_ITERATIONS = 1000000
DISPLAY_STEP = 10
VALIDATION_STEP = 200

NUM_CHECKPOINTS = 144

def input(dataset_path,csv_path,type,dataset_type):
    csv_file = dataset_type+'.csv'

    queue = tf.train.string_input_producer([csv_path + csv_file])
    reader = tf.TextLineReader(skip_header_lines = True)
    _,row = reader.read(queue)
    record_defaults = [[""],[0],[0],[0]]
    image_path,width,height,label = tf.decode_csv(row,record_defaults,field_delim=',')

    image_path = dataset_path + tf.constant('/') + image_path
    label = tf.cast(label,tf.int64)
    width = tf.cast(width,tf.int64)
    height = tf.cast(height,tf.int64)

    image = tf.image.convert_image_dtype(tf.image.decode_jpeg(tf.read_file(image_path),channels = 3),dtype = tf.float32)
    image.set_shape([IMAGE_SIZE,IMAGE_SIZE,3])

    if type == 'train':
        images,labels = tf.train.shuffle_batch([image,label],batch_size = BATCH_SIZE,num_threads = 8,capacity = NUM_PER_EPOCH_FOR_TRAIN + 3*BATCH_SIZE,min_after_dequeue = NUM_PER_EPOCH_FOR_TRAIN)
    elif type == 'validation' or type == 'test':
        num_per_epoch = NUM_PER_EPOCH_FOR_VAL
        if type == 'test':
            num_per_epoch = NUM_PER_EPOCH_FOR_TEST
        images,labels = tf.train.batch([image,label],batch_size = BATCH_SIZE, num_threads = 8, capacity = num_per_epoch)

    return images,labels

def create_variable(name,shape,initializer):
    return tf.get_variable(name,shape,initializer = initializer,dtype = tf.float32)

def conv_layer(name,bottom,shape):
    with tf.variable_scope(name):
        kernal = create_variable('weights',shape,tf.contrib.layers.xavier_initializer_conv2d())
        conv = tf.nn.conv2d(bottom,kernal,[1,1,1,1],padding = 'SAME')
        biases = create_variable('biases',[shape[-1]],tf.contrib.layers.xavier_initializer())
        preactivation = tf.nn.bias_add(conv,biases)
        relu = tf.nn.relu(preactivation,name = name)

        return relu

def ip_layer(name,bottom,top):
    with tf.variable_scope(name):
        shape = bottom.get_shape().as_list()
        dim = np.prod(shape[1:])
        reshape = tf.reshape(bottom,[-1,dim])
        weights = create_variable('weights',[dim,top],tf.contrib.layers.xavier_initializer(uniform = False))
        biases = create_variable('biases',[top],tf.contrib.layers.xavier_initializer())

        return tf.nn.relu(tf.matmul(reshape,weights)+biases,name = name)

def pool_layer(name,bottom):
    return tf.nn.max_pool(bottom,ksize=[1,2,2,1],strides=[1,2,2,1],padding = 'SAME',name=name)

def inference(image):
    conv1_1 = conv_layer('conv1_1',image,[3,3,3,64])
    conv1_2 = conv_layer('conv1_2',conv1_1,[3,3,64,64])
    pool1 = pool_layer('pool1',conv1_2)
    conv2_1 = conv_layer('conv2_1',pool1,[3,3,64,128])
    conv2_2 = conv_layer('conv2_2',conv2_1,[3,3,128,128])
    pool2 = pool_layer('pool2',conv2_2)
    conv3_1 = conv_layer('conv3_1',pool2,[3,3,128,256])
    conv3_2 = conv_layer('conv3_2',conv3_1,[3,3,256,256])
    conv3_3 = conv_layer('conv3_3',conv3_2,[3,3,256,256])
    pool3 = pool_layer('pool3',conv3_3)
    conv4_1 = conv_layer('conv4_1',pool3,[3,3,256,512])
    conv4_2 = conv_layer('conv4_2',conv4_1,[3,3,512,512])
    conv4_3 = conv_layer('conv4_3',conv4_2,[3,3,512,512])
    pool4 = pool_layer('pool4',conv4_3)
    conv5_1 = conv_layer('conv5_1',pool4,[3,3,512,512])
    conv5_2 = conv_layer('conv5_2',conv5_1,[3,3,512,512])
    conv5_3 = conv_layer('conv5_3',conv5_2,[3,3,512,512])
    pool5 = pool_layer('pool5',conv5_3)
    fc1 = ip_layer('fc1',pool5,4096)
    fc2 = ip_layer('fc2',fc1,4096)
    fc3 = ip_layer('fc3',fc2,20)

    return fc3

def loss_op(logits,labels):
    cross_entropy = tf.nn.sparse_softmax_cross_entropy_with_logits(labels=labels,logits = logits,name = 'cross_entropy_per_batch')
    return tf.reduce_mean(cross_entropy,name = 'cross_entropy')

def train():

    with tf.Graph().as_default():
        global_step = tf.contrib.framework.get_or_create_global_step()

        with tf.device('/cpu:0'):
            images,labels = input('./train_images','./',type = 'train',dataset_type = 'train')

        decay_steps = int(50*NUM_PER_EPOCH_FOR_TRAIN/BATCH_SIZE)
        lr = tf.train.exponential_decay(0.01,global_step*BATCH_SIZE,decay_steps,0.95,staircase=True)

        opt = tf.train.MomentumOptimizer(lr,MOMENTUM)

        logits = inference(images)
        loss = loss_op(logits,labels)
        train_op = opt.minimize(loss,global_step = global_step)

        init = tf.global_variables_initializer()

        saver = tf.train.Saver(max_to_keep = 1000)

        var_list = [var for var in tf.global_variables() if not '2_2' in var.name and not '1_2' in var.name and  not '3_3' in var.name and not '4_3' in var.name and not '5_3' in var.name and not 'fc' in var.name]
        restore_saver = tf.train.Saver(var_list)

        with tf.Session() as sess:

            sess.run(init)
            ckpt = tf.train.get_checkpoint_state('./','checkpoint1')
            restore_saver.restore(sess,ckpt.model_checkpoint_path)

            coord = tf.train.Coordinator()
            threads = tf.train.start_queue_runners(sess=sess,coord=coord)

            time_start = datetime.now()
            time_end = 0

            loss_average = 0

            for step in range(MAX_ITERATIONS):
                _,batch_loss = sess.run([train_op,loss])
                loss_average += batch_loss

                if step%DISPLAY_STEP == 0:
                    time_end = datetime.now()
                    if step !=0:
                        loss_average /= 10
                    print("step:{},duration:{},average loss:{}".format(step,time_end-time_start,loss_average))
                    record_file = open('./log','a')
                    record_file.write('{},{}\n'.format(step,loss_average))
                    record_file.close()
                    loss_average = 0
                    time_start = time_end
                if step%VALIDATION_STEP ==0:
                    saver.save(sess,"./vgg16_4096.ckpt",global_step = step)
                    print('checkpoint saved')

        coord.request_stop()
        coord.join(threads)

def evaluate():

    with tf.Graph().as_default():

        global_step = tf.contrib.framework.get_or_create_global_step()

        with tf.device('/cpu:0'):
            images,labels = input('./validation_images','./',type = 'validation',dataset_type = 'validation')

        logits = inference(images)
        loss = loss_op(logits,labels)
        top_k = tf.nn.in_top_k(logits,labels,5)
        init = tf.global_variables_initializer()

        saver = tf.train.Saver()

        with tf.Session() as sess:

            coord = tf.train.Coordinator()
            threads = tf.train.start_queue_runners(sess=sess,coord=coord)

            num_iter = int(math.ceil(NUM_PER_EPOCH_FOR_VAL/BATCH_SIZE))
            num_sample = num_iter*BATCH_SIZE

            for checkpoint_id in range(NUM_CHECKPOINTS):
                checkpoint_id += 1
                file_name = 'checkpoint{}'.format(checkpoint_id)
                ckpt = tf.train.get_checkpoint_state('./',file_name)

                print('evaluating {}...'.format(file_name))

                sess.run(init)
                saver.restore(sess,ckpt.model_checkpoint_path)
                global_step = ckpt.model_checkpoint_path.split('./')[-1].split('-')[-1]

                accuracy = 0
                loss_average = 0
                top_k_accuracy = 0
                class_accuracy = {}
                class_num = {}
                for i in range(20):
                    class_accuracy[i] = 0
                    class_num[i] = 0

                for step in range(num_iter):
                    top_k_bool,prediction,loss_batch,label_batch = sess.run([top_k,logits,loss,labels])
                    prediction = np.argmax(prediction,axis=1)
                    accuracy_batch = BATCH_SIZE - np.count_nonzero(prediction-label_batch)
                    top_k_accuracy_batch = np.count_nonzero(top_k_bool)

                    print('step:{},batch accuracy:{},top 5:{},batch loss:{}'.format(step,accuracy_batch,top_k_accuracy_batch,loss_batch))
                    accuracy += accuracy_batch
                    loss_average += loss_batch
                    top_k_accuracy += top_k_accuracy_batch
                    for i in range(BATCH_SIZE):
                        class_num[label_batch[i]] += 1
                        if label_batch[i] == prediction[i]:
                            class_accuracy[label_batch[i]] += 1

                accuracy /= num_iter
                loss_average /= num_iter
                top_k_accuracy /= num_iter
                print('{},loss:{},accuracy:{},top 5:{}'.format(file_name,loss_average,accuracy,top_k_accuracy))
                for i in range(20):
                    class_accuracy[i] /= class_num[i]
                print(class_accuracy)
                record_file = open('./evaluation_validation_log','a')
                record_file.write('{},{},{},{}\n{}\n'.format(file_name,loss_average,accuracy,top_k_accuracy,class_accuracy))
                record_file.close()

        coord.request_stop()
        coord.join(threads)

def main():
    print('Begin...')

if __name__ == '__main__':
    #train()
    evaluate()


from django.urls import path, re_path
from blog import views

# define patterns

urlpatterns = [
    re_path(r'^$', views.PostListView.as_view(), name='post_list'),
    re_path(r'^about/$', views.About.as_view(), name='about'),
    re_path(r'^post/(?P<pk>\d+)/$', views.PostDetailView.as_view(), name='post_detail'),
    re_path(r'^post/new', views.CreatePostView.as_view(), name='post_new'),
    re_path(r'^post/(?P<pk>\d+)/edit$', views.UpdatePostView.as_view(), name = 'post_edit'),
    re_path(r'^post/(?P<pk>\d+)/delete/$', views.PostDeleteView.as_view(), name = 'post_remove'),
    re_path(r'^drafts/$', views.DraftPostView.as_view(), name = 'post_draft'),
    re_path(r'^post/(?P<pk>\d+)/comment/$', views.add_comment_to_post, name = 'add_comment_to_post'),
    re_path(r'^comment/(?P<pk>\d+)/approve/$', views.comment_approve, name = 'comment_approve'),
    re_path(r'^comment/(?P<pk>\d+)/remove/$', views.remove_comment, name = 'remove_comment'),
    re_path(r'^post/(?P<pk>\d+)/publish/$', views.post_publish, name = 'publish_post'),
]


import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

"""
Dataset obsahuje nasledujici promenne:
 'Age' - vek v rocich
 'Fare' - cena jizdenky
 'Name' - jmeno cestujiciho
 'Parch' - # rodicu/deti daneho cloveka na palube
 'PassengerId' - Id
 'Pclass' - Trida, 1 = 1. trida, 2 = 2.trida, 3 = 3.trida
 'Sex' - pohlavi
 'SibSp' - # sourozencu/manzelu daneho cloveka na ppalube
 'Survived' - 0 = Neprezil, 1 = Prezil
 'Embarked' - Pristav, kde se dany clovek nalodil. C = Cherbourg, Q = Queenstown, S = Southampton
 'Cabin' - Cislo kabiny
 'Ticket' - Cislo tiketu
"""

def load_dataset(train_file_path, test_file_path):
    """
    Napiste funkci, ktera nacte soubory se souboru zadanych parametrem a vytvori dva separatni DataFrame. Pro testovani vyuzijte data 'data/train.csv' a 'data/test.csv'
    Ke kazdemu dataframe pridejte sloupecek pojmenovaný jako "Label", ktery bude obsahovat hodnoty "Train" pro train.csv a "Test" pro test.csv.

    1. Pote slucte oba dataframy.
    2. Z vysledneho slouceneho DataFramu odstraňte sloupce  "Ticket", "Embarked", "Cabin".
    3. Sloučený DataDrame bude mít index od 0 do do počtu řádků.
    4. Vratte slouceny DataDrame.
    """

    train = pd.read_csv(train_file_path)
    test = pd.read_csv(test_file_path)
    train['Label'] = "Train"
    test['Label'] = "Test"

    return train.append(test, ignore_index=True, sort=True).drop(columns=["Ticket", "Embarked", "Cabin"])

def get_missing_values(df : pd.DataFrame) -> pd.DataFrame:
    """
    Ze zadaneho dataframu zjistete chybejici hodnoty. Vyvorte DataFrame, ktery bude obsahovat v indexu jednotlive promenne
    a ve prvnim sloupci bude promenna 'Total' obsahujici celkovy pocet chybejicich hodnot a ve druhem sloupci promenna 'Percent',
    ve ktere bude procentualni vyjadreni chybejicich hodnot vuci celkovemu poctu radku v tabulce.
    DataFrame seradte od nejvetsich po nejmensi hodnoty.
    Vrattre DataFrame chybejicich hodnot a celkovy pocet chybejicich hodnot.

    Priklad:

               |  Total  |  Percent
    "Column1"  |   34    |    76
    "Column2"  |   0     |    0

    """
    total = df.isna().sum().to_numpy(dtype = int)
    percent = total / df.shape[0]
    output = pd.DataFrame(columns = ['Total', 'Percent'], index = df.columns.values, data = np.column_stack((total, percent * 100)))

    return output.sort_values(list(output.columns.values), ascending=False)

def substitute_missing_values(df: pd.DataFrame) -> pd.DataFrame:
    """
    Chybejici hodnoty ve sloupecku "Age" nahradte meanem hodnot z "Age".
    Chybejici hodnoty ve sloupecku "Fare" nahradte meadianem hodnot z "Fare".
    V jednom pripade pouzijte "loc" a ve druhem "fillna".
    Zadany DataFrame neupravujte, ale vytvorte si kopii.
    Vratte upraveny DataFrame.
    """

    output = df.fillna({'Age': df['Age'].mean()})
    output.loc[np.isnan(output['Fare'])] = output['Fare'].median()

    return output

def get_correlation(df: pd.DataFrame) -> float:
    """
    Spocitejte korelaci pro "Age" a "Fare" a vratte korelaci mezi "Age" a "Fare".
    """

    return df['Age'].corr(df['Fare'])

def get_survived_per_class(df : pd.DataFrame, group_by_column_name : str) ->pd.DataFrame:
    """
    Spocitejte prumer z promenne "Survived" pro kazdou skupinu zadanou parametrem "group_by_column_name".
    Hodnoty seradte od nejvetsich po mejmensi.
    Hodnoty "Survived" zaokhroulete na 2 desetinna mista.
    Vratte pd.DataFrame.

    Priklad:

    get_survived_per_class(df, "Sex")

                 Survived
    Male     |      0.32
    Female   |      0.82

    """

    group_name_df = df.groupby(group_by_column_name).mean()['Survived']
    output = pd.DataFrame(columns = [group_by_column_name], data = group_name_df.index.to_numpy())
    output['Survived'] = np.round(group_name_df.values, 2)

    return output.sort_values('Survived', ascending = False)

def get_outliers(df: pd.DataFrame) -> (int, str):
    """
    Vyfiltrujte odlehle hodnoty (outliers) ve sloupecku "Fare" pomoci metody IRQ.
    Tedy spocitejte rozdil 3. a 1. kvantilu, tj. IQR = Q3 - Q1.
    Pote odfiltrujte vsechny hodnoty nesplnujici: Q1 - 1.5*IQR < "Fare" < Q3 + 1.5*IQR.
    Namalujte box plot pro sloupec "Fare" pred a po vyfiltrovani outlieru.
    Vratte tuple obsahujici pocet outlieru a jmeno cestujiciho pro nejvetsi outlier.
    """

    Q1 = df['Fare'].quantile(0.25)
    Q3 = df['Fare'].quantile(0.75)
    IQR = Q3 - Q1

    low = Q1 - 1.5 * IQR
    high = Q3 + 1.5 * IQR
    output = df.loc[(df['Fare'] <= low) | (df['Fare'] >= high)]

    plt.boxplot([df['Fare'].dropna().tolist(), output['Fare'].dropna().tolist()])

    return output.shape[0], output.loc[output['Fare'].idxmax()]['Name']

def normalise(df: pd.DataFrame, col: str) -> pd.DataFrame:
    """
    Naskalujte sloupec "col" zadany parametrem pro kazdou "Pclass" hodnotu z dataframu "df" zvlast.
    Pouzijte vzorec: scaled_x_i = (x_i - min(x)) / (max(x) - min(x)), kde "x_i" prestavuje konkretni hodnotu ve sloupeci "col".
    Vratte naskalovany dataframe.
    """

    output = df

    for i in df['Pclass'].unique():
        column = df.loc[df['Pclass'] == i, [col]]
        output.loc[df['Pclass'] == i, [col]] = (column - column.min())/(column.max() - column.min())

    return output

def create_new_features(df: pd.DataFrame) -> pd.DataFrame:
    """
    Vytvorte 3 nove promenne:
    1. "Fare_scaled" - vytvorte z "Fare" tak, aby mela nulovy prumer a jednotkovou standartni odchylku.
    2. "Age_log" - vytvorte z "Age" tak, aby nova promenna byla logaritmem puvodni "Age".
    3. "Sex" - Sloupec "Sex" nahradte: "female" -> 1, "male" -> 0, kde 0 a 1 jsou integery.

    Nemodifikujte predany DataFrame, ale vytvorte si novy, upravte ho a vratte jej.
    """
    output = df

    output['Fare_scaled'] = (output['Fare'] - output['Fare'].mean()) / np.std(output['Fare'])
    output['Age_log'] = np.log(output['Age'])
    output['Sex'] = (output['Sex'] == 'female')

    return output

def determine_survival(df: pd.DataFrame, n_interval: int, age: float, sex: str) -> float:
    """
    Na zaklade statistickeho zpracovani dat zjistete pravdepodobnost preziti Vami zadaneho cloveka (zadava se vek a pohlavi pomoci parametru "age" a "sex")

    Vsechny chybejici hodnoty ve vstupnim DataFramu ve sloupci "Age" nahradte prumerem.
    Rozdelte "Age" do n intervalu zadanych parametrem "n_interval". Napr. pokud bude Age mit hodnoty [2, 13, 18, 25] a mame jej rozdelit do 2 intervalu,
    tak bude vysledek:

    0    (1.977, 13.5]
    1    (1.977, 13.5]
    2     (13.5, 25.0]
    3     (13.5, 25.0]

    Pridejte k rozdeleni jeste pohlavi. Tj. pro kazdou kombinaci pohlavi a intervalu veku zjistete prumernou
    pravdepodobnost preziti ze sloupce "Survival" a tu i vratte.

    Vysledny DataFrame:

    "AgeInterval"   |    "Sex"    |   "Survival Probability"
       (0-10)       | "male"      |            0.21
       (0-10)       | "female"    |            0.28
       (10-20)      | "male"      |            0.10
       (10-20)      | "female"    |            0.15
       atd...

    Takze vystup funkce determine_survival(df, n_interval=20, age = 5, sex = "male") bude 0.21. Tato hodnota bude navratovou hodnotou funkce.

    """

    df = df.fillna({'Age': df['Age'].mean()})
    intervals = np.linspace(df['Age'].min(), df['Age'].max(), n_interval + 1)

    AgeIntervals = [(intervals[i], intervals[i + 1])
                    for i in range(0, intervals.shape[0] - 1)
                        for j in (0, 1)] #male ande female intervals
    sexes = []
    for i in range(len(AgeIntervals)) :
        if i % 2 == 0 : sexes.append('male')
        else : sexes.append('female')

    output = 0.0
    survival_probabilities = []
    for interval, it_sex in zip(AgeIntervals, sexes):
        probability = df.loc[(df['Age'] > interval[0]) & (df['Age'] <= interval[1]) & (df['Sex'] == it_sex), ['Survived']].mean()['Survived']
        survival_probabilities.append(probability)

        if output == 0.0 and interval[0] < age <= interval[1] and it_sex == sex:
            output = probability

    output_df = pd.DataFrame()

    output_df['AgeInterval'] = AgeIntervals
    output_df['Sex'] = sexes
    output_df['Survival Probability'] = survival_probabilities

    return output


# Usage: python music_collection_renamer.py folder
#

import sys
import os
from tinytag import TinyTag
from os import listdir
from os.path import isfile, join

folder = sys.argv[1]

if not os.path.exists(folder):
    print("Folder doesn't exist...")
    exit

files = [f for f in listdir(folder) if isfile(join(folder, f))]

# Usually music folders have one .nfo file
for file in reversed(files):
    if file.endswith(".nfo"):
        os.remove(os.path.join(folder, file))
        break

# Remove artist name from the filename
# This is only for CD album folders, not for folders with mixed artists
temp = None
replace_with = ""
for file in files:
    if file.endswith((".mp3",".flac", ".wav", ".ogg", ".mp4", ".m4a", ".wma", ".wave", ".opus")):
        tag = TinyTag.get(os.path.join(folder, file))
        artist = tag.artist

        if temp == None:
            if artist not in file:
                break

            if artist + " - " in file:
                temp = artist + " - "
            elif "-"+artist+"-":
                temp = "-"+artist+"-"
                replace_with = " - "

        os.rename(os.path.join(folder, file), os.path.join(folder, file.replace(temp, replace_with)))


"""empty message

Revision ID: 6bae619ac9f6
Revises: 27b5a273a861
Create Date: 2020-11-26 17:27:31.801212

"""
from alembic import op
import sqlalchemy as sa

# revision identifiers, used by Alembic.
revision = '6bae619ac9f6'
down_revision = '27b5a273a861'
branch_labels = None
depends_on = None

def upgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    op.add_column('order', sa.Column('tour_date', sa.Date(), nullable=True))
    op.create_index(op.f('ix_order_tour_date'), 'order', ['tour_date'], unique=False)
    op.drop_index('ix_order_add_date', table_name='order')
    op.drop_column('order', 'add_date')
    # ### end Alembic commands ###

def downgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    op.add_column('order', sa.Column('add_date', sa.DATE(), autoincrement=False, nullable=True))
    op.create_index('ix_order_add_date', 'order', ['add_date'], unique=False)
    op.drop_index(op.f('ix_order_tour_date'), table_name='order')
    op.drop_column('order', 'tour_date')
    # ### end Alembic commands ###


"""
### CODE OWNERS: Shea Parkes, Kyle Baird

### OBJECTIVE:
  Prove I can connect.

### DEVELOPER NOTES:
  <none>
"""

from fhirclient import client

# =============================================================================
# LIBRARIES, LOCATIONS, LITERALS, ETC. GO ABOVE HERE
# =============================================================================

settings = {
    'app_id': 'prm_analytics',
    'api_base': 'https://open-ic.epic.com/FHIR/api/FHIR/DSTU2'
}
epic = client.FHIRClient(settings=settings)

import fhirclient.models.patient as p
patient = p.Patient.read('Tbt3KuCY0B5PSrJvCu2j-PlK.aiHsu2xUjUM8bWpetXoB', epic.server)
patient.birthDate.isostring

epic.human_name(patient.name[0])


from itertools import combinations
k,n = map(int, input().split(","))

def num(k,n):
    nums=[1,2,3,4,5,6,7,8,9]
    res=[]
    for i in range(len(nums)):
        res +=list(combinations(nums,i))
    res=[x for x in res if len(x) == k]
    a=[]
    for j in res:
        if sum(j) ==n :
            a.append(list(j))
    return a

print(num(k,n))


from multiprocessing import Process, Queue
import multiprocessing
import threading
import time
import uuid
import ctypes
import json
import traceback
import copy
import sys

class _threading(threading.Thread):
    def __init__(self, *args, **keywords):
        threading.Thread.__init__(self, *args, **keywords)

    def get_id(self):
        for id, thread in threading._active.items():
            if thread is self:
                return id

    def kill(self):
        thread_id = self.get_id()
        res = ctypes.pythonapi.PyThreadState_SetAsyncExc(ctypes.c_long(thread_id), ctypes.py_object(SystemExit))
        if res == 0:
            logging.debug("Exception raise failure - invalid thread ID")
        if res > 1:
            ctypes.pythonapi.PyThreadState_SetAsyncExc(ctypes.c_long(thread_id), 0)

class workerHandler:
    class _worker:
        def __init__(self, name, call, args, delete, maxDuration, multiprocessing):
            self.name = name
            self.call = call
            self.id = str(uuid.uuid4())
            self.createdTime = int(time.time())
            self.startTime = 0
            self.endTime = 0
            self.duration = 0
            self.result = None
            self.running = None
            self.args = args
            self.multiprocessing = multiprocessing
            if not self.multiprocessing:
                self.thread = _threading(target=self.threadCall)
            else:
                self.thread = _threading(target=self.multiprocessingThreadCall)
            self.maxDuration = maxDuration
            self.delete = delete

        def start(self):
            self.thread.start()

        def multiprocessingThreadCall(self):
            self.startTime = int(time.time())
            self.running = True
            logging.debug("Threaded process worker started, workerID={0}".format(self.id))

            Q = Queue()
            p = Process(target=multiprocessingThreadStart, args=(Q,self.call,self.args)) # Taking an entire copy of cache is not effient review bug
            try:
                p.start()
                try:
                    rc, e = Q.get(timeout=self.maxDuration)
                    p.join(timeout=self.maxDuration)
                except:
                    raise SystemExit

                if rc != 0:
                    logging.debug("Threaded process worker crashed, workerID={0}".format(self.id))
                    systemTrigger.failedTrigger(self.id,"triggerCrashed",''.join(traceback.format_exception(etype=type(e), value=e, tb=e.__traceback__)))

                # Ensure cache is updated with any new items
                #cache.globalCache.sync(globalCacheObjects)
            except SystemExit:
                logging.debug("Threaded process worker killed, workerID={0}".format(self.id))
                systemTrigger.failedTrigger(self.id,"triggerKilled")
            except Exception as e:
                logging.debug("Threaded worker crashed, workerID={0}".format(self.id))
                systemTrigger.failedTrigger(self.id,"triggerCrashed",''.join(traceback.format_exception(etype=type(e), value=e, tb=e.__traceback__)))
            finally:
                if p.exitcode == None:
                    p.terminate()
                #Q.close()

            logging.debug("Threaded process worker completed, workerID={0}".format(self.id))
            self.running = False
            self.endTime = int(time.time())
            self.duration = (self.endTime - self.startTime)

        def threadCall(self):
            self.startTime = int(time.time())
            self.running = True
            logging.debug("Threaded worker started, workerID={0}".format(self.id))
            # Handle thread raise exception kill
            try:
                if self.args:
                    self.result = self.call(*self.args)
                else:
                    self.result = self.call()
            except SystemExit:
                logging.debug("Threaded worker killed, workerID={0}".format(self.id))
                systemTrigger.failedTrigger(self.id,"triggerKilled")
            except Exception as e:
                logging.debug("Threaded worker crashed, workerID={0}".format(self.id))
                systemTrigger.failedTrigger(self.id,"triggerCrashed",''.join(traceback.format_exception(etype=type(e), value=e, tb=e.__traceback__)))
            logging.debug("Threaded worker completed, workerID={0}".format(self.id))
            self.running = False
            self.endTime = int(time.time())
            self.duration = (self.endTime - self.startTime)

    def __init__(self,concurrent=15,autoStart=True):
        self.concurrent = concurrent
        self.workerList = []
        self.stopped = False

        # Autostarting worker handler thread
        workerThread = self._worker("workerThread",self.handler,None,True,0,False)
        workerThread.start()
        self.workerList.append(workerThread)
        self.workerID = workerThread.id

    def handler(self):
        tick = 0
        loops = 0
        underConcurrent = self.concurrent # Used to limit list looping to find active workers
        workersStillWaiting = [] # Cache waiting workers to limit list looping to find waiting workers
        while not self.stopped:
            now = int(time.time())
            self.lastHandle = now

            # Any room to start another worker?
            if underConcurrent < 1:
                activeWorkerCount = len([ x for x in self.workerList if x.running == True ])
                underConcurrent = ( self.concurrent - activeWorkerCount )
            if underConcurrent > 0:
                if len(workersStillWaiting) == 0:
                    workersStillWaiting = [ x for x in self.workerList if x.running == None ]
                if len(workersStillWaiting) > 0:
                    # Check if number of workersWaiting is above the number of available concurrent threads and select mx available
                    workersWaiting = workersStillWaiting
                    if len(workersWaiting) > underConcurrent:
                        workersWaiting = workersWaiting[0:underConcurrent]
                    # Start all workers possible up to the concurrent limit
                    for workerWaiting in workersWaiting:
                        logging.debug("Starting threaded worker, workerID={0}".format(workerWaiting.id))
                        workerWaiting.start()
                        underConcurrent-=1
                        del workersStillWaiting[workersStillWaiting.index(workerWaiting)]

            # Execute worker cleanup every 5ish seconds
            if (tick + 5) < now:
                # Any workers need clearning up due to overrun or stopped?
                cleanupWorkers = [ x for x in self.workerList if (x.running == False and x.delete) or (x.startTime > 0 and x.maxDuration > 0 and (now - x.startTime ) > x.maxDuration) ]
                for worker in cleanupWorkers:
                    if worker.running != False:
                        worker.thread.kill()
                    del self.workerList[self.workerList.index(worker)]
                tick = now

            # CPU saver
            loops+=1
            if ((underConcurrent == 0) or (underConcurrent > 0 and len(workersStillWaiting) == 0)):
                loops = 0
                time.sleep(workerSettings["loopT1"])
            elif (loops > workerSettings["loopL"] and len(workersStillWaiting) != 0):
                loops = 0
                time.sleep(workerSettings["loopT"])

    def new(self, name, call, args=None, delete=True, maxDuration=60, multiprocessing=False):
        workerThread = self._worker(name, call, args, delete, maxDuration, multiprocessing)
        self.workerList.append(workerThread)
        logging.debug("Created new worker, workerID={0}".format(workerThread.id))
        return workerThread.id

    def get(self, id):
        worker = [x for x in self.workerList if x.id == id]
        if worker:
            worker = worker[0]
        logging.debug("Got data for worker, workerID={0}".format(id))
        return worker

    def getAll(self):
        result = []
        for worker in self.workerList:
            result.append(worker)
        return result

    def getActive(self):
        result = []
        workersRunning = [x for x in self.workerList if x.running == True]
        for worker in workersRunning:
            result.append(worker)
        return result

    def delete(self, id):
        worker = [x for x in self.workerList if x.id == id]
        if worker:
            worker = worker[0]
            logging.debug("Deleted worker, workerID={0}".format(id))
            del worker
        else:
            logging.debug("Unable to locate worker, workerID={0}".format(id))

    def kill(self, id):
        worker = [x for x in self.workerList if x.id == id]
        if worker:
            worker = worker[0]
            worker.thread.kill()
            logging.debug("Killed worker, workerID={0}".format(id))
        else:
            logging.debug("Unable to locate worker, workerID={0}".format(id))

    def wait(self, jid):
        worker = [x for x in self.workerList if x.id == id][0]
        logging.debug("Waiting for worker, workerID={0}".format(id))
        while (worker.running != False ):
            time.sleep(0.1)

    def waitAll(self):
        while (self.queue() > 0 or len(self.active()) > 0):
            time.sleep(0.5)

    def activeCount(self):
        workersRunning = [x for x in self.workerList if x.id != self.workerID and x.running == True]
        return len(workersRunning)

    def active(self):
        result = []
        workersRunning = [x for x in self.workerList if x.id != self.workerID and x.running == True]
        for workerRunning in workersRunning:
            result.append(workerRunning.name)
        return result

    def count(self):
        return len(self.workerList)

    def queue(self):
        workersWaiting = [x for x in self.workerList if x.running == None]
        return len(workersWaiting)

    def stop(self):
        self.stopped = True
        for runningJob in self.getActive():
            self.kill(runningJob.id)
        for job in self.getAll():
            self.delete(job.id)

    # API Calls
    def api_get(self,id=None,action=None):
        result = { "results" : []}
        if not id and not action:
            workers = self.getAll()
        elif id and not action:
            workers = [self.get(id)]
        elif not id and action == "active":
            workers = self.getActive()

        for worker in workers:
            if worker:
                result["results"].append({ "id" : worker.id, "nane": worker.name, "startTime" : worker.startTime, "createdTime" : worker.createdTime })

        return result

    def api_delete(self,id=None):
        if not id:
            workers = self.getAll()
        else:
            workers = [self.get(id)]

        for worker in workers:
            worker.thread.kill()

        return { "result" : True }

from core import api, logging, settings, model, cache
from system.models import trigger as systemTrigger

workerSettings = settings.config["workers"]

multiprocessing.set_start_method("spawn",force=True)

def start():
    global workers
    # Creating instance of workers
    try:
        if workers:
            workers.kill(workers.workerID)
            logging.debug("Workers start requested, Existing thread kill attempted, workerID='{0}'".format(workers.workerID),6)
            workers = None
    except NameError:
        pass
    workers = workerHandler(workerSettings["concurrent"])
    logging.debug("Workers started, workerID='{0}'".format(workers.workerID),6)
    return True

def multiprocessingThreadStart(Q,threadCall,args):
    #cache.globalCache.sync(globalCache)
    rc = 0
    error = None
    try:
        threadCall(*args)
    except Exception as e:
        error = e
        rc = 1
    Q.put((rc,error))

######### --------- API --------- #########
if api.webServer:
    if not api.webServer.got_first_request:
        @api.webServer.route(api.base+"workers/", methods=["GET"])
        def getWorkers():
            result = workers.api_get()
            if result["results"]:
                return result, 200
            else:
                return {}, 404

        @api.webServer.route(api.base+"workers/", methods=["DELETE"])
        def deleteWorkers():
            result = workers.api_delete()
            if result["result"]:
                return result, 200
            else:
                return {}, 404

        @api.webServer.route(api.base+"workers/", methods=["POST"])
        def updateWorkers():
            data = json.loads(api.request.data)
            if data["action"] == "start":
                result = start()
                return { "result" : result }, 200
            elif data["action"] == "settings":
                if "concurrent" in data:
                    workerSettings["concurrent"] = int(data["concurrent"])
                    workers.concurrent = workerSettings["concurrent"]
                if "loopT" in data:
                    workerSettings["loopT"] = float(data["loopT"])
                if "loopL" in data:
                    workerSettings["loopL"] = float(data["loopL"])
                return { }, 200
            else:
                return { }, 404

        @api.webServer.route(api.base+"workers/<workerID>/", methods=["GET"])
        def getWorker(workerID):
            if workerID == "0":
                result = workers.api_get(workers.workerID)
                result["results"][0]["lastHandle"] = workers.lastHandle
                result["results"][0]["workerID"] = workers.workerID
            else:
                result = workers.api_get(workerID)

            if result["results"]:
                return result, 200
            else:
                return {}, 404

        @api.webServer.route(api.base+"workers/<workerID>/", methods=["DELETE"])
        def deleteWorker(workerID):
            result = workers.api_delete(workerID)
            if result["result"]:
                return result, 200
            else:
                return {}, 404

        @api.webServer.route(api.base+"workers/stats/", methods=["GET"])
        def getWorkerStats():
            result = {}
            result["results"] = []
            result["results"].append({ "activeCount" : workers.activeCount(), "queueLength" : workers.queue(), "workers" : workers.active() })
            return result, 200

        @api.webServer.route(api.base+"workers/settings/", methods=["GET"])
        def getWorkerSettings():
            result = {}
            result["results"] = []
            result["results"].append(workerSettings)
            return result, 200


#!/usr/bin/env python3

from PIL import Image
import os

path = '/supplier-data/images'
for filename in os.listdir(path):
	if filename.endswith('.tiff'):
		name = (filename.strip(".tiff")) + '.jpeg'
		img = Image.open(os.path.join(path, filename))
		img.resize((600,400)).convert('RGB').save("/supplier-data/images/{}".format(name))


# -*- coding: utf-8 -*-
"""
Created on Sun Aug  6 08:06:06 2017

@author: Administrator
"""

import requests
import re

def getHTMLtext(url):
    try:
        r = requests.get(url, timeout = 30)
        r.raise_for_status()
        r.encoding = r.apparent_encoding
        return r.text
    except:
        return " "

def parsePage(ilt,html):
    try:
        plt = re.findall(r'\"view_price\"\:\"[\d].*"',html)
        tlt = re.findall(r'\"raw_title\"\:\".*?\"',html)
        for i in range(len(plt)):
            price = eval(plt[i].split(":")[1])
            title = eval(tlt[i].split(":")[1])
            ilt.append([price,title])
    except:
            return " "

def printGoodList(ilt):
    tplt = "{:4}\t{:8}\t{:16}"
    print(tplt.format("序号","价格","商品名称"))
    count = 0
    for g in ilt:
        count += 1
       # print(tplt.format(count,g[0],g[1]))
        print(count,g[0],g[1])

def main():
    goods = '马裤'
    start_url = 'https://s.taobao.com/search?q=' + 'goods' + '&commend=all&ssid=s5-e&search_type=item&sourceId=tb.index&spm=a21bo.50862.201856-taobao-item.1&ie=utf8&initiative_id=tbindexz_20170806'
    infoList = []

    url = start_url
    html = getHTMLtext(url)
    parsePage(infoList,html)

    printGoodList(infoList)

main()


import pytest

from jwst.pipeline.calwebb_spec2 import Spec2Pipeline
from jwst.pipeline.collect_pipeline_cfgs import collect_pipeline_cfgs
from jwst.tests.base_classes import BaseJWSTTest, raw_from_asn

@pytest.mark.bigdata
class TestSpec2Pipeline(BaseJWSTTest):
    input_loc = 'niriss'
    ref_loc = ['test_spec2pipeline', 'truth']
    test_dir = 'test_spec2pipeline'

    def test_nis_wfss_spec2(self):
        """
        Regression test of calwebb_spec2 pipeline performed on NIRISS WFSS data.
        """
        # Collect data
        asn_file = self.get_data(self.test_dir,
                                 'jw87600-a3001_20171109T145456_spec2_001_asn.json')
        for file in raw_from_asn(asn_file):
            self.get_data(self.test_dir, file)

        # Run the step
        collect_pipeline_cfgs('cfgs')
        Spec2Pipeline.call(asn_file, config_file='cfgs/calwebb_spec2.cfg', save_bsub=True)

        # Test results.
        outputs = [('jw87600017001_02101_00002_nis_cal.fits',
                    'jw87600017001_02101_00002_nis_cal_ref.fits'),
                   ('jw87600017001_02101_00002_nis_x1d.fits',
                    'jw87600017001_02101_00002_nis_x1d_ref.fits')]
        self.compare_outputs(outputs)