# -*- coding: utf-8 -*-
import hashlib
import re
import threading
import time
from collections import deque

from lxml import etree
from pybloom_live import BloomFilter

from selenium import webdriver
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities

user_agent = (
    "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_4) " +
    "AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.57 Safari/537.36"
)
dcap = dict(DesiredCapabilities.PHANTOMJS)
dcap["phantomjs.page.settings.userAgent"] = user_agent
Phantomjs_path="C:/Program Files (x86)/Python36-32/phantomjs-2.1.1-windows/bin/phantomjs.exe"

feeds_crawler = webdriver.PhantomJS(desired_capabilities=dcap,executable_path=Phantomjs_path)
feeds_crawler.set_window_size(1920, 1200)  # optional
user_crawler = webdriver.PhantomJS(desired_capabilities=dcap,executable_path=Phantomjs_path)
user_crawler.set_window_size(1920, 1200)  # optional

domain = "weibo.com"
url_home = "http://" + domain

download_bf = BloomFilter(1024*1024*16, 0.01)
cur_queue = deque()

# feeds_crawler.find_element_by_class_name('WB_detail')
# time = feeds_crawler.find_elements_by_xpath('//div[@class="WB_detail"]/div[@class="WB_from S_txt2"]/a[0]').text

seed_user = 'http://weibo.com/yaochen'

min_mblogs_allowed = 100
max_follow_fans_ratio_allowed = 3

def extract_user(users):
    print('extract user')
    for _ in range(20):
        user_crawler.save_screenshot("test.png")
        for user_element in user_crawler.find_elements_by_xpath('//li[@class="follow_item S_line2"]'):
            print("提取该用户信息")
            tried = 0
            while tried < 3:
                try:
                    user = {
                        'follows': re.findall(
                            r'(\d+)',
                            user_element.find_element_by_xpath(
                                './/div[@class="info_connect"]/span'
                            ).text,
                        )[0]
                    }

                    user['follows_link'] = user_element.find_element_by_xpath('.//div[@class="info_connect"]/span//a').get_attribute('href')
                    user['fans'] = re.findall(r'(\d+)', user_element.find_elements_by_xpath('.//div[@class="info_connect"]/span')[1].text)[0]
                    user['fans_link'] = user_element.find_elements_by_xpath('.//div[@class="info_connect"]/span//a')[1].get_attribute('href')
                    user['mblogs'] = re.findall(r'(\d+)', user_element.find_elements_by_xpath('.//div[@class="info_connect"]/span')[2].text)[0]
                    user_link = user_element.find_element_by_xpath('.//div[contains(@class,"info_name")]/a')
                    user['link'] = re.findall(r'(.+)\?', user_link.get_attribute('href'))[0]
                    if user['link'][:4] != 'http':
                        user['link'] = domain + user['link']
                    user['name'] = user_link.text
                    user['icon'] = re.findall(r'/([^/]+)$', user_element.find_element_by_xpath('.//dt[@class="mod_pic"]/a/img').get_attribute('src'))[0]
                    # name = user_element.find_element_by_xpath('.//a[@class="S_txt1"]')

                    print('--------------------')
                    print(user['name'] + ' follows: ' + user['follows'] + ' blogs:' + user['mblogs'])
                    print(user['link'])

                    # 如果微博数量少于阈值或者关注数量与粉丝数量比值超过阈值，则跳过
                    if int(user['mblogs']) < min_mblogs_allowed or int(user['follows'])/int(user['fans']) > max_follow_fans_ratio_allowed:
                        break

                    enqueueUrl(user['link'])
                    users.append(user)
                    break
                except Exception as e:
                    print(e)
                    time.sleep(1)
                    tried += 1
        if go_next_page(user_crawler) is False:
            return users

    return users

def extract_feed(feeds):
    for _ in range(5):  #翻5页
        scroll_to_bottom()
        for element in feeds_crawler.find_elements_by_class_name('WB_detail'):
            tried = 0
            while tried < 3:
                try:
                    feed = {
                        'time': element.find_element_by_xpath(
                            './/div[@class="WB_from S_txt2"]'
                        ).text
                    }

                    feed['content'] = element.find_element_by_xpath('.//div[@class="WB_text W_f14"]').text
                    feed['image_names'] = []
                    for image in element.find_elements_by_xpath('.//li[contains(@class,"WB_pic")]/img'):
                        feed['image_names'].append(re.findall('/([^/]+)$', image.get_attribute('src')))
                    feeds.append(feed)
                    print('--------------------')
                    print(feed['time'])
                    print(feed['content'])
                    break
                except Exception:
                    tried += 1
                    time.sleep(1)
        if go_next_page(feeds_crawler) is False:
            return feeds

def scroll_to_bottom():
    # 最多尝试 20 次滚屏
    print('scroll down')
    for _ in range(50):
        # print 'scrolling for the %d time' % (i)
        feeds_crawler.execute_script('window.scrollTo(0, document.body.scrollHeight)')
        html = feeds_crawler.page_source
        tr = etree.HTML(html)
        next_page_url = tr.xpath('//a[contains(@class,"page next")]')
        if len(next_page_url) > 0:
            return next_page_url[0].get('href')
        if len(re.findall('点击重新载入', html)) > 0:
            print('scrolling failed, reload it')
            feeds_crawler.find_element_by_link_text('点击重新载入').click()
        time.sleep(1)

def go_next_page(cur_driver):
    try:
        next_page = cur_driver.find_element_by_xpath('//a[@class="page next S_txt1 S_line1"]').get_attribute('href')
        print('next page is ' + next_page)
        cur_driver.get(next_page)
        time.sleep(3)
        return True
    except Exception:
        print('next page is not found')
        return False

def fetch_user(user_link):
    print('downloading ' + user_link)
    feeds_crawler.get(user_link)
    time.sleep(5)

    # 提取用户姓名
    account_name = feeds_crawler.find_element_by_xpath('//h1[1]').text

    #photo = get_element_by_xpath(feeds_crawler, '//p[@class="photo_wrap"]/img')[0].get('src')
    photo = feeds_crawler.find_element_by_xpath('//p[@class="photo_wrap"]/img[1]').get_attribute('src')
    account_photo = re.findall('/([^/]+)$', photo)

    # 提取他的关注主页
    follows_link = get_element_by_xpath(feeds_crawler, '//a[@class="t_link S_txt1"]')[0].get('href')

    print('account: ' + account_name)
    print('photo url is'+str(account_photo))
    print('follows link is ' + follows_link)

    user_crawler.get( "http://"+follows_link )
    time.sleep(5)

    feeds = []
    users = []
    t_users = threading.Thread(target=extract_user, name=None, args=(users,))
    t_feeds = threading.Thread(target=extract_feed, name=None, args=(feeds,))

    t_users.setDaemon(True)
    t_feeds.setDaemon(True)

    t_users.start()
    t_feeds.start()

    t_users.join()
    t_feeds.join()
    t_users.join()

def get_element_by_xpath(cur_driver, path):
    tried = 0
    while tried < 6:
        html = cur_driver.page_source
        tr = etree.HTML(html)
        elements = tr.xpath(path)
        if len(elements) == 0:
            time.sleep(1)
            continue
        return elements

def login(username, password):
    print('Login')
    feeds_crawler.get(url_home)
    user_crawler.get(url_home)
    time.sleep(8)
    print('find click button to login')

    feeds_crawler.find_element_by_id('loginname').send_keys(username)
    feeds_crawler.find_element_by_name('password').send_keys(password)
    # 执行 click()
    feeds_crawler.find_element_by_xpath('//div[contains(@class,"login_btn")][1]/a').click()
    time.sleep(10)
    feeds_crawler.save_screenshot("screenshot1.png")
    time.sleep(10)
    verifycode1=input("please enter verifycode")
    try:
        feeds_crawler.find_elements_by_xpath('//*[@id="pl_login_form"]/div/div[3]/div[3]/div/input')[0].send_keys(verifycode1)
    except Exception as e:
        print(e)
    feeds_crawler.save_screenshot("3.png")
    feeds_crawler.find_element_by_xpath('//div[contains(@class,"login_btn")][1]/a').click()
    print("success!")
    # 也可以使用 execute_script 来执行一段 javascript
    # feeds_crawler.execute_script('document.getElementsByClassName("W_btn_a btn_32px")[0].click()')
    user_crawler.find_element_by_id('loginname').send_keys(username)
    user_crawler.find_element_by_name('password').send_keys(password)
    # # 执行 click()
    user_crawler.find_element_by_xpath('//div[contains(@class,"login_btn")][1]/a').click()
    time.sleep(10)
    user_crawler.save_screenshot("screenshot2.png")
    time.sleep(10)
    verifycode2=input("please enter verifycode")
    user_crawler.find_elements_by_xpath('//*[@id="pl_login_form"]/div/div[3]/div[3]/div/input')[0].send_keys(verifycode2)
    user_crawler.save_screenshot("4.png")
    user_crawler.find_element_by_xpath('//div[contains(@class,"login_btn")][1]/a').click()
    #for cookie in feeds_crawler.get_cookies():
    #user_crawler.add_cookie(cookie)

def enqueueUrl(url):
    try:
        md5v = hashlib.md5(url.encode("utf-8")).hexdigest()
        if md5v not in download_bf:
            print(url + ' is added to queue')
            cur_queue.append(url)
            download_bf.add(md5v)
        # else:
            # print 'Skip %s' % (url)
    except ValueError:
        pass

def dequeuUrl():
    return cur_queue.popleft()

def crawl():
    while True:
        url = dequeuUrl()
        fetch_user(url)

if __name__ == '__main__':
    enqueueUrl(seed_user)
    login('13125928026', 'cxyLOVE19970507')
    crawl()
    feeds_crawler.close()
    user_crawler.close()


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Thu Dec 13 11:00:27 2018

@author: sage
"""
from sklearn.model_selection import train_test_split
from DataLoaders.DataPoint import DataPoint
from sklearn.model_selection import KFold
import numpy as np
import os

class DataLoader():
    '''Abstract DataLoader Class'''

    def __init__(self,
                 init_location,
                 label_location,
                 in_memory=True,
                 memory_loc=None,
                 compress=False,
                 preloaded=False,
                 ):

        '''
        init_location - Location of the raw data files.
        label_location - Location of the label file/folder.
        in_memory - Flag to determine if the data should be loaded into memory
                    or if it should be saved to disk.
        memory_loc - If saved to disk, location to save to.
        compress - Flag to determine if the data should be saved in a
                   compressed form.
        preloaded - Flag to indicate if data has already been saved in temp mem spot
        '''

        self.init_location = os.path.abspath(init_location)
        self.label_location = os.path.abspath(label_location)

        self.in_memory = in_memory
        self.memory_loc = memory_loc
        self.compress = compress
        self.preloaded = preloaded

        self.data_points = []

        self.kf_train_splits = []
        self.kf_test_splits = []

    def load_labels(self):
        pass

    def load_data(self):
        pass

    def load_new(self):
        pass

    def load_unseen(self):
        self.load_new()

        return self.data_points

    def create_data_point(self, name, label, slc=None):

        if type(label) == list:

            dp = DataPoint(
                name = name,
                label = label[0],
                extra = label[1:],
                in_memory = self.in_memory,
                memory_loc = self.memory_loc,
                compress = self.compress,
                slc = slc )

        else:

            dp = DataPoint(
                    name = name,
                    label = label,
                    in_memory = self.in_memory,
                    memory_loc = self.memory_loc,
                    compress = self.compress,
                    slc = slc )

        return dp

    def get_unique_patients(self):

        patients = sorted(list(set([dp.get_patient() for dp in self.data_points])))
        return np.array(patients)

    def get_data_points_by_patient(self, patients):

        relevant = []

        for dp in self.data_points:
            if dp.get_patient() in patients:
                relevant.append(dp)

        return relevant

    def load_all(self):

        self.load_labels()
        self.load_data()

    def get_all(self):
        '''Return just one set, for just train'''

        self.load_all()

        return self.data_points

    def get_train_test_split(self, test_size, seed):

        self.load_all()
        patients = self.get_unique_patients()

        train_patients, test_patients = train_test_split(patients,
                                                         test_size=test_size,
                                                         random_state=seed)

        train = self.get_data_points_by_patient(train_patients)
        test = self.get_data_points_by_patient(test_patients)

        return train, test

    def get_train_test_val_split(self, test_size, val_size, seed):

        self.load_all()
        patients = self.get_unique_patients()

        train_patients, test_patients = train_test_split(patients,
                                                         test_size=test_size,
                                                         random_state=seed)
        train_patients, val_patients = train_test_split(train_patients,
                                                        test_size=val_size,
                                                        random_state=seed)

        train = self.get_data_points_by_patient(train_patients)
        test = self.get_data_points_by_patient(test_patients)
        val = self.get_data_points_by_patient(val_patients)

        return train, test, val

    def setup_kfold_splits(self, n_splits, seed):
        '''Preforms a kfold val_split by patient, and stores the splits.'''

        self.load_all()
        patients = self.get_unique_patients()

        kf = KFold(n_splits=n_splits, random_state=seed)

        for train_patients, test_patients in kf.split(patients):
            self.kf_train_splits.append(patients[train_patients])
            self.kf_test_splits.append(patients[test_patients])

    def get_k_split(self, ind):

        train_patients = self.kf_train_splits[ind]
        test_patients = self.kf_test_splits[ind]

        train = self.get_data_points_by_patient(train_patients)
        test = self.get_data_points_by_patient(test_patients)

        return train, test


import pytest

from hexalog.adapters.struct_logger import StructLogger

_PATH_TO_STRUCT_LOGGER = "hexalog.adapters.struct_logger.get_logger"

_KWARGS = {"foo": "bar"}

@pytest.mark.parametrize(
    "method,level,msg,kwargs",
    [
        ("debug", "debug", "test debug message", _KWARGS),
        ("info", "info", "test info message", _KWARGS),
        ("warning", "warning", "test warning message", _KWARGS),
        ("error", "error", "test error message", _KWARGS),
    ],
)
def test_logger_methods(mocker, method, level, msg, kwargs):
    mock_logger = mocker.patch(_PATH_TO_STRUCT_LOGGER)

    logger = StructLogger()

    log_method = getattr(logger, method)

    log_method(msg, **kwargs)

    getattr(mock_logger(), level).assert_called_once_with(msg, **kwargs)

def test_fatal_exits(mocker):
    mock_logger = mocker.patch(_PATH_TO_STRUCT_LOGGER)
    logger = StructLogger()

    msg = "test fatal"
    level = "fatal"

    log_method = getattr(logger, level)

    with pytest.raises(SystemExit) as e:
        log_method(msg, **_KWARGS)

    getattr(mock_logger(), level).assert_called_once_with(msg, **_KWARGS)

    assert e.type == SystemExit
    assert e.value.code == msg


"""
To run the app
$ streamlit run front.py
"""

import streamlit as st
import requests, json
import pandas as pd

def get_records(record_type, record_time, event):
    data_request = {"event": event, "record_time": str(record_time), "record_type": record_type}
    response = requests.post(
        "https://wca-nr-api-jhaooholda-ue.a.run.app/get_nr_countries", data=json.dumps(data_request)
    ).json()
    # response = requests.post("http://127.0.0.1:8000/get_nr_countries", data=json.dumps(data_request)).json()
    if response["result"]:
        result_df = pd.DataFrame.from_dict(response["result"])[
            ["personId", "name", "gender", "best", "countryId", "eventId"]
        ]
    else:
        result_df = (
            f"Sorry, with this time you cannot beat any existing National Records in {event} but you may try a country"
            " where the record wasn't set yet"
        )
    return response["database_date"], result_df

EVENT_LIST = [
    "222",
    "333",
    "333bf",
    "333fm",
    "333ft",
    "333oh",
    "444",
    "444bf",
    "555",
    "555bf",
    "666",
    "777",
    "clock",
    "magic",
    "minx",
    "mmagic",
    "pyram",
    "skewb",
    "sq1",
]

st.set_page_config("WCA NR", page_icon="images/rubik.png")
st.sidebar.markdown("Enter a time for a specific event")
st.title("WCA NR")
record_type = st.radio("Single or Average?", ("Single", "Average"))
record_time = int(
    st.number_input(
        label="What is your record (format in seconds x100, ex: 4.86s -> 486, except FM just put the number of moves)?",
        min_value=0,
        max_value=100_000,
        step=1,
        value=1000,
    )
)
event = st.selectbox("Select the event", EVENT_LIST)

if st.button("Launch"):
    database_date, result_df = get_records(record_type, record_time, event)
    st.write(f"### Latest update from WCA database: {database_date}")
    if isinstance(result_df, str):
        st.write(result_df)
    else:
        st.dataframe(result_df, width=800, height=210)


import asyncio
from collections import defaultdict
from datetime import timedelta

import pytest

from yui.api import SlackAPI
from yui.bot import Bot
from yui.box import Box
from yui.types.slack.response import APIResponse

from .util import FakeImportLib

def test_bot_init(monkeypatch, bot_config):
    importlib = FakeImportLib()

    monkeypatch.setattr("importlib.import_module", importlib.import_module)

    bot_config.APPS = ["yui.app1", "yui.app2"]
    box = Box()
    bot = Bot(bot_config, using_box=box)

    assert bot.config == bot_config
    assert bot.channels == []
    assert bot.ims == []
    assert bot.groups == []
    assert bot.restart is False
    assert isinstance(bot.api, SlackAPI)
    assert bot.box is box
    assert isinstance(bot.queue, asyncio.Queue)
    assert importlib.import_queue == [
        "yui.app1",
        "yui.app2",
    ]

@pytest.mark.asyncio()
async def test_call(bot_config, response_mock):
    token = "asdf1234"  # noqa: S105

    response_mock.post(
        "https://slack.com/api/test11",
        payload={"res": "hello world!"},
    )
    response_mock.post(
        "https://slack.com/api/test12",
        payload={"res": "hello world!", "data": {"extra": "wow"}},
    )

    response_mock.post(
        "https://slack.com/api/test21",
        payload={"error": "aaa"},
        status=404,
    )
    response_mock.post(
        "https://slack.com/api/test22",
        payload={"error": "aaa"},
        status=404,
    )
    response_mock.post(
        "https://slack.com/api/test3",
        payload={"res": "hello world!"},
    )

    box = Box()
    bot = Bot(bot_config, using_box=box)
    bot.api.throttle_interval = defaultdict(lambda: timedelta(0))

    resp = await bot.call("test11")
    assert isinstance(resp, APIResponse)
    assert resp.body == {"res": "hello world!"}
    assert resp.status == 200
    assert resp.headers["Content-Type"] == "application/json"

    resp = await bot.call("test12", data={"extra": "wow"})
    assert isinstance(resp, APIResponse)
    assert resp.body == {"res": "hello world!", "data": {"extra": "wow"}}
    assert resp.status == 200
    assert resp.headers["Content-Type"] == "application/json"

    resp = await bot.call("test21")
    assert isinstance(resp, APIResponse)
    assert resp.body == {"error": "aaa"}
    assert resp.status == 404
    assert resp.headers["Content-Type"] == "application/json"

    resp = await bot.call("test22", data={"extra": "wow"})
    assert isinstance(resp, APIResponse)
    assert resp.body == {"error": "aaa"}
    assert resp.status == 404
    assert resp.headers["Content-Type"] == "application/json"

    resp = await bot.call("test3", token=token)
    assert isinstance(resp, APIResponse)
    assert resp.body == {"res": "hello world!"}
    assert resp.status == 200
    assert resp.headers["Content-Type"] == "application/json"


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

###############################################################################
#该模块定义了对modis文件的操作的各种方法
#整个处理遥感数据需要的一些方法。
###############################################################################

import os
import gdal
import shutil
import numpy as np
import matplotlib as mpl
mpl.use('Agg')
import matplotlib.pyplot as plt
from gdalconst import *

#检查素材文件夹是否存在，不存在建立
def checkEnv(names):
	for i in names:
		if os.path.exists(i):
			continue;
		else:
			os.mkdir(i)

#~ #返回形式为 [['0501.hdf', '0502.hdf'],['0601.hdf','0602.hdf']] 的文件索引
#~ #参数： folder为根目录，keywords为文件名的关键字
def getRasters(folder,keywords):
	result = []
	for root ,dirs,files in os.walk(folder):
		#只有显示二级目录
		if files ==[]:
			continue
		else:
			temp= []
			#连接文件名
			for name in files:
				str =  os.path.join(root,name)
				#根据关键字过滤
				for j in keywords:
					if j in str and 'xml' not in str:
						temp.append(str)
						break
		result.append(temp)

	return result

#遍历文件夹，只显示文件
def readFile(path):
	for root ,dirs,files in os.walk(path):
		#只有显示二级目录
		if files ==[]:
			continue
		else:
			temp= []
			#连接文件名
			for name in files:
				str =  os.path.join(root,name)
				temp.append(str)
		return temp

#输入path1, 输出 [ [band1,band2,...],[name1,name2...] ]
def getBandName(path):
	dataset = gdal.Open(path,GA_ReadOnly)
	#获取子波段
	subdatasets = dataset.GetSubDatasets()
	pathname=[]
	bandname=[]
	for i in subdatasets:
		#排除一个质量图层
		#~ if '[1x2400x2400]'in i[1]:
			#~ continue
		pathname.append(i[0])
		bandname.append(i[1])

	result = [pathname,bandname]
	dataset = None
	return result

#转换
#转换
def transHDF(infile,outfile):
                os.system('gdal_translate \'%s\' %s -of GTiff' %(infile,'temp/'+outfile))
# modified by neptune by add single quote to enclose infile to prevent error caused by space in infile

#拼接
def merge(infiles,outfile):
	str=''
	for i in infiles:
		#过滤xml文件
		if 'xml' in i:
			continue
		str+=i+' '
	os.system('gdal_merge.py -o %s -of GTiff %s' %(outfile,str))

#更改投影
def warp(infile,outfile):
	os.system('gdalwarp %s %s -r near -t_srs EPSG:4326' % (infile,outfile))
	return 'warp ok. generate'+outfile

#矢量图重投影
def shpRepro(inshp,outshp):
	os.system('ogr2ogr -t_srs EPSG:4326 %s %s' % (outshp, inshp))

#从栅格图中裁剪
# -crop_to_cutline  忽略矢量图外部分
def mask(inshp,inraster,outraster):
	os.system('gdalwarp -cutline %s %s %s -crop_to_cutline'% (inshp,inraster,outraster) )

	return 'warp ok. generate'+outraster

#生成缩略图
def makeThumbnail(src):
	dataset = gdal.Open(src)
	#判断数据集的波段数
	if(dataset.RasterCount<1):
		return
	if(dataset.RasterCount>1):
		ds = dataset.GetRasterBand(1).ReadAsArray()
	else:
		ds = dataset.ReadAsArray()

	A = np.array(ds)
	fig = plt.figure(frameon = False)    #生成画布
	ax = fig.add_subplot(111)             #增加子图
	ax.imshow(A, interpolation='nearest', vmin = 0,vmax = 16,cmap=plt.cm.gist_earth)    #子图上显示数据
	plt.savefig(src.replace('.tif','THUMBNAIL.png'),dpi = 80)
	ax.set_xticks([])                            #去除坐标轴
	ax.set_yticks([])
	plt.savefig(src.replace('.tif','.png'),dpi = 300)
	ds = None
	dataset = None


from rest_framework.pagination import PageNumberPagination
from rest_framework.response import Response
import math
from rest_framework import status
## you can override page_size, max_page_size from url query params \
## to make it more dynamic
class CustomPagination(PageNumberPagination):
    page_size = 1 # default page size
    max_page_size = 1000 # default max page size
    page_size_query_param = 'page_size' # if you want to dynamic items per page from request you must have to add it

    def get_paginated_response(self, data):
        # if you want to show page size in resposne just add these 2 lines
        if self.request.query_params.get('page_size'):
            self.page_size = int(self.request.query_params.get('page_size'))

        # you can count total page from request by total and page_size
        total_page = math.ceil(self.page.paginator.count / self.page_size)

        # here is your response
        return Response({
            'message':"Records getting successfully",
            'count': self.page.paginator.count,
            'total': total_page,
            'page_size': self.page_size,
            'current': self.page.number,
            'previous': self.get_previous_link(),
            'next': self.get_next_link(),
            'results': data
        }, status=status.HTTP_200_OK)


''' Contains all the cart view.'''

from django.shortcuts import render
from django.http import HttpResponseRedirect, JsonResponse
from django.urls import reverse

from products.models import Product
from .models import Cart, CartItem
from .view_helper_functions import retrived_product,retrived_cart, update_cart_total, update_cartitem

def cart(request):
    '''Get the cart id from the session, retrive the cart
    from the database and then pass it to the context dict.'''

    # retrive cart from session, making context, render
    try:
        the_id = request.session['cart_id']
    except:
        the_id = None

    if the_id:
        cart = Cart.objects.get(id=the_id)
        context = {'cart': cart}
    else:
        context = {'empty': True}

    template = 'carts/cart.html'
    return render(request, template, context)

def add_to_cart(request, slug):
    '''Retrive the product and the cart then feed to the
    CartItem.Then update the cartitem and the cart.'''

    # retrive the product
    product = retrived_product(slug)

    # retrive the cart
    cart = retrived_cart(request)

    # Feeding to the CartItem
    cart_item, created = CartItem.objects.get_or_create(cart=cart, product=product)

    # update cartitem and cart
    update_cartitem(request, cart_item)
    update_cart_total(request, cart)

    return HttpResponseRedirect(reverse('cart'))

def remove_from_cart(request, pk):

    cart = retrived_cart(request)
    cart_item = CartItem.objects.filter(cart=cart, pk=pk)
    cart_item.delete()
    # message
    update_cart_total(request, cart)

    return HttpResponseRedirect(reverse('cart'))

def update_cart_item(request):
    '''Update cart Item quantity and also variations(still not applied) from the cart.'''

    pk = request.GET.get('pk')
    cart_item = CartItem.objects.get(pk=pk)

    if int(request.GET.get('qty')) <= 0:
        cart_item.delete()
        cart = retrived_cart(request)
        update_cart_total(request, cart)
        cart_total = cart.total
        return JsonResponse({
            'id': pk,
            'product': 'empty',
            'cart_total': cart_total
        })

    cart_item.quantity = request.GET.get('qty')
    cart_item.save()
    cart = retrived_cart(request)
    update_cart_total(request, cart)

    if request.is_ajax():
        line_total = CartItem.objects.get(pk=pk).line_total
        cart_total = cart.total
        print('hi')
        return JsonResponse({
            'line_total': line_total,
            'cart_total': cart_total
        })

    return HttpResponseRedirect(reverse('cart'))


# -*- coding: utf-8 -*-
from typing import List

class Solution:
    def maxEqualFreq(self, nums: List[int]) -> int:
        for i in range(len(nums) - 1, -1, -1):
            #nums_x = [x for x in nums if x != nums[i]]
            #if len(nums_x) == 0:
            #    return i

            '''for j in range(0, len(nums_x)):
                nums_y = []
                for y in range(j):
                    nums_y.append(nums_x[y])
                for y in range(j + 1, len(nums_x)):
                    nums_y.append(nums_x[y])'''
            nums_x = nums[0:i + 1]
            hashmap = {}
            for key in nums_x:
                hashmap[key] = hashmap.get(key, 0) + 1
            if len(hashmap) == 1:
                return i + 1
            #check = set(list(hashmap.values()))
            #if len(check) == 1:
            #    if 1 in check:
            #        return i + 1
            #if len(check) == 2:
            another = {}
            for k, v in hashmap.items():
                another.setdefault(v, []).append(k)
            if len(another) == 1 and 1 in another.keys():
                return i + 1
            if len(another) == 2 and 1 in another.keys() and len(another[1]) == 1:
                return i + 1
            if len(another) == 2:
                minKey = min(another.keys(), key=(lambda x: x))
                if minKey + 1 in another.keys() and len(another[minKey + 1]) == 1:
                    return i + 1

if __name__ == '__main__':
    solution = Solution()
    nums = [10,2,8,9,3,8,1,5,2,3,7,6]
    res = solution.maxEqualFreq(nums)
    print(res)


from PyQt5.QtWidgets import QWidget, QAction
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Conv2D, Activation, Dense, Flatten, Reshape, Dropout, Conv2DTranspose
from tensorflow.keras.callbacks import ModelCheckpoint

import configparser
import numpy as np

# Action Settings
config = configparser.ConfigParser()
config.read('config/action_settings.ini')
SEP = config['ACTION']['SEP']
ADD = config['ACTION']['ADD']
SUB = config['ACTION']['SUB']
DIV = config['ACTION']['DIV']
MUL = config['ACTION']['MUL']
SPL = config['ACTION']['SPL']
NPZ = config['ACTION']['NPZ']
MOD = config['ACTION']['MOD']
JSN = config['ACTION']['JSN']

class ModelTrain(QWidget):
    def __init__(self, nodeflow_main, n, nn, config):
        super(ModelTrain, self).__init__()

        DATASET = config.get('DATASET')
        MODEL = config.get('MODEL')
        SETTINGS = config.get('SETTINGS')

        name = nn+'Train_Name'
        dat_dir = nn+'Dataset_Dir'
        dat_ext = nn+'Dataset_Ext'
        mod_ext = nn+'Model_Ext'
        mod_dir = nn+'Model_Dir'
        set_ext = nn+'Settings_Ext'
        set_dir = nn+'Settings_Dir'

        BATCH_SIZE = 100
        EPOCHS = 60
        OPTIMIZER = 'adam'
        LOSS = 'mse'
        MONITOR = 'val_loss'
        VERBOSE = 1

        nodeflow_main.createAttribute(node=n, name='Train_Name', preset='String', socket=True, plug=True, dataType='str', dataAttr='')

        nodeflow_main.createAttribute(node=n, name='Epochs', preset='Integer', socket=True, plug=False, dataType='int', dataAttr=EPOCHS)
        nodeflow_main.createAttribute(node=n, name='Batch_Size', preset='Integer', socket=True, plug=False, dataType='int', dataAttr=BATCH_SIZE)
        nodeflow_main.createAttribute(node=n, name='Optimizer', preset='String', socket=True, plug=False, dataType='str', dataAttr=OPTIMIZER)
        nodeflow_main.createAttribute(node=n, name='Loss', preset='String', socket=True, plug=False, dataType='str', dataAttr=LOSS)
        nodeflow_main.createAttribute(node=n, name='Monitor', preset='String', socket=True, plug=False, dataType='str', dataAttr=MONITOR)
        nodeflow_main.createAttribute(node=n, name='Verbose', preset='Integer', socket=True, plug=False, dataType='int', dataAttr=VERBOSE)

        nodeflow_main.createAttribute(node=n, name='Dataset_Path', preset='Path', socket=True, plug=True, dataType='str', dataExpr=SPL + DATASET + SPL + ADD + name + ADD + NPZ)
        nodeflow_main.createAttribute(node=n, name='Model_Path', preset='Path', socket=True, plug=True, dataType='str', dataExpr=SPL + MODEL + SPL + ADD + name + ADD + MOD)
        nodeflow_main.createAttribute(node=n, name='Settings_Path', preset='Path', socket=True, plug=True, dataType='str', dataExpr=SPL + SETTINGS + SPL + ADD + name + ADD + JSN)

class ModelTrainAction(QAction):
    """Model Train"""
    def __init__(self, attrData, config):
        super(ModelTrainAction, self).__init__()

        print("Loading previously created data...")

        npz_path = attrData.get('Dataset_Path')
        data = np.load(npz_path)
        mod_path = attrData.get('Model_Path')

        dataX = "x_test"
        dataY = "y_test"

        epochs = int(attrData.get('Epochs'))
        batch_size = int(attrData.get('Batch_Size'))

        optimizer = attrData.get('Optimizer')
        loss = attrData.get('Loss')
        monitor = attrData.get('Monitor')
        verbose = int(attrData.get('Verbose'))

        input_dim = data[dataX].shape[1:]
        output_dim = data[dataY].shape[1:]

        # Building the model
        model = Sequential()

        # convolution layers
        model.add(Conv2D(1, (1, 1), data_format="channels_last", input_shape=input_dim))
        model.add(Conv2D(2, (3, 3)))
        model.add(Conv2D(3, (4, 4)))
        model.add(Dropout(.05))

        # Transpose convolution layers (Deconvolution)
        model.add(Conv2DTranspose(3, (3, 3)))
        model.add(Conv2DTranspose(2, (5, 5)))
        model.add(Conv2DTranspose(1, (8, 8)))
        model.add(Dropout(.1))

        # Fully connected layers
        model.add(Flatten())
        model.add(Dense(np.prod(output_dim)))
        model.add(Reshape(output_dim))  # scaling to the output dimension
        model.add(Activation("linear"))  # using a "soft" activation

        model.compile(optimizer=optimizer, loss=loss)
        print(model.summary())

        # fitting the model
        print("Fitting the model...")
        checkpoint = ModelCheckpoint(mod_path, monitor=monitor, verbose=verbose, save_best_only=True)
        callbacks_list = [checkpoint]

        model.fit(data["x_train"], data["y_train"],
                  batch_size=batch_size,
                  epochs=epochs,
                  validation_data=(data[dataX], data[dataY]),
                  callbacks=callbacks_list)

        model.save_weights(mod_path)
        print("Saved model to disk")
        print('######################### TRAINING COMPLETE #########################')


import logging
from odoo import models, fields, api, tools, release, _
from odoo.exceptions import ValidationError, UserError
from .server import get_default_server
from .settings import debug

logger = logging.getLogger(__name__)

class PbxUser(models.Model):
    _name = 'asterisk_plus.user'
    _inherit = 'mail.thread'
    _description = _('Asterisk User')

    exten = fields.Char()
    user = fields.Many2one('res.users', required=True,
                           ondelete='cascade',
                           # Exclude shared users
                           domain=[('share', '=', False)])
    name = fields.Char(related='user.name', readonly=True)
    #: Server where the channel is defined.
    server = fields.Many2one('asterisk_plus.server', required=True,
                             ondelete='restrict', default=get_default_server)
    server_id = fields.Char(related='server.server_id')
    channels = fields.One2many('asterisk_plus.user_channel',
                               inverse_name='asterisk_user')
    originate_vars = fields.Text(string='Channel Variables')
    open_reference = fields.Boolean(
        default=True,
        help=_('Open reference form on incoming calls.'))
    user_call_count = fields.Integer(compute='_get_call_count', string='Calls')
    missed_calls_notify = fields.Boolean(
        default=True,
        help=_('Notify user on missed calls.'))
    call_popup_is_enabled = fields.Boolean(
        default=True,
        string='Call Popup')
    call_popup_is_sticky = fields.Boolean(
        default=True,
        string='Popup Is Sticky')

    _sql_constraints = [
        ('exten_uniq', 'unique (exten,server)',
         _('This phone extension is already used!')),
        ('user_uniq', 'unique ("user",server)',
         _('This user is already defined!')),
    ]

    @api.model
    def create(self, vals):
        user = super(PbxUser, self).create(vals)
        if user and not self.env.context.get('no_clear_cache'):
            self.pool.clear_caches()
        return user

    def write(self, vals):
        user = super(PbxUser, self).write(vals)
        if user and not self.env.context.get('no_clear_cache'):
            self.pool.clear_caches()
        return user

    @api.model
    def has_asterisk_plus_group(self):
        """Used from actions.js to check if Odoo user is enabled to
        use Asterisk applications in order to start a bus listener.
        """
        if (self.env.user.has_group('asterisk_plus.group_asterisk_admin') or
                self.env.user.has_group(
                    'asterisk_plus.group_asterisk_user')):
            return True

    def _get_originate_vars(self):
        self.ensure_one()
        try:
            if not self.originate_vars:
                return []
            return [k for k in self.originate_vars.split('\n') if k]
        except Exception:
            logger.exception('Get originate vars error:')
            return []

    def dial_user(self):
        self.ensure_one()
        self.env.user.asterisk_users[0].server.originate_call(
            self.exten, model='asterisk_plus.user', res_id=self.id)

    def open_user_form(self):
        if self.env.user.has_group('asterisk_plus.group_asterisk_admin'):
            return {
                'type': 'ir.actions.act_window',
                'res_model': 'asterisk_plus.user',
                'name': 'Users',
                'view_mode': 'tree,form',
                'view_type': 'form',
                'target': 'current',
            }
        else:
            if not self.env.user.asterisk_users:
                raise ValidationError('PBX user is not configured!')
            return {
                'type': 'ir.actions.act_window',
                'res_model': 'asterisk_plus.user',
                'res_id': self.env.user.asterisk_users.id,
                'name': 'User',
                'view_id': self.env.ref(
                    'asterisk_plus.asterisk_plus_user_user_form').id,
                'view_mode': 'form',
                'view_type': 'form',
                'target': 'current',
            }

    @api.model
    @tools.ormcache('exten', 'system_name')
    def get_res_user_id_by_exten(self, exten, system_name):
        # TODO: Is it required?
        astuser = self.search([
            ('exten', '=', exten), ('system_name', '=', system_name)], limit=1)
        debug(self, 'GET RES USER BY EXTEN {} at {}: {}'.format(
            exten, system_name, astuser))
        return astuser.user.id

    def _get_call_count(self):
        for rec in self:
            rec.user_call_count = self.env[
                'asterisk_plus.call'].sudo().search_count(
                ['|', ('calling_user', '=', rec.user.id),
                      ('called_user', '=', rec.user.id)])

    def action_view_calls(self):
        # Used from the user calls view button.
        self.ensure_one()
        return {
            'name': _("Calls"),
            'type': 'ir.actions.act_window',
            'view_mode': 'tree',
            'res_model': 'asterisk_plus.call',
            'domain': ['|', ('calling_user', '=', self.user.id),
                            ('called_user', '=', self.user.id)],
        }


"""web URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/3.2/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, include
from django.conf import settings
from django.conf.urls.static import static
from django.contrib.auth import views as auth_views
from core import views
from core.customer import views as customer_views
from core.courier import views as courier_views, apis as courier_apis

customer_urlpatters = [
    path('', customer_views.customer_page, name="home"),
    path('profile/', customer_views.profile_page, name="profile"),
    path('payment_method/', customer_views.payment_method_page, name="payment_method"),
    path('create_job/', customer_views.create_job_page, name="create_job"),
    path('jobs/current/', customer_views.current_jobs_page, name="current_jobs"),
    path('jobs/archived/', customer_views.archived_jobs_page, name="archived_jobs"),
    path('jobs/<job_id>/', customer_views.job_page, name="job"),

]

courier_urlpatters = [
    path('', courier_views.courier_page, name="home"),
    path('jobs/available/', courier_views.available_jobs_page, name="available_jobs"),

    path('api/jobs/available/', courier_apis.available_jobs_api, name="available_jobs_api"),
]

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', views.home),

    path('accounts/', include('allauth.urls')),

    path('', views.home),

    path('customer/', include((customer_urlpatters, 'customer'))),
    path('courier/', include((courier_urlpatters, 'courier'))),
]
if settings.DEBUG:
    urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)


#!/usr/bin/env python

import jinja2
import json
import logging
import webapp2
import re
from google.appengine.api import mail
from google.appengine.api import memcache
from google.appengine.api import urlfetch
from google.appengine.ext import ndb

JINJA_ENVIRONMENT = jinja2.Environment(
    loader=jinja2.FileSystemLoader('templates/'),
    extensions=['jinja2.ext.autoescape'],
    autoescape=True
)

class WebComic(ndb.Model):
    source = ndb.StringProperty()
    inst = ndb.StringProperty(default='comic')
    last_json = ndb.StringProperty()

    @property
    def last(self):
        try:
            return json.loads(self.last_json)
        except:
            return None

    @last.setter
    def last(self, value):
        self.last_json = json.dumps(value)

    @classmethod
    def get_all(cls):
        return cls.query(cls.inst == 'comic')

def get_latest_xkcd():
    data = memcache.get('xkcd-latest')
    if data is None:
        result = urlfetch.fetch('http://xkcd.com')
        content = result.content
        match = re.search('
\n<img src="(.*?)" title="(.*?)"', content)
        if not match:
            return False
        url = match.group(1)
        alt = match.group(2)
        memcache.set('xkcd-latest', [url, alt], 60*30)
    return data or [url, alt]

def get_latest_candh():
    data = memcache.get('candh-latest')
    if data is None:
        result = urlfetch.fetch('http://explosm.net/comics/')
        content = result.content
        match = re.search('', content)
        if not match:
            return False
        url = match.group(1)
        memcache.set('candh-latest', url, 60*30)
    return data or url

def get_latest_jl8():
    num = memcache.get('jl8-latest')
    if num is None:
        result = urlfetch.fetch('http://limbero.org/jl8/')
        url = result.final_url
        num = url.split('/')[-1]
        try:
            num = int(num)
        except ValueError:
            return False
        memcache.set('jl8-latest', num, 60*30)
    return num

def get_latest_smbc():
    url = memcache.get('smbc-latest')
    if url is None:
        result = urlfetch.fetch('http://smbc-comics.com')
        match = re.search('
\s*?', result.content)
        if not match:
            return False
        url = match.group(1)
        memcache.set('smbc-latest', url, 60*30)
    return url

comic_types = {
    'xkcd': get_latest_xkcd,
    'smbc': get_latest_smbc,
    #'jl8': get_latest_jl8,
    'candh': get_latest_candh,
}

pretty_names = {
    'smbc': 'SMBC',
    'jl8': 'JL8',
    'candh': 'Cyanide & Happiness'
}

def trigger_email(kind, args):
    template = JINJA_ENVIRONMENT.get_template(kind + '.html')
    html = template.render(data=args)
    message = mail.EmailMessage(
        sender='legoktm@gmail.com',
        to='legoktm@gmail.com',
        subject='A new %s is here!' % pretty_names.get(kind, kind),
        body='A new %s is here!' % pretty_names.get(kind, kind),
        html=html
    )
    message.send()
    logging.info('Sent %s email.' % kind)

class CronHandler(webapp2.RequestHandler):
    # TODO: Move this into it's own file???
    def get(self):
        comics = list(comic_types)
        query = WebComic.get_all()
        objs = []
        for model in query.fetch(100):
            if model.source in comics:
                comics.remove(model.source)
            objs.append(model)
        for cmc in comics:
            objs.append(WebComic(source=cmc))
        futures = []
        for obj in objs:
            if obj.source in comic_types:
                latest = comic_types[obj.source]()
            else:
                continue
            self.response.write(latest)
            self.response.write(obj.last)
            if latest != obj.last:
                trigger_email(obj.source, latest)
                obj.last = latest
                futures.append(obj.put_async())
        if futures:
            ndb.Future.wait_all(futures)
        self.response.write('Done.')

class MainHandler(webapp2.RequestHandler):
    def get(self):
        self.response.write('Hello world!')

class JL8(webapp2.RequestHandler):
    def get(self):
        template = JINJA_ENVIRONMENT.get_template('jl8.html')
        self.response.write(template.render(data=get_latest_jl8()))

class XKCD(webapp2.RequestHandler):
    def get(self):
        info = get_latest_xkcd()
        template = JINJA_ENVIRONMENT.get_template('xkcd.html')
        self.response.write(template.render(data=info))

class SMBC(webapp2.RequestHandler):
    def get(self):
        template = JINJA_ENVIRONMENT.get_template('smbc.html')
        self.response.write(template.render(data=get_latest_smbc()))

class CandH(webapp2.RequestHandler):
    def get(self):
        template = JINJA_ENVIRONMENT.get_template('candh.html')
        self.response.write(template.render(data=get_latest_candh()))

app = webapp2.WSGIApplication([
    ('/', MainHandler),
    ('/candh', CandH),
    ('/jl8', JL8),
    ('/xkcd', XKCD),
    ('/smbc', SMBC),
    ('/cron', CronHandler)
], debug=True)


import numpy as np
import matplotlib.pyplot as plt

class HMM(object):
    # Construct an HMM with the following set of variables
    #    numStates:          The size of the state space
    #    numOutputs:         The size of the output space
    #    trainStates[i][j]:  The jth element of the ith state sequence
    #    trainOutputs[i][j]: Similarly, for output
    def __init__(self, numStates, numOutputs, states, outputs):

        self.numStates = numStates
        self.numOutputs = numOutputs
        self.states = states
        self.outputs = outputs

        # Initialize all parameters as stated
        self.prior = np.array([0, 1/12, 1/12, 0, 1/12, 0, 1/12, 1/12, 1/12, 1/12, 1/12, 1/12, 1/12, 1/12, 0, 1/12])
        self.trans = np.zeros((16, 16))

        self.trans[1, 1] = 0.2
        self.trans[1, 2] = 0.8
        self.trans[2, 2] = 0.2
        self.trans[2, 1] = 0.4
        self.trans[2, 6] = 0.4
        self.trans[4, 4] = 0.2
        self.trans[4, 8] = 0.8
        self.trans[6, 6] = 0.2
        self.trans[6, 2] = 0.8/3.0
        self.trans[6, 7] = 0.8/3.0
        self.trans[6, 10] = 0.8/3.0
        self.trans[7, 7] = 0.2
        self.trans[7, 6] = 0.4
        self.trans[7, 11] = 0.4
        self.trans[8, 8] = 0.2
        self.trans[8, 4] = 0.8/3.0
        self.trans[8, 9] = 0.8/3.0
        self.trans[8, 12] = 0.8/3.0
        self.trans[9, 9] = 0.2
        self.trans[9, 8] = 0.8/3.0
        self.trans[9, 10] = 0.8/3.0
        self.trans[9, 13] = 0.8/3.0
        self.trans[10, 10] = 0.2
        self.trans[10, 6] = 0.8/3.0
        self.trans[10, 9] = 0.8/3.0
        self.trans[10, 11] = 0.8/3.0
        self.trans[11, 11] = 0.2
        self.trans[11, 7] = 0.8/3.0
        self.trans[11, 10] = 0.8/3.0
        self.trans[11, 15] = 0.8/3.0
        self.trans[12, 12] = 0.2
        self.trans[12, 8] = 0.4
        self.trans[12, 13] = 0.4
        self.trans[13, 13] = 0.2
        self.trans[13, 9] = 0.4
        self.trans[13, 12] = 0.4
        self.trans[15, 15] = 0.2
        self.trans[15, 11] = 0.8

        self.trans[0, 0] = 1.0
        self.trans[3, 3] = 1.0
        self.trans[5, 5] = 1.0
        self.trans[14, 14] = 1.0

        self.emit = np.zeros((16, 4))

        self.emit[1, 0] = 0.7
        self.emit[1, 1] = 0.1
        self.emit[1, 2] = 0.1
        self.emit[1, 3] = 0.1
        self.emit[2, 0] = 0.1
        self.emit[2, 1] = 0.7
        self.emit[2, 2] = 0.1
        self.emit[2, 3] = 0.1
        self.emit[4, 0] = 0.1
        self.emit[4, 1] = 0.7
        self.emit[4, 2] = 0.1
        self.emit[4, 3] = 0.1
        self.emit[6, 0] = 0.1
        self.emit[6, 1] = 0.1
        self.emit[6, 2] = 0.7
        self.emit[6, 3] = 0.1
        self.emit[7, 0] = 0.7
        self.emit[7, 1] = 0.1
        self.emit[7, 2] = 0.1
        self.emit[7, 3] = 0.1
        self.emit[8, 0] = 0.1
        self.emit[8, 1] = 0.1
        self.emit[8, 2] = 0.1
        self.emit[8, 3] = 0.7
        self.emit[9, 0] = 0.1
        self.emit[9, 1] = 0.7
        self.emit[9, 2] = 0.1
        self.emit[9, 3] = 0.1
        self.emit[10, 0] = 0.7
        self.emit[10, 1] = 0.1
        self.emit[10, 2] = 0.1
        self.emit[10, 3] = 0.1
        self.emit[11, 0] = 0.1
        self.emit[11, 1] = 0.1
        self.emit[11, 2] = 0.1
        self.emit[11, 3] = 0.7
        self.emit[12, 0] = 0.1
        self.emit[12, 1] = 0.1
        self.emit[12, 2] = 0.7
        self.emit[12, 3] = 0.1
        self.emit[13, 0] = 0.1
        self.emit[13, 1] = 0.1
        self.emit[13, 2] = 0.1
        self.emit[13, 3] = 0.7
        self.emit[15, 0] = 0.1
        self.emit[15, 1] = 0.1
        self.emit[15, 2] = 0.7
        self.emit[15, 3] = 0.1

        self.emit[0, 0] = 0.25
        self.emit[0, 1] = 0.25
        self.emit[0, 2] = 0.25
        self.emit[0, 3] = 0.25
        self.emit[3, 0] = 0.25
        self.emit[3, 1] = 0.25
        self.emit[3, 2] = 0.25
        self.emit[3, 3] = 0.25
        self.emit[5, 0] = 0.25
        self.emit[5, 1] = 0.25
        self.emit[5, 2] = 0.25
        self.emit[5, 3] = 0.25
        self.emit[14, 0] = 0.25
        self.emit[14, 1] = 0.25
        self.emit[14, 2] = 0.25
        self.emit[14, 3] = 0.25

    # compute the forward matrix for a given sequence
    def alpha_mat(self, seqnum):

        forward_mat = np.zeros((201, 16))
        normal_factor = np.zeros(201)
        ZT = self.outputs[seqnum]

        forward_mat[0, :] = self.prior * self.emit[:, ZT[0]]
        # normalize
        normal_factor[0] = sum(forward_mat[0, :])
        forward_mat[0, :] = forward_mat[0, :]/sum(forward_mat[0, :])

        for t in range(1, 201):
            for xi in range(16):
                summ = 0
                for xt_minus_1 in range(16):
                    summ += self.trans[xt_minus_1, xi] * forward_mat[t-1, xt_minus_1]
                forward_mat[t, xi] = self.emit[xi, ZT[t]] * summ
            # normalize
            normal_factor[t] = sum(forward_mat[t, :])
            forward_mat[t, :] = forward_mat[t, :]/sum(forward_mat[t, :])

        return (forward_mat, normal_factor)

    # compute the backward matrix for a given sequence and the normalization factors from forward matrix
    def beta_mat(self, seqnum, normal_factor):

        backward_mat = np.zeros((201, 16))
        ZT = self.outputs[seqnum]

        backward_mat[200, :] = np.array([1/normal_factor[200], 1/normal_factor[200], 1/normal_factor[200], 1/normal_factor[200], 1/normal_factor[200], 1/normal_factor[200], 1/normal_factor[200], 1/normal_factor[200], 1/normal_factor[200], 1/normal_factor[200], 1/normal_factor[200], 1/normal_factor[200], 1/normal_factor[200], 1/normal_factor[200], 1/normal_factor[200], 1/normal_factor[200]])

        t = 199
        while t >= 0:
            for xi in range(16):
                summ = 0
                for xt_plus_1 in range(16):
                    summ += self.emit[xt_plus_1, ZT[t+1]] * self.trans[xi, xt_plus_1] * backward_mat[t+1, xt_plus_1]
                backward_mat[t, xi] = summ
                # normalize with normal_factor of forward matrix
                backward_mat[t, xi] = backward_mat[t, xi]/normal_factor[t]
            t = t - 1

        return backward_mat

    # compute the gemma matrix from forward/backward matrices for a given sequence
    def gemma_mat(self, forward_mat, backward_mat, seqnum):

        gemma = forward_mat * backward_mat
        # normalize
        if gemma.sum(axis=1)[:, np.newaxis].all() != 0:
            gemma /= gemma.sum(axis=1)[:, np.newaxis]
        return gemma

    # compute the transition probability matrix for all time for a given sequence
    def eps_mat(self, forward_mat, backward_mat, seqnum):

        ZT = self.outputs[seqnum]
        temp = np.transpose(self.trans)
        eps_mat = np.zeros((200, 16, 16))
        for t in range(200):
            tempp = np.transpose(temp * forward_mat[t])
            eps_mat[t, :, :] = tempp * self.emit[:, ZT[t+1]] * backward_mat[t+1, :]
            # normalize
            if np.sum(eps_mat[t, :, :]) != 0:
                eps_mat[t, :, :] = eps_mat[t, :, :] / np.sum(eps_mat[t, :, :])
        return eps_mat

    # Estimate the transition and observation likelihoods and the
    # prior over the initial state based upon training data
    def train(self):

        # approximate observation log probability for all iterations
        obs_log = np.zeros(50)
        # iteration as x-axis
        x = np.zeros(50)
        # good convergence at 50 iterations
        for iterr in range(50):
            print("Epoch: " + str(iterr))
            x[iterr] = iterr
            # initialize of new iteration
            new_prior = np.zeros(16)
            trans_sum = np.zeros((16, 16))
            transdenom_sum = np.zeros((16, 16))
            emit_sum = np.zeros((16, 4))
            emitdenom_sum = np.zeros((16, 4))
            obs_sum = 0
            # go through training data
            for seqnum in range(200):
                if seqnum%10 == 0:
                    print(seqnum)

                ZT = self.outputs[seqnum]
                (forward_mat, normal_factor) = self.alpha_mat(seqnum)
                # observation probability
                obs_sum += np.prod(normal_factor)
                backward_mat = self.beta_mat(seqnum, normal_factor)
                gemma_mat = self.gemma_mat(forward_mat, backward_mat, seqnum)
                eps_mat = self.eps_mat(forward_mat, backward_mat, seqnum)
                # take in gemma at time = 0 for every gemma matrices
                new_prior = new_prior + gemma_mat[0, :]

                # calculate values that help with updates
                for i in range(16):
                    denom = np.sum(gemma_mat[0:200, i])
                    for j in range(16):
                        trans_sum[i, j] = trans_sum[i, j] + np.sum(eps_mat[:, i, j])
                        transdenom_sum[i, j] = transdenom_sum[i, j] + denom

                for i in range(16):
                    denom = np.sum(gemma_mat[:, i])
                    for m in range(4):
                        summ = 0
                        for t in range(201):
                            if ZT[t] == m:
                                summ += gemma_mat[t, i]
                        emit_sum[i, m] = emit_sum[i, m] + summ
                        emitdenom_sum[i, m] = emitdenom_sum[i, m] + denom

            print("Current observation log probability:")
            print(np.log(obs_sum))
            obs_log[iterr] = np.log(obs_sum)
            # update transition matrix
            for i in range(16):
                for j in range(16):
                    if transdenom_sum[i, j] != 0:
                        self.trans[i, j] = trans_sum[i, j]/transdenom_sum[i, j]
            # update emittion matrix
            for i in range(16):
                for m in range(4):
                    if emitdenom_sum[i, m] != 0:
                        self.emit[i, m] = emit_sum[i, m]/emitdenom_sum[i, m]
            # update prior
            self.prior = new_prior/np.sum(new_prior)

        plt.plot(x, obs_log)
        plt.xlabel('Iteration')
        plt.ylabel('Log Probability')
        plt.show()

    # # Returns the log probability associated with a transition from
    # # the dummy start state to the given state according to this HMM
    # def getLogStartProb (state):

    #     # Your code goes here
    #     print ("Please add code")

    # # Returns the log probability associated with a transition from
    # # fromState to toState according to this HMM
    # def getLogTransProb (fromState, toState):

    #     # Your code goes here
    #     print ("Please add code")

    # # Returns the log probability of state state emitting output
    # # output
    # def getLogOutputProb (state, output):

    #     # Your code goes here
    #     print ("Please add code")


#!/bin/python3
# author: Jan Hybs
import os
from typing import List

from loguru import logger
from pathlib import Path
import cihpc.core.db as db
from cihpc.core.parsers.schedule_parser import parse_args
from cihpc.core.processing.project import ProcessProject
from cihpc.core.utils import iter_project_definition
from cihpc.common.utils.vcs import HistoryBrowser, GitHistory

def main(cmd_args=None):
    from cihpc.cfg.config import global_configuration

    from cihpc.core.processing.project import ProcessProject

    # parse args
    args = parse_args(cmd_args)

    if args.secret_yaml:
        global_configuration.cfg_secret_path = args.secret_yaml

    actions: List[str] = args.actions

    # -------------------------------------------------------

    for project_definition in iter_project_definition(args):
        # prepare process
        project = ProcessProject(project_definition, initialize_repository=False)
        logger.info(f'processing project {project_definition.name}')
        scheduler = ProjectScheduler(project_definition, actions)

        scheduler.run()

class ProjectScheduler:
    def __init__(self, project, actions: List[str] = None):
        """
        :type project: cihpc.core.structures.project.Project
        """
        self.project = project
        if not self.project.use_database:
            raise ValueError(f'Project {self.project.name} must have database enabled')

        db.CIHPCMongo.set_default(
            db.CIHPCMongo.get(self.project.name)
        )

        if not self.project.git:
            raise ValueError(f'Project {self.project.name} must have git repository set')

        self.browser = HistoryBrowser(
            self.project.git.main_repo.url,
            Path(self.project.git.main_repo.dir),
        )

        self.history: List[GitHistory] = None
        self.actions = actions[:-1]
        self.test_action = actions[-1]
        logger.info(f'Git repo dir: {self.project.git.main_repo.dir}')

    def run(self):
        os.chdir(self.project.git.main_repo.dir)
        hist = list(self.browser.git_history(limit=10))
        self.history= sorted(list(set([h for h in hist])), reverse=True)
        logger.info(f'Found {len(hist)} commits, {len(self.history)} of which are unique')
        total = len(self.history)

        for i, gh in enumerate(self.history):
            logger.critical(f'[{i+1}/{total}] Running commit {gh.short_hexsha}')
            self.project.git.main_repo._commit = str(gh.commit.hexsha)
            self.project.git.main_repo._branch = 'master'  # sadly a single commit can be in several branches

            pp = ProcessProject(self.project, initialize_repository=True)
            test_stage = pp.get_stage_by_name(self.test_action)
            if not test_stage:
                continue

            threads = pp.get_stage_variable_stats(test_stage)
            need_to_run = False
            for need_repeats, db_index in threads:
                if need_repeats > 0:
                    need_to_run = True
                    break

            failed = False
            if not need_to_run:
                logger.warning(f'no need to process this commit')
            else:
                for action in self.actions:
                    logger.info(f'running stage {action}')
                    stage = pp.get_stage_by_name(action)

                    if stage:
                        if not pp.process_stage(stage):
                            # terminate the current build on error
                            logger.error(f"stage {stage.name} failed, breaking")
                            failed = True
                            break

                if not failed:
                    pp.process_stage(test_stage)

    def check_for_new_commits(self, min_reps: int = 0):
        pass

if __name__ == '__main__':
    main()


import os
import pydicom
import numpy
from matplotlib import pyplot
from PIL import Image
import PIL
import SimpleITK as sitk
import vtk
from vtkmodules.util import numpy_support
import cv2
import io
from natsort import natsorted

PathDicom = "E:/Dicom/test/DicomResource"  # 与python文件同一个目录下的文件夹
lstFilesDCM = []
DcmName = []
for dirName, subdirList, fileList in sorted(os.walk(PathDicom)):
    fileList = natsorted(fileList)
    for filename in fileList:
        if ".dcm" in filename.lower():  # 判断文件是否为dicom文件
            lstFilesDCM.append(os.path.join(dirName, filename))  # 加入到列表中
            DcmName.append(filename)

'''
RefDs = pydicom.read_file(lstFilesDCM[0],force=True)
reader = sitk.ImageSeriesReader()
dicom_names = reader.GetGDCMSeriesFileNames(PathDicom)
reader.SetFileNames(dicom_names)
image = reader.Execute()
columns = RefDs.Columns
row = RefDs.Rows
ConstOrigin = image.GetOrigin()
ConstPixelSpacing = image.GetSpacing()
ConstPixelDims = (int(row), int(columns), len(lstFilesDCM))
'''
gap = len(DcmName) - 1
file_one = pydicom.read_file(lstFilesDCM[0],force=True)
z_one = file_one.ImagePositionPatient[2]
file_tow = pydicom.read_file(lstFilesDCM[gap],force=True)
z_tow = file_tow.ImagePositionPatient[2]
columns = file_one.Columns
row = file_one.Rows
ConstPixelDims = (int(row), int(columns), len(lstFilesDCM))
if z_one > z_tow:
    slice_gap = (z_one - z_tow)/gap
    ConstOrigin = (file_tow.ImagePositionPatient[0],file_tow.ImagePositionPatient[1],file_tow.ImagePositionPatient[2])
    ConstPixelSpacing = (float(file_tow.PixelSpacing[0]), float(file_tow.PixelSpacing[1]), float(slice_gap))
else:
    slice_gap = (z_tow - z_one)/gap
    ConstOrigin = (file_one.ImagePositionPatient[0],file_one.ImagePositionPatient[1],file_one.ImagePositionPatient[2])
    ConstPixelSpacing = (float(file_one.PixelSpacing[0]), float(file_one.PixelSpacing[1]), float(slice_gap))

image_1 = int(ConstPixelDims[0]//2)
image_2 = int(ConstPixelDims[1]//2)
image_3 = int(ConstPixelDims[2]//2)
x = numpy.arange(0.0, (ConstPixelDims[0] + 1) * ConstPixelSpacing[0],ConstPixelSpacing[0])  # 0到（第一个维数加一*像素间的间隔），步长为constpixelSpacing
y = numpy.arange(0.0, (ConstPixelDims[1] + 1) * ConstPixelSpacing[1],ConstPixelSpacing[1])  #
z = numpy.arange(0.0, (ConstPixelDims[2] + 1) * ConstPixelSpacing[2],ConstPixelSpacing[2])  #
ArrayDicom = numpy.zeros(ConstPixelDims, dtype=file_one.pixel_array.dtype)

# 遍历所有的dicom文件，读取图像数据，存放在numpy数组中
for filenameDCM in lstFilesDCM:
    ds = pydicom.read_file(filenameDCM,force=True)
    ArrayDicom[:, :, lstFilesDCM.index(filenameDCM)] = ds.pixel_array

'''
fig1 = pyplot.figure(dpi=300)
pyplot.axes().set_aspect('equal','datalim')
pyplot.set_cmap(pyplot.gray())
pyplot.pcolormesh(x, y, numpy.flipud(ArrayDicom[:, :, image_3]))  # 第三个维度表示现在展示的是第几层
pyplot.axis('off')
buffer_ = io.BytesIO()
pyplot.savefig(buffer_,format='png')
buffer_.seek(0)
img1 = PIL.Image.open(buffer_)
img_arr1 = numpy.asarray(img1)
buffer_.close()

fig2 = pyplot.figure(dpi=300)
pyplot.axes().set_aspect('equal','datalim')
pyplot.set_cmap(pyplot.gray())
pyplot.pcolormesh(y, z, numpy.fliplr(numpy.rot90((ArrayDicom[image_1, :, :]),3)))
pyplot.axis('off')
buffer_ = io.BytesIO()
pyplot.savefig(buffer_,format='png')
buffer_.seek(0)
img2 = PIL.Image.open(buffer_)
img_arr2 = numpy.asarray(img2)
buffer_.close()

fig3 = pyplot.figure(dpi=300)
pyplot.axes().set_aspect('equal','datalim')
pyplot.set_cmap(pyplot.gray())
pyplot.pcolormesh(x, z, numpy.fliplr(numpy.rot90((ArrayDicom[:, image_2, :]),3)))
pyplot.axis('off')
buffer_ = io.BytesIO()
pyplot.savefig(buffer_,format='png')
buffer_.seek(0)
img3 = PIL.Image.open(buffer_)
img_arr3 = numpy.asarray(img3)
buffer_.close()

pyplot.figure(figsize=(3,1),dpi=300)
pyplot.subplot(131)
pyplot.imshow(img_arr1)
pyplot.title('AxialSlice',fontsize=4,y=0.9)
pyplot.axis('off')
pyplot.xticks([])
pyplot.yticks([])
pyplot.subplot(132)
pyplot.imshow(img_arr2)
pyplot.title('CoronalSlice',fontsize=4,y=0.9)
pyplot.axis('off')
pyplot.xticks([])
pyplot.yticks([])
pyplot.subplot(133)
pyplot.imshow(img_arr3)
pyplot.title('SagitalSlice',fontsize=4,y=0.9)
pyplot.axis('off')
pyplot.xticks([])
pyplot.yticks([])
pyplot.tight_layout(pad=0.5,w_pad=2)
pyplot.subplots_adjust(wspace=0,hspace=0)
# pyplot.savefig('E:\\Dicom\\test\\images\\'+'image.jpg')
pyplot.show()

'''
'''
pyplot.figure(dpi=300)
pyplot.axes().set_aspect('equal')
pyplot.set_cmap(pyplot.gray())
pyplot.pcolormesh(x, y, numpy.flipud(ArrayDicom[:, :, image_3]))  # 第三个维度表示现在展示的是第几层
pyplot.axis('off')
pyplot.savefig('E:\\Dicom\\test\\images\\'+'AxialSlice'+'.jpg',bbox_inches='tight',pad_inches=0.0)
pyplot.show()

pyplot.figure(dpi=300)
pyplot.axes().set_aspect('equal')
pyplot.set_cmap(pyplot.gray())
pyplot.pcolormesh(y, z, numpy.fliplr(numpy.rot90((ArrayDicom[image_1, :, :]),3)))
pyplot.axis('off')
pyplot.savefig('E:\\Dicom\\test\\images\\'+'CoronalSlice'+'.jpg',bbox_inches='tight',pad_inches=0.0)
pyplot.show()

pyplot.figure(dpi=300)
pyplot.axes().set_aspect('equal')
pyplot.set_cmap(pyplot.gray())
pyplot.pcolormesh(x, z, numpy.fliplr(numpy.rot90((ArrayDicom[:, image_2, :]),3)))
pyplot.axis('off')
pyplot.savefig('E:\\Dicom\\test\\images\\'+'SagitalSlice'+'.jpg',bbox_inches='tight',pad_inches=0.0)
pyplot.show()

'''

Array_vtk = numpy_support.numpy_to_vtk(ArrayDicom.ravel('F'), deep=True, array_type=vtk.VTK_FLOAT)
imagedata = vtk.vtkImageData()
imagedata.SetOrigin(ConstOrigin)
imagedata.SetSpacing(ConstPixelSpacing)
imagedata.SetDimensions(ConstPixelDims)
imagedata.GetPointData().SetScalars(Array_vtk)
origin = numpy.array(ConstOrigin)
ConstPixelSpacing = numpy.array(ConstPixelSpacing)
ConstPixelDims = numpy.array(ConstPixelDims)
center = origin + (ConstPixelSpacing * ConstPixelDims / 2)
DirectionCosines_x = (0, 0, 1, 0, 1, 0, -1, 0, 0)
DirectionCosines_y = (1, 0, 0, 0, 0, -1, 0, 1, 0)
DirectionCosines_z = (1, 0, 0, 0, 1, 0, 0, 0, 1)

def mip_x():
    ImageSlab = vtk.vtkImageSlabReslice()
    ImageSlab.SetInputData(imagedata)
    ImageSlab.SetResliceAxesOrigin(center)
    ImageSlab.SetResliceAxesDirectionCosines(DirectionCosines_x)
    ImageSlab.SetSlabThickness(ConstPixelSpacing[0]*ConstPixelDims[0])
    ImageSlab.SetBlendModeToMax()
    ImageSlab.SetSlabResolution(ConstPixelSpacing[0])
    ImageSlab.Update()
    image = ImageSlab.GetOutput()
    m = image.GetDimensions()
    vtk_data = image.GetPointData().GetScalars()
    arr = numpy_support.vtk_to_numpy(vtk_data).reshape(m[1], m[0])
    arr = (arr - numpy.min(arr)) / ((numpy.max(arr) - numpy.min(arr)) / 255)
    width = columns
    height = int(len(lstFilesDCM) * (ConstPixelSpacing[2] / ConstPixelSpacing[1]))
    dim = (width, height)
    resized = cv2.resize(numpy.rot90(arr, 1), dim, interpolation=cv2.INTER_AREA)
    return resized

def mip_y():
    ImageSlab = vtk.vtkImageSlabReslice()
    ImageSlab.SetInputData(imagedata)
    ImageSlab.SetResliceAxesOrigin(center)
    ImageSlab.SetResliceAxesDirectionCosines(DirectionCosines_y)
    ImageSlab.SetSlabThickness(ConstPixelSpacing[1]*ConstPixelDims[1])
    ImageSlab.SetBlendModeToMax()
    ImageSlab.SetSlabResolution(ConstPixelSpacing[1])
    ImageSlab.Update()
    image = ImageSlab.GetOutput()
    m = image.GetDimensions()
    vtk_data = image.GetPointData().GetScalars()
    arr = numpy_support.vtk_to_numpy(vtk_data).reshape(m[1], m[0])
    arr = (arr - numpy.min(arr)) / ((numpy.max(arr) - numpy.min(arr)) / 255)
    width = int(len(lstFilesDCM) * (ConstPixelSpacing[2] / ConstPixelSpacing[0]))
    height = row
    dim = (width, height)
    resized = cv2.resize(numpy.rot90(arr, -1), dim, interpolation=cv2.INTER_AREA)
    # cv2.imwrite( path +'/'+ name +'.jpg', resized)
    return resized

def mip_z():
    ImageSlab = vtk.vtkImageSlabReslice()
    ImageSlab.SetInputData(imagedata)
    ImageSlab.SetResliceAxesOrigin(center)
    ImageSlab.SetResliceAxesDirectionCosines(DirectionCosines_z)
    ImageSlab.SetSlabThickness(ConstPixelSpacing[2] * ConstPixelDims[2])
    ImageSlab.SetBlendModeToMax()
    ImageSlab.SetSlabResolution(ConstPixelSpacing[2])
    ImageSlab.Update()
    image = ImageSlab.GetOutput()
    m = image.GetDimensions()
    vtk_data = image.GetPointData().GetScalars()
    arr = numpy_support.vtk_to_numpy(vtk_data).reshape(m[1], m[0])
    arr = (arr - numpy.min(arr)) / ((numpy.max(arr) - numpy.min(arr)) / 255)
    arr = numpy.rot90(arr,-1)
    # cv2.imwrite(path+'/'+name+'.jpg', numpy.rot90(arr, -1))
    return arr

pyplot.figure(figsize=(3,1),dpi=300)
pyplot.subplot(131)
pyplot.imshow(mip_z(),cmap='gray')
pyplot.title('AxialSlice_MIP',fontsize=4,y=1.1)
pyplot.xticks([])
pyplot.yticks([])
pyplot.subplot(132)
pyplot.imshow(mip_x(),cmap='gray')
pyplot.title('CoronalSlice_MIP',fontsize=4,y=1.1)
pyplot.xticks([])
pyplot.yticks([])
pyplot.subplot(133)
pyplot.imshow(numpy.rot90(mip_y(),1),cmap='gray')
pyplot.title('SagitalSlice_MIP',fontsize=4,y=1.1)
pyplot.xticks([])
pyplot.yticks([])
pyplot.tight_layout(pad=1.3,w_pad=2)
pyplot.subplots_adjust(wspace=0,hspace=0)
# pyplot.savefig('E:\\Dicom\\test\\images\\'+'MIP_image.jpg')
pyplot.show()


from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import QMainWindow, QApplication
import converterPDFtoJPEGCore
import converterPDFtoJPEGAlertDialog
import sys

class Ui_MainWindow(object):
    def __init__(self):
        self.core = None

    def setupUi(self, MainWindow) :
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(1000, 246)
        self.initComponents(MainWindow)
        self.initLayout(MainWindow)
        self.initConnect()

    def setCore(self, core) :
        self.core = core

    def initComponents(self, MainWindow) :
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        MainWindow.setCentralWidget(self.centralwidget)

        self.fromLabel = QtWidgets.QLabel("From Folder")
        self.fromEdit = QtWidgets.QLineEdit()
        self.fromEdit.setReadOnly(True)

        self.indexBeginLabel = QtWidgets.QLabel("index begin")
        self.indexEndLabel = QtWidgets.QLabel("index end")
        self.fromPrefixLabel = QtWidgets.QLabel("Image Prefix:")
        self.fromPrefixInput = QtWidgets.QLineEdit()
        self.fromIndexBegin = QtWidgets.QSpinBox()
        self.fromIndexBegin.setMaximum(999999)
        self.fromIndexEnd = QtWidgets.QSpinBox()
        self.fromIndexEnd.setMaximum(999999)

        self.separator = QtWidgets.QWidget()
        self.separator.setStyleSheet("background-color:black;")

        self.destLabel = QtWidgets.QLabel("Destination Folder")
        self.destEdit = QtWidgets.QLineEdit()
        self.destEdit.setReadOnly(True)

        self.destPrefixLabel = QtWidgets.QLabel("Image Prefix:")
        self.destindexBeginLabel = QtWidgets.QLabel("index begin")
        self.destPrefixInput = QtWidgets.QLineEdit()
        self.destIndexBegin = QtWidgets.QSpinBox()
        self.destIndexBegin.setMaximum(999999)

        self.separator2 = QtWidgets.QWidget()
        self.separator2.setStyleSheet("background-color:black;")

        self.convertButton = QtWidgets.QPushButton("Convert")
        self.progress = QtWidgets.QProgressBar()
        self.progress.setAlignment(QtCore.Qt.AlignCenter)

    def initLayout(self, MainWindow) :
        self.vbox = QtWidgets.QVBoxLayout(self.centralwidget)
        self.vbox.addWidget(self.fromLabel)
        self.vbox.addWidget(self.destLabel)
        self.hbox1 = QtWidgets.QHBoxLayout()
        self.hbox2 = QtWidgets.QHBoxLayout()
        self.hbox3 = QtWidgets.QHBoxLayout()
        self.hbox4 = QtWidgets.QHBoxLayout()

        self.hbox1.addWidget(self.fromLabel)
        self.hbox1.addWidget(self.fromEdit)

        self.hbox2.addWidget(self.fromPrefixLabel)
        self.hbox2.addWidget(self.fromPrefixInput)
        self.hbox2.addWidget(self.indexBeginLabel)
        self.hbox2.addWidget(self.fromIndexBegin)
        self.hbox2.addWidget(self.indexEndLabel)
        self.hbox2.addWidget(self.fromIndexEnd)

        self.hbox3.addWidget(self.destLabel)
        self.hbox3.addWidget(self.destEdit)

        self.hbox4.addWidget(self.destPrefixLabel)
        self.hbox4.addWidget(self.destPrefixInput)
        self.hbox4.addWidget(self.destindexBeginLabel)
        self.hbox4.addWidget(self.destIndexBegin)

        self.vbox.addLayout(self.hbox1)
        self.vbox.addLayout(self.hbox2)
        self.vbox.addWidget(self.separator)
        self.vbox.addLayout(self.hbox3)
        self.vbox.addLayout(self.hbox4)
        self.vbox.addWidget(self.separator2)
        self.vbox.addWidget(self.convertButton)
        self.vbox.addWidget(self.progress)

    def initConnect(self) :
        self.fromEdit.selectionChanged.connect(self.openFolderfrom)
        self.destEdit.selectionChanged.connect(self.openFolderdest)
        self.convertButton.clicked.connect(self.tapOnConvertButton)
        self.fromIndexBegin.valueChanged.connect(self.fromIndexBeginChanged)
        self.fromIndexEnd.valueChanged.connect(self.fromIndexEndChanged)
        self.destIndexBegin.valueChanged.connect(self.destIndexBeginChanged)
        self.destPrefixInput.textChanged.connect(self.refreshPrefix)
        self.fromPrefixInput.textChanged.connect(self.refreshPrefix)

    def openFolderfrom(self) :
        fname = QtWidgets.QFileDialog.getExistingDirectory()
        if fname :
            self.fromEdit.setText(fname)
            self.core.sendfromFolder(fname)

    def openFolderdest(self) :
        fname = QtWidgets.QFileDialog.getExistingDirectory()
        if fname :
            self.destEdit.setText(fname)
            self.core.senddestFolder(fname)

    def fromIndexBeginChanged(self, value) :
        self.core.sendfromIndexBegin(value)

    def fromIndexEndChanged(self, value) :
        self.core.sendfromIndexEnd(value)

    def destIndexBeginChanged(self, value) :
        self.core.senddestIndexBegin(value)

    def refreshIndexfrom(self, indexBegin, indexEnd) :
        self.fromIndexEnd.setValue(indexEnd)

    def refreshPrefix(self) :
        self.core.sendPrefix(self.fromPrefixInput.text(), self.destPrefixInput.text())

    def tapOnConvertButton(self) :
        self.core.checkAllData()

    def showAlert(self, message) :
        u_dialog = QtWidgets.QDialog()
        dialog = converterPDFtoJPEGAlertDialog.ConverterPDFtoJPEGAlertDialog(u_dialog, message)
        u_dialog.exec_()

    def setValueProgressBar(self, val, max) :
        self.progress.setValue(val/max*100)

if __name__ == "__main__" :
    app = QtWidgets.QApplication(sys.argv)
    MainWindow = QtWidgets.QMainWindow()
    ui = Ui_MainWindow()
    core = converterPDFtoJPEGCore.ConverterPDFtoJPEGCore()
    ui.setupUi(MainWindow)
    ui.setCore(core)
    core.setView(ui)
    MainWindow.show()
    sys.exit(app.exec_())


from ast import Call
from re import L
from urllib.request import urlretrieve
from aiogram import Dispatcher
from aiogram.types import Message, CallbackQuery
from aiogram.dispatcher import FSMContext
from aiogram.dispatcher.filters import Text

import time
import os
import urllib
import requests

from markups.add_section import *
from models.user import User
from models.city import City
from models.category import Category
from models.section import Section, SectionPhoto
from states.find_section import FindSection
from utils.db_connection import create_db_session

from markups.find_section import *

from email_validator import validate_email, EmailNotValidError

async def select_city(message: Message):
    await FindSection.City.set()
    kb = await get_cities_kb(offset=0)
    chat_id = message["from"]["id"]
    await message.bot.send_message(
        text="""
        Город🏢
        ---
        Выберите город из
        предложенного списка.
    """,
        chat_id=chat_id,
        reply_markup=kb,
    )

async def save_city_value_and_select_category(call: CallbackQuery, state: FSMContext):
    chat_id = call["from"]["id"]
    async with state.proxy() as data:
        data["city"] = call.data.split("_")[1]

    await FindSection.Category.set()

    kb = await f_get_categories_kb(offset=0)
    await call.bot.send_message(
        text="""
        Категория
        ---
        Необходимо определиться с
        категорией.
        Так мы сможем релевантно
        подобрать места.💪
    """,
        chat_id=chat_id,
        reply_markup=kb,
    )

async def metro_or_district(call: CallbackQuery, state: FSMContext):
    await FindSection.MetroOrDistrict.set()
    async with state.proxy() as data:
        data["category"] = call.data.split("_")[1]

    chat_id = call["from"]["id"]
    await call.bot.send_message(
        text="""
        Выбор метро или района
        ---
        По какому параметру сузить
        поиск мест.🗺
    """,
        chat_id=chat_id,
        reply_markup=metro_or_district_kb,
    )

async def by_metro(call: CallbackQuery, state: FSMContext):
    await FindSection.Metro.set()
    async with state.proxy() as data:
        data["by_metro"] = True

        kb = await get_metros_kb(city=data["city"], offset=0)

    chat_id = call["from"]["id"]

    await call.bot.send_message(
        text="""
        Метро
        ---
        Укажите станцию метро🚇
    """,
        chat_id=chat_id,
        reply_markup=kb,
    )

async def by_district(call: CallbackQuery, state: FSMContext):
    await FindSection.District.set()
    async with state.proxy() as data:
        data["by_district"] = True
        kb = await get_districts_kb(city=data["city"], offset=0)

    chat_id = call["from"]["id"]

    await call.bot.send_message(
        text="""
        Район
        ---
        Укажите район📍
    """,
        chat_id=chat_id,
        reply_markup=kb,
    )

async def select_training(call: CallbackQuery, state: FSMContext):
    await FindSection.Trainings.set()
    async with state.proxy() as data:
        data["metro_or_district"] = call.data.split("_")[1]

    kb = await get_trainigs_kb(offset=0)
    chat_id = call["from"]["id"]
    await call.bot.send_message(
        text="""
        Вид занятий
        ---
        Это может быть все, что угодно,
        от йоги и стретчинга до бокса
        и функциональных тренировок.🏋♂
        ---
        Вы можете написать в ответ боту
        вид занятий, который вас
        интересует⤵
    """,
        chat_id=chat_id,
        reply_markup=kb,
    )

async def waiting_for_find(call: CallbackQuery, state: FSMContext):
    await FindSection.Wait.set()
    session_maker = await create_db_session()
    async with state.proxy() as data:
        data["traning"] = call.data

        category = await Category.get_category(
            session_maker=session_maker, name=data["category"]
        )
        category = category[0]
        if data.get("by_district"):
            district = await District.get_district(
                session_maker=session_maker, name=data["metro_or_district"]
            )
            district = district
            sections = await Section.find(
                session_maker=session_maker,
                city=data["city"],
                category_id=category.id,
                district_id=district[0].id,
            )
        else:
            metro = await Metro.get_metro(
                session_maker=session_maker, name=data["metro_or_district"]
            )
            sections = await Section.find(
                session_maker=session_maker,
                city=data["city"],
                category_id=category.id,
                metro_id=metro[0].id,
            )
        if sections == []:
            await call.bot.send_message(
                text="Подходящей секции не нашлось. ", chat_id=call['from']['id']
            )
        else:

            chat_id = call["from"]["id"]
            await call.bot.send_message(text="Ищем для вас места, ожидайте⏱", chat_id=chat_id)
            time.sleep(2)
            await call.bot.send_message(
                text="""
                Отлично!🏋
                Нашли для тебя места,
                формируем список ⚙
            """,
            chat_id=chat_id,
            )

            tranings = ""
            if type(sections[0].tranings) == list:
                for traning in sections[0].tranings:
                    tranings += traning + "\n"
            else:
                tranings = sections[0].tranings

            category = await Category.get_category(
                session_maker=session_maker, name=data["category"]
            )
            district = await District.get_district_by_id(
                session_maker=session_maker, id=sections[0].district_id
            )
            metro = await Metro.get_metro_by_id(
                session_maker=session_maker, id=sections[0].metro_id
            )

            data["section"] = sections[0]
            data['section_id'] = sections[0].id

            section_photo = await SectionPhoto.get_by_section_id(session_maker=session_maker, section_id=data['section'].id)

            if section_photo != []:
                photo = requests.get(section_photo[0].file_path)

                await call.bot.send_photo(
                photo=photo.content,
                caption=f"""
                    {sections[0].title}

                    Город:{sections[0].city}
                    Категория: {sections[0].category_id}
                    Адрес: {sections[0].address}
                    Район: {district[0].name}
                    Метро: {metro[0].name}

                    Виды занятий:
                    {tranings}
                """,
                chat_id=chat_id,
                reply_markup=waiting_for_find_kb,
                )
            else:
                await call.bot.send_message(
                    text=f"""
                    {sections[0].title}

                    Город:{sections[0].city}
                    Категория: {sections[0].category_id}
                    Адрес: {sections[0].address}
                    Район: {district[0].name}
                    Метро: {metro[0].name}

                    Виды занятий:
                    {tranings}
                """,
                chat_id=chat_id,
                reply_markup=waiting_for_find_kb,
                )

async def way(call: CallbackQuery, state: FSMContext):
    async with state.proxy() as data:
        lat = data['section'].geoposition.split(' ')[0]
        long = data['section'].geoposition.split(" ")[1]

    await call.bot.send_message(text=f"""
        Открыть карту
Москвы в приложении Яндекс.Карты
    """, chat_id=call['from']['id'])

async def consult(call: CallbackQuery, state: FSMContext):

    async with state.proxy() as data:
        await call.bot.send_message(
            text=f"""
            Подтвердите данные
            ---
            Место
            {data['section'].title}
            Имя
            {call['from']['first_name']}

            Телефон:

        """,
            chat_id=call["from"]["id"],
            reply_markup=consult_kb,
        )
    await call.bot.send_message(
        text = "Напишите свой номер телефона",
        chat_id = call['from']['id']
    )

    await call.bot.send_message(
        text=f"""
        Устанавливаем связь с местом
    """,
        chat_id=call["from"]["id"],
    )
    time.sleep(1)
    await call.bot.send_message(
        text=f"""
        Ваша заявка отправлена, в
        рабочее время с вами свяжется
        менеджер места и ответит на все
        вопросы
        ---
        Спасибо, что воспользовались
        подбором, будем рады, если
        поддержите наш бот ₽(рублем)
    """,
        chat_id=call["from"]["id"],
        reply_markup=consult_sent_kb,
    )

async def feedback(call: CallbackQuery, state: FSMContext):
    await call.bot.send_message(
        text="""
        Оцените место⭐
        ---
        Другие пользователи, при выборе места, будут учитывать рейтинг
    """,
        chat_id=call["from"]["id"],
        reply_markup=feedback_kb,
    )

async def feedback_text(call: CallbackQuery, state: FSMContext):

    rate = call.data.split("_")[1]
    session_maker = await create_db_session()
    async with state.proxy() as data:
        section = data["section"]
        await section.update_section_rates(session_maker=session_maker, rate=int(rate))

    await call.bot.send_message(
        text="""
        Напишите отзыв
        ---
        Вам нравится это место?
        Расскажите, почему!
    """,
        chat_id=call["from"]["id"],
    )

async def not_help(call: CallbackQuery, state: FSMContext):
    await call.bot.send_message(
        text="""
        Отлично
        Места, в которые вы отправили
        заявки можно посмотреть, отправив команду
        ---
        /listplace
    """,
        chat_id=call["from"]["id"],
    )

    time.sleep(10)
    await call.bot.send_message(
        text="""
        Привет!
        Это снова бот портала
        MestoSporta
        ---
        Скажите, связался ли с вами фитнес-клуб?
    """,
        chat_id=call["from"]["id"],
        reply_markup=yes_or_not_kb,
    )

async def yes_bot(call: CallbackQuery, state: FSMContext):
    await call.bot.send_message(
        text="""
        Спасибо за обратную связь. Хороших вам тренировок
    """,
    chat_id=call['from']['id']
    )

async def no_bot(call: CallbackQuery, state: FSMContext):
    await call.bot.send_message(
        text="""
        Спасибо за обратную связь. Мы поработаем над этим.
    """,
        chat_id=call["from"]["id"],
    )

def register_select_section(dp: Dispatcher):
    dp.register_callback_query_handler(select_city, text=["start_search"], state='*')
    dp.register_callback_query_handler(
        save_city_value_and_select_category,
        Text(startswith="city_"),
        state="*",
    )
    dp.register_callback_query_handler(
        metro_or_district, Text(startswith="findcategory_"), state=FindSection
    )
    dp.register_callback_query_handler(by_metro, text=["by_metro"], state='*')
    dp.register_callback_query_handler(
        by_district, text=["by_district"], state='*'
    )
    dp.register_callback_query_handler(
        select_training, Text(startswith="findmetro_"), state="*"
    )
    dp.register_callback_query_handler(
        select_training, Text(startswith="finddistrict_"), state='*'
    )
    dp.register_callback_query_handler(
        waiting_for_find, Text(startswith="findtraning_"), state='*'
    )

    dp.register_callback_query_handler(consult, text=["consult"], state='*')
    dp.register_callback_query_handler(feedback, text=["feedback"], state='*')
    dp.register_callback_query_handler(
        feedback_text, Text(startswith="rate_"), state='*'
    )

    dp.register_callback_query_handler(not_help, text=["not_help"], state='*')
    dp.register_callback_query_handler(yes_bot, text=["yes"], state='*')
    dp.register_callback_query_handler(no_bot, text=["no"], state='*')
    dp.register_callback_query_handler(way, text=['way'], state='*')

# def register_select_section(dp: Dispatcher):
#     dp.register_callback_query_handler(select_city, text=["start_search"])
#     dp.register_callback_query_handler(
#         save_city_value_and_select_category,
#         Text(startswith="city_"),
#         state=FindSection.City,
#     )
#     dp.register_callback_query_handler(
#         metro_or_district, Text(startswith="category_"), state=FindSection.Category
#     )
#     dp.register_callback_query_handler(by_metro, text=["by_metro"], state=FindSection)
#     dp.register_callback_query_handler(
#         by_district, text=["by_district"], state=FindSection
#     )
#     dp.register_callback_query_handler(
#         select_training, Text(startswith="metro_"), state=FindSection
#     )
#     dp.register_callback_query_handler(
#         select_training, Text(startswith="district_"), state=FindSection
#     )
#     dp.register_callback_query_handler(
#         waiting_for_find, Text(startswith="traning_"), state=FindSection
#     )

#     dp.register_callback_query_handler(consult, text=["consult"], state=FindSection)
#     dp.register_callback_query_handler(feedback, text=["feedback"], state=FindSection)
#     dp.register_callback_query_handler(
#         feedback_text, Text(startswith="rate_"), state=FindSection
#     )

#     dp.register_callback_query_handler(not_help, text=["not_help"], state=FindSection)
#     dp.register_callback_query_handler(yes_bot, text=["yes"], state=FindSection)
#     dp.register_callback_query_handler(no_bot, text=["no"], state=FindSection)
#     dp.register_callback_query_handler(way, text=['way'], state=FindSection)


from bs4 import BeautifulSoup
print('-----------  태그와 속성을 이용하여 데리고 오기 ------------')
# find_all('태그명',{'속성명':'값',...})
# find('태그명',{'속성명':'값',...})

# <div> 에서 id 속성의 값이 sample_id 인 것 데려오기
with open('sample.html', encoding='utf-8') as fp:   # 한글이 있는 경우 encoding='utf-8' 넣기
    soup = BeautifulSoup(fp, 'html.parser')
    sample_id_div = soup.find('div', {'id':'sample_id'})
    print(sample_id_div)

print('-----------  html 구조을 이용하여 데리고 오기 ------------')
with open('sample.html', encoding='utf-8') as fp:   # 한글이 있는 경우 encoding='utf-8' 넣기
    soup = BeautifulSoup(fp, 'html.parser')
#   id = 'sample_id인 div 태그 가져오기
    sample_id_divs = soup.find('div', {'id':'sample_id'})
#   그 태그 안에서 p 태그 가져오기
    all_ps_sample_p_sample_id_divs = sample_id_divs.find_all('p')
    print(all_ps_sample_p_sample_id_divs)

    print('-'*50)
    temp = soup.find_all('p')
    print(temp)  # p 태그 전체 추출


import urllib.request
import gevent
from gevent import monkey
monkey.patch_all()

def downloader(file_name,url):
    reponse = urllib.request.urlopen(url)
    photo_data = reponse.read()
    with open(file_name, "wb") as f:
        f.write(photo_data)
def main():
    gevent.joinall([
        gevent.spawn(downloader, "1.jpg", "http://imgsrc.baidu.com/image/c0%3Dshijue1%2C0%2C0%2C294%2C40/sign=739b937b8f35e5dd8421ad9c1eafcd9a/e61190ef76c6a7eff242db0ff7faaf51f3de66b6.jpg"),
        gevent.spawn(downloader, "2.jpg", "http://pic1.win4000.com/wallpaper/b/59c9adad14908.jpg")
    ])
if __name__ == "__main__":
    main()