## PyQT5
from PyQt5 import uic
from PyQt5.QtCore import Qt, QRunnable, pyqtSlot, pyqtSignal, QThreadPool,  \
                         QObject, QTimer, QEventLoop
from PyQt5.QtWidgets import QApplication, QMainWindow, QPushButton, \
                            QVBoxLayout, QWidget, QSlider, QFileDialog, \
                            QMessageBox, QProgressBar, QGraphicsScene, \
                            QInputDialog, QDialog
from PyQt5.QtGui import QImage, QPixmap, QPen, QPainter
from PyQt5.QtTest import QTest

## General packages
import sys
import time
import json
import os

## Custome imports
from OPTIMAQS.utils.signals import Signals
from OPTIMAQS.utils.worker import Worker
from OPTIMAQS.utils.custom_sleep_function import custom_sleep_function
from OPTIMAQS.utils.json_functions import jsonFunctions
from OPTIMAQS.utils.debug import Pyqt_debugger

### View model imports
from OPTIMAQS.view.camera.camera_gui import CameraGui
from OPTIMAQS.view.dlp.dlp_gui import DLPGui
from OPTIMAQS.view.laser.laser_gui import LaserGui
from OPTIMAQS.view.controller.controller_gui import ControllerGui
from OPTIMAQS.view.electrophysiology.electrophysiology_gui import ElectrophysiologyGui

class AutomationGui(QWidget):
    def __init__(self, info_logfile_path, timings_logfile_path):
        super(AutomationGui, self).__init__()
        self.automation_ui = uic.loadUi('OPTIMAQS/view/automation/automation.ui', self)
        self.automation_ui.show()

        self.actions()
        self.threadpool = QThreadPool()

        self.n_experiment = 1

        # Init path variables
        if jsonFunctions.find_json('OPTIMAQS/config_files/path_init.json'):
            self.path_init = self.set_main_path_from_config_file()
        else:
            self.path_init = self.set_main_path_from_user_input()

        self.path = jsonFunctions.open_json('OPTIMAQS/config_files/path_init.json')
        self.path_experiment = jsonFunctions.open_json('OPTIMAQS/config_files/last_experiment.json')
        #self.initialize_experiment()

        self.info_logfile_path = info_logfile_path
        self.timings_logfile_path = timings_logfile_path

        self.load_modules()

    def set_main_path_from_config_file(self):
        """
        Set the main path of the experiment from the path saved in the
        path_init config file.
        """
        return jsonFunctions.open_json('OPTIMAQS/config_files/path_init.json')

    def actions(self):
        """
        Define actions for buttons and items.
        """
        self.export_experiment_button.clicked.connect(self.export_experiment)
        self.load_experiment_button.clicked.connect(self.load_experiment)
        self.run_experiment_dlp_static_button.clicked.connect(self.run_experiment_dlp_static_image)
        self.run_experiment_dlp_hdmi_button.clicked.connect(self.run_experiment_dlp_hdmi)
        self.end_experiment_function = Signals()
        self.end_experiment_function.finished.connect(self.end_experiment)

    def reset(self, info_logfile_path, timings_logfile_path, path):
        ## update automation paths
        self.timings_logfile_path = timings_logfile_path
        self.info_logfile_path = info_logfile_path
        self.path = path
        ## update path of other dependancies:
        self.dlp_gui.reset(timings_logfile_path = self.timings_logfile_path,
                                       info_logfile_path = self.info_logfile_path,
                                       path_experiment = self.path)
        self.camera_gui.reset(timings_logfile_path = self.timings_logfile_path,
                                       info_logfile_path = self.info_logfile_path,
                                       path_experiment = self.path)
        self.laser_gui.reset(timings_logfile_path = self.timings_logfile_path,
                                       info_logfile_path = self.info_logfile_path)

#    def initialize_experiment(self):
#        """
#        Initialize/Reinitilize experiment logfiles and variables
#        """
#        ## reinitilize JSON files
#        self.init_log_dict()
#
#        self.images = []
#        self.image_list = []
#        self.image_reshaped = []
#        self.ephy_data = []
#        self.run_nb = 0
#
#        ## init perf_counter for timing events
#        self.perf_counter_init = time.perf_counter()
#        jsonFunctions.write_to_json(self.perf_counter_init,
#                                    'OPTIMAQS/config_files/perf_counter_init.json')
#
#        ## generate folder to save the data
#        self.path = self.path_init
#        self.path_raw_data = self.path + '\\raw_data'
#        date = time.strftime("%Y_%m_%d")
#        self.path = os.path.join(self.path, date)
#        if not os.path.exists(self.path):
#            os.makedirs(self.path) ## make a folder with the date of today if it does not already exists
#        self.path_temp = os.path.join(self.path, 'experiment_' + str(self.n_experiment))  ## in case of multiple experiments a day, need to create several subdirectory
#        while os.path.exists(self.path_temp):                             ## but necesarry to check which one aleady exists
#            self.n_experiment += 1
#            self.path_temp = os.path.join(self.path, 'experiment_' + str(self.n_experiment))
#        self.path = self.path_temp
#        self.path_raw_data = self.path + '\\raw_data'
#        os.makedirs(self.path)
#        os.makedirs(self.path + '\\dlp_images')
#        os.makedirs(self.path + '\\raw_data')
#        jsonFunctions.write_to_json(self.path, 'OPTIMAQS/config_files/last_experiment.json')
#
#        ## generate log files
#        self.info_logfile_path = self.path + "/experiment_{}_info.json".format(self.n_experiment)
#        experiment_time = time.asctime(time.localtime(time.time()))
#        self.info_logfile_dict['experiment creation date'] = experiment_time
##        with open(self.info_logfile_path,"w+") as file:       ## store basic info and comments
##            json.dump(self.info_logfile_dict, file)
#        jsonFunctions.write_to_json(self.info_logfile_dict, self.info_logfile_path)
#
#        self.timings_logfile_path = self.path + "/experiment_{}_timings.json".format(self.n_experiment)
##        with open(self.timings_logfile_path, "w+") as file:
##            json.dump(self.timings_logfile_dict, file)
#        jsonFunctions.write_to_json(self.timings_logfile_dict, self.timings_logfile_path)
#
#        # self.current_folder_label_2.setText(str(self.path)) ## show current directory in the GUI  # this doesn't work here but works in main
#
#        ## update path of other dependancies:
#        self.dlp_gui.reset(timings_logfile_path= self.timings_logfile_path,
#                                       info_logfile_path = self.info_logfile_path)
#        self.camera_gui.reset(timings_logfile_path= self.timings_logfile_path,
#                                       info_logfile_path = self.info_logfile_path,
#                                       path_experiment = self.path)
#        self.laser_gui.reset(timings_logfile_path= self.timings_logfile_path,
#                                       info_logfile_path = self.info_logfile_path)

    def load_modules(self):
        ## can there be a better way than having automation on top of main ?
        self.dlp_gui = DLPGui(info_logfile_path = self.info_logfile_path,
                              timings_logfile_path = self.timings_logfile_path)
        self.dlp_gui.setGeometry(1200, 400, 500, 100)
        self.camera_gui = CameraGui(info_logfile_path = self.info_logfile_path,
                              timings_logfile_path = self.timings_logfile_path)
        self.camera_gui.setGeometry(100, 30, 200, 900)
        self.laser_gui = LaserGui(info_logfile_path = self.info_logfile_path,
                              timings_logfile_path = self.timings_logfile_path)
        self.laser_gui.setGeometry(1200, 250, 500, 100)
#        self.controller_gui = ControllerGui
#        self.electrophysiology_gui = ElectrophysiologyGui()

#    def init_log_dict(self):
#        """
#        Initialize dictionaries that will populate the json files saving info
#        and timings
#        """
#        ## initilizing dict for timings
#        self.timings_logfile_dict = {}
#        self.timings_logfile_dict['timer_init'] = {}
#        self.timings_logfile_dict['timer_init']['main'] = []
#        self.timings_logfile_dict['timer_init']['camera'] = []
#        self.timings_logfile_dict['timer_init']['dlp'] = []
#        self.timings_logfile_dict['timer_init']['laser'] = []
#        self.timings_logfile_dict['timer_init']['ephy'] = []
#        self.timings_logfile_dict['timer_init']['ephy_stim'] = [] # do I need this one ?
#        self.timings_logfile_dict['laser'] = {}
#        self.timings_logfile_dict['laser']['on'] = []
#        self.timings_logfile_dict['laser']['off'] = []
#        self.timings_logfile_dict['dlp'] = {}
#        self.timings_logfile_dict['dlp']['on'] = []
#        self.timings_logfile_dict['dlp']['off'] = []
#        self.timings_logfile_dict['camera'] = []
#        self.timings_logfile_dict['camera_bis'] = []
#        self.timings_logfile_dict['ephy'] = {}
#        self.timings_logfile_dict['ephy']['on'] = []
#        self.timings_logfile_dict['ephy']['off'] = []
#        self.timings_logfile_dict['ephy_stim'] = {}
#        self.timings_logfile_dict['ephy_stim']['on'] = []
#        self.timings_logfile_dict['ephy_stim']['off'] = []
#        ## initilizing dict for info
#        self.info_logfile_dict = {}
#        self.info_logfile_dict['experiment creation date'] = None
#        self.info_logfile_dict['roi'] = []
#        self.info_logfile_dict['exposure time'] = []
#        self.info_logfile_dict['binning'] = []
#        self.info_logfile_dict['fov'] = []
#        self.info_logfile_dict['fps'] = []

    def dlp_static_image(self):
        ## getting values from automation gui
        mode_index = 0 ## refer to mode_index of the function selection for the dlp
        # print(str(self.dlp_mode_comboBox.currentText())) # this doesn't work here but works in main
        dlp_on = int(self.dlp_time_on_lineEdit.text())
        dlp_off = int(self.dlp_time_off_lineEdit.text())
        dlp_interval = int(self.intervalle_between_sequences_lineEdit.text())
        dlp_sequence = int(self.number_of_sequence_lineEdit.text())
        dlp_repeat_sequence = int(self.number_sequence_repetition_lineEdit.text())

        ## lauching auto protocol
        for i in range(dlp_repeat_sequence):
            for j in range(dlp_sequence):
                self.laser_gui.laser_on()
                custom_sleep_function(1000)
#                if self.electrophysiology_gui.record_electrophysiological_trace_radioButton.isChecked():
#                    self.electrophysiology_gui.ephy_stim_start()
                ## ON
                self.dlp_gui.display_mode(0) ## static image
                self.dlp_gui.choose_action(2) ## display_image
#                self.timings_logfile_dict['dlp']['on'].append((time.perf_counter() - self.perf_counter_init)*1000)
                custom_sleep_function(dlp_on)
#                if self.record_electrophysiological_trace_radioButton.isChecked():
#                    self.ephy_stim_end()
                self.dlp_gui.turn_dlp_off()
#                self.timings_logfile_dict['dlp']['off'].append((time.perf_counter() - self.perf_counter_init)*1000)
                custom_sleep_function(dlp_off)
                self.laser_gui.laser_off()
            custom_sleep_function(dlp_interval)
        self.camera_gui.camera_signal.finished.emit()
#        self.ephy_signal.finished.emit()
        self.dlp_gui.dlp_signal.finished.emit()
#        self.end_experiment_function.finished.emit()

    def dlp_static_image_repetition(self):
        experiment_repetition = int(self.experiment_repetition_lineEdit.text())
        for repeat in range(experiment_repetition):
            print(f"experiment repetition number {repeat}")
            self.run_experiment_dlp_static_image()

    def run_experiment_dlp_static_image(self):
#        self.initialize_experiment()
        dlp_worker = Worker(self.dlp_static_image)
#        ephy_worker = Worker(self.ephy_recording_thread)
        self.camera_gui.stream()
        custom_sleep_function(2000)
        self.threadpool.start(dlp_worker)  ## in those experiment the dlp function drives the camera and laser stops
        self.recording = True
        self.ephy_data = []
#        if self.record_electrophysiological_trace_radioButton.isChecked():
#            self.recording = True
#            self.threadpool.start(ephy_worker)
#
#            while not self.end_expe:
#                time.sleep(1)
#                QApplication.processEvents()

    def dlp_hdmi_video_gen(self):
        # getting value from automation gui to create video
        print('generating video for hdmi display')
        duration_of_each_image_stimulus = int(self.duration_of_each_image_stimulus_lineEdit.text())
        time_between_stimulus_image = int(self.time_between_stimulus_image_lineEdit.text())

        #TODO: other way to do that? To Simplify and reuse function in dlp_gui ?
        self.info_logfile_dict = jsonFunctions.open_json(self.info_logfile_path)
        self.roi_list = self.info_logfile_dict['roi']
        self.dlp_gui.generate_one_image_per_roi(self.roi_list)
        self.dlp_gui.movie_from_images(time_stim_image=duration_of_each_image_stimulus,
                                       inter_image_interval=time_between_stimulus_image)
        # self.dlp_gui.generate_every_paired_combination_movie(self.roi_list,
        #                                                      time_stim_image = duration_of_each_image_stimulus,
        #                                                      inter_image_interval = time_between_stimulus_image)
    def dlp_hdmi(self):
        self.laser_gui.laser_on()
        custom_sleep_function(100)
        ## ON
        self.dlp_gui.display_mode(2)
        self.dlp_gui.choose_action(1)
        custom_sleep_function(10000) #TODO: estimate length of video instead
        ## OFF
        self.dlp_gui.turn_dlp_off()
        self.laser_gui.laser_off()
        ## DELAY
        self.camera_gui.camera_signal.finished.emit()
        self.dlp_gui.dlp_signal.finished.emit()

    def dlp_hdmi_repetition(self):
        number_of_repetition = int(self.number_of_repetition_lineEdit.text())
        delay_between_repetition = int(self.delay_between_repetition_lineEdit.text())
        for i in range(number_of_repetition):
            self.run_experiment_dlp_hdmi()
            custom_sleep_function(delay_between_repetition)

    def run_experiment_dlp_hdmi(self):
        if self.run_nb == 0:
            self.dlp_hdmi_video_gen()
        dlp_hdmi_worker = Worker(self.dlp_hdmi)
        self.camera_gui.stream()
        custom_sleep_function(2000)
        self.threadpool.start(dlp_hdmi_worker)
        self.recording = True
        self.run_nb += 1

    def export_experiment(self):
        self.info_logfile_dict['roi'].append(self.roi_list)
        self.info_logfile_dict['exposure time'].append(self.exposure_time_value.value())
        self.info_logfile_dict['binning'].append(self.bin_size)
        self.info_logfile_dict['fps'].append(self.internal_frame_rate)
        self.info_logfile_dict['fov'].append((self.x_init, self.x_dim, self.y_init, self.y_dim))
        jsonFunctions.write_to_json(self.info_logfile_dict, self.info_logfile_path)
#        with open(self.info_logfile_path, "w") as file:
#            file.write(json.dumps(self.info_logfile_dict, default=lambda x:list(x), indent=4, sort_keys=True))

    def load_experiment(self):
        ## experiment json file
        self.path = QFileDialog.getExistingDirectory(None, 'Experiment folder:',
                                                        'C:/', QFileDialog.ShowDirsOnly)[0]
        experiment_path = QFileDialog.getOpenFileName(self, 'Select Experiment file',
                                                        'C:/',"Experiment file (*.json)")[0]
        # experiment_path = '/media/jeremy/Data/Data_Jeremy/2019_10_29/experiment_1/experiment_1_info.json'
        ## load/write camera related stuff
#        with open(experiment_path) as file:
#            self.info_logfile_dict = dict(json.load(file))
        self.info_logfile_dict = jsonFunctions.open_json(self.path)
        self.roi_list = self.info_logfile_dict['roi'][0]
        self.cam.write_exposure(self.info_logfile_dict['exposure time'][0])
        self.cam.write_binning(self.info_logfile_dict['binning'][0])
        self.cam.write_subarray_mode(2)
        self.x_init = self.info_logfile_dict['fov'][0][0]
        self.x_dim = self.info_logfile_dict['fov'][0][1]
        self.y_init = self.info_logfile_dict['fov'][0][2]
        self.y_dim = self.info_logfile_dict['fov'][0][3]
        self.cam.write_subarray_size(self.x_init, self.x_dim, self.y_init, self.y_dim)

    def end_experiment(self):
        print('end experiment signal received')
        self.end_expe = True

if __name__ == "__main__":
    app = QApplication(sys.argv)
    win = AutomationGui()
    win.showMaximized()
    app.exit(app.exec_())


import os
from ppadb.client import Client
import sys
import argparse
import zipfile
from tqdm import tqdm
import win32file
import requests
from bs4 import BeautifulSoup
import urllib.request
__author__ = "Paver(Zhen_Bo)"
local_version = "1.3"

def app_path():
    if hasattr(sys, 'frozen'):
        return os.path.dirname(sys.executable)  # 使用pyinstaller打包后的exe目录
    return os.path.dirname(__file__)  # 没打包前的py目录

def setup():
    adb_path = "{}/adb/adb.exe".format(app_path())
    os.system("{0} start-server".format(adb_path))
    client = Client(host="127.0.0.1", port=5037)
    devices = client.devices()
    dev = []
    print("請輸入有幾個隊員(1/2)?")
    main_count = input()
    for i in range(int(main_count)):
        print("請選擇隊員 {}".format(i+1))
        get_dev, devices = select_devices(devices)
        dev.append(get_dev)
    print("請選擇隊長")
    get_dev, devices = select_devices(devices)
    dev.append(get_dev)
    return dev

def select_devices(devices, error=0):
    for i in range(len(devices)):
        print("\033[1;32m{}: {}\033[0m".format(i+1, devices[i].serial))
    if error == 1:
        print("\033[1;31m{}\033[0m".format("!!!輸入設備編號過大!!!"))
    elif error == 2:
        print("\033[1;31m{}\033[0m".format("!!!編號輸入錯誤,請在試一次!!!"))
    inputIndex = input("請輸入編號 [1 ~ {0}]:".format(len(devices)))
    try:
        value = int(inputIndex)
        if value < 1:
            exit()
        elif value > len(devices):
            return select_devices(devices, 1)
        else:
            device = devices[value-1]
            del devices[value-1]
            return (device, devices)
    except (KeyboardInterrupt, SystemExit):
        raise Exception("KeyboardInterrupt")
    except:
        return select_devices(devices, 2)

def get_info():
    battle_info = list()
    boss = {"0": "大蛇", "1": "亞多明尼斯", "2": "白虎", "3": "Sec-5200L", "4": "詛咒艾基爾之長",
            "5": "寄居蟹船長", "6": "怒潮海怪", "7": "遺跡魔像", "8": "不死族之王雷希塔洛", "9": "風之隱者"}
    boss_code = {"0": "snake", "1": "robot", "2": "tiger", "3": "sec-5200L", "4": "curse",
                 "5": "crab", "6": "squid", "7": "golem", "8": "undead", "9": "owl"}
    level = {"0": "超級", "1": "高級+", "2": "高級", "3": "中級", "4": "初級"}
    level_code = {"0": "level_super", "1": "level_high+",
                  "2": "level_high", "3": "level_middle", "4": "level_begin"}
    select_boss = None
    while True:
        os.system('cls')
        print("請問要選擇的共鬥王為")
        for index in boss:
            print("{}: {}".format(index, boss[index]))
        print("====================================")
        number = int(input("請輸入數字代號(0~7): "))
        if number >= 0 and number <= 7:
            select_boss = boss[str(number)]
            battle_info.append(boss_code[str(number)])
            break
    while True:
        os.system('cls')
        print("已選定BOSS: {}".format(select_boss))
        print("====================================")
        print("請問要選擇的難度為")
        for index in level:
            print("{}: {}".format(index, level[index]))
        print("====================================")
        number = int(input("請輸入數字代號(0~4): "))
        if number >= 0 and number <= 4:
            battle_info.append(level_code[str(number)])
            break
    return [battle_info[0], battle_info[1]]

def check_update(version):
    print("檢查更新中...")
    # remote_version = requests.get(
    #     "https://zhen-bo.github.io/Auto-worldflipper/").text
    remote_version = urllib.request.urlopen(
        "https://zhen-bo.github.io/Auto-worldflipper/")
    remote_version = remote_version.read().decode("utf8")
    soup = BeautifulSoup(remote_version, features="html.parser")
    remote_version = soup.find_all("p", {"class": "version"})
    remote_version = remote_version[0].text.split("\n")[0]
    remote_link = "https://github.com/Zhen-bo/Auto-worldflipper/releases/download/{}/Auto-worldflipper.zip".format(
        remote_version)
    if remote_version == version:
        print("當前為最新版: {}".format(local_version))
    elif remote_version != version:
        print("即將從 {} 版 升級成 {} 版".format(version, remote_version))
        r = requests.get(remote_link, stream=True, allow_redirects=True)
        print("開始下載更新...")
        total_size = int(r.headers.get('content-length', 0))
        progress_bar = tqdm(total=total_size, unit='ib', unit_scale=True)
        with open(os.path.join(app_path(), "update.zip"), 'wb') as file:
            for data in r.iter_content(1024):
                progress_bar.update(len(data))
                file.write(data)
        progress_bar.close()
        print("下載完成")
        print("正在更新中...")
        temp_dir = os.path.join(app_path(), "_update_tmp/")
        with zipfile.ZipFile(os.path.join(app_path(), "update.zip"), 'r') as zip_ref:
            if not os.path.exists(temp_dir):
                os.mkdir(temp_dir)
            for file in tqdm(iterable=zip_ref.namelist(), total=len(zip_ref.namelist())):
                try:
                    zip_ref.extract(member=file, path=app_path())
                except:
                    try:
                        win32file.MoveFileEx(os.path.join(app_path(), file), os.path.join(
                            temp_dir, file), win32file.MOVEFILE_REPLACE_EXISTING)
                    except Exception as e:
                        if e.args[0] == 3:
                            dir_path = temp_dir
                            for folder in file.split('/')[:-1]:
                                dir_path = os.path.join(dir_path, folder)
                            file_name = file.split('/')[-1]
                            os.makedirs(dir_path)
                        win32file.MoveFileEx(os.path.join(app_path(), file), os.path.join(
                            dir_path, file_name), win32file.MOVEFILE_REPLACE_EXISTING)
                    zip_ref.extract(member=file, path=app_path())
        #os.system("start {}".format(os.path.join(app_path(), "Auto-worldflipper.exe")))
        os.system("start {}".format(
            "choice /C Y /N /D Y /T 1 & Auto-worldflipper.exe"))
        sys.exit()

if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    # 如果只有一個隊員的話是否招募並等待
    parser.add_argument("--wait_people", type=str, default="False")
    # quit=退出模式 close=重啟模式
    parser.add_argument("--mode", type=str, default="quit",)
    args = parser.parse_args()
    mode = args.mode
    os.system('cls')
    if os.path.exists(os.path.join(app_path(), "_update_tmp/")):
        os.system('choice /C Y /N /D Y /T 1 & rmdir /s {}'.format(
            os.path.join(app_path(), "_update_tmp/")))
    check_update(local_version)
    from core.bot import auto
    from core.worker import worker
    dev = setup()
    boss, level = get_info()
    try:
        if len(dev) == 2:
            main = worker(dev[0], "隊員")
            ap = worker(dev[1], "隊長")
            bot = auto(boss=boss, level=level,
                       wait_people=args.wait_people, main=main, ap=ap)
            bot.start(mode)
        else:
            main_1 = worker(dev[0], "隊員1")
            main_2 = worker(dev[1], "隊員2")
            ap = worker(dev[2], "隊長")
            bot = auto(boss=boss, level=level, wait_people=args.wait_people,
                       main=main_1, main2=main_2, ap=ap)
            bot.start(mode)
    except KeyboardInterrupt:
        print("STOP")
        sys.exit()
    except:
        os.system("PAUSE")


import json

from common.lock.py_redis_lock import Lock
from inventory_srv.model.models import Inventory, InventoryHistory
from inventory_srv.proto import inventory_pb2, inventory_pb2_grpc
from inventory_srv.settings import settings

import grpc
from google.protobuf import empty_pb2
from loguru import logger
from peewee import DoesNotExist
from rocketmq.client import ConsumeStatus, ReceivedMessage

def reback_inventory(msg: ReceivedMessage) -> ConsumeStatus:
    """
    通过 msg body 中的 order_sn 确认归还库存
    :param msg: ReceivedMessage
    :return: ConsumeStatus
    """
    msg_body = json.loads(msg.body.decode("utf-8"))
    order_sn = msg_body["orderSn"]

    with settings.DB.atomic() as txn:
        try:
            inv_history = InventoryHistory.get(
                InventoryHistory.order_sn == order_sn,
                InventoryHistory.status == 1
            )
            inv_details = json.loads(inv_history.order_inv_detail)
            for item in inv_details:
                goods_id = item["goods_id"]
                num = item["num"]
                Inventory.update(stocks=Inventory.stocks+num).where(
                    Inventory.goods == goods_id).execute()
            inv_history.status = 2
            inv_history.save()
            return ConsumeStatus.CONSUME_SUCCESS
        except DoesNotExist:
            return ConsumeStatus.CONSUME_SUCCESS
        except Exception:
            txn.rollback()
            return ConsumeStatus.RECONSUME_LATER

class InventoryServicer(inventory_pb2_grpc.InventoryServicer):

    @logger.catch
    def SetInv(
        self,
        request: inventory_pb2.GoodsInvInfo,
        context: grpc.ServicerContext
    ) -> empty_pb2.Empty:
        """
        设置商品库存
        :param request: inventory_pb2.GoodsInvInfo
        :param context: grpc.ServicerContext
        :return: empty_pb2.Empty
        """
        force_insert = False
        inv = Inventory.select().where(
            Inventory.goods == request.goodsId).first()
        if not inv:
            inv = Inventory()
            inv.goods = request.goodsId
            force_insert = True
        inv.stocks = request.num
        inv.save(force_insert=force_insert)

        return empty_pb2.Empty()

    @logger.catch
    def InvDetail(
        self,
        request: inventory_pb2.GoodsInvInfo,
        context: grpc.ServicerContext
    ) -> inventory_pb2.GoodsInvInfo:
        """
        获取某个商品库存详情
        :param request: inventory_pb2.GoodsInvInfo
        :param context: grpc.ServicerContext
        :return: inventory_pb2.GoodsInvInfo
        """
        inv = Inventory.select().where(
            Inventory.goods == request.goodsId).first()
        if not inv:
            context.set_code(grpc.StatusCode.NOT_FOUND)
            context.set_details("inventory not found")
            return inventory_pb2.GoodsInvInfo()
        return inventory_pb2.GoodsInvInfo(goodsId=inv.goods, num=inv.stocks)

    @logger.catch
    def Sell(
        self, request: inventory_pb2.SellInfo, context: grpc.ServicerContext
    ) -> empty_pb2.Empty:
        """
        扣减库存
        解决超卖问题，使用 peewee 事务
        :param request: inventory_pb2.SellInfo
        :param context: grpc.ServicerContext
        :return: empty_pb2.Empty
        """
        inv_history = InventoryHistory(order_sn=request.orderSn)
        inv_details = []
        with settings.DB.atomic() as txn:
            for item in request.goodsInfo:
                lock = Lock(settings.REDIS_CLIENT,
                            f"lock:goods:{item.goodsId}",
                            auto_renewal=True, expire=10)
                lock.acquire()
                goods_inv = Inventory.select().where(
                    Inventory.goods == item.goodsId).first()
                # 库存不存在或者库存不足
                if not goods_inv:
                    context.set_code(grpc.StatusCode.NOT_FOUND)
                    context.set_details("inventory not found")
                    txn.rollback()
                    return empty_pb2.Empty()
                if goods_inv.stocks < item.num:
                    context.set_code(grpc.StatusCode.RESOURCE_EXHAUSTED)
                    context.set_details("insufficient inventory")
                    txn.rollback()
                    return empty_pb2.Empty()
                # 扣减库存
                inv_details.append({"goods_id": item.goodsId, "num": item.num})
                goods_inv.stocks -= item.num
                goods_inv.save()
                lock.release()

            inv_history.order_inv_detail = json.dumps(inv_details)
            inv_history.save()
            return empty_pb2.Empty()

    @logger.catch
    def Reback(
        self,
        request: inventory_pb2.GoodsInvInfo,
        context: grpc.ServicerContext
    ) -> empty_pb2.Empty:
        """
        归还库存
        1. 订单超时
        2. 订单创建失败
        3. 订单取消
        :param request: inventory_pb2.GoodsInvInfo
        :param context: grpc.ServicerContext
        :return: empty_pb2.Empty
        """
        with settings.DB.atomic() as txn:
            for item in request.goodsInfo:
                lock = Lock(settings.REDIS_CLIENT,
                            f"lock:goods:{item.goodsId}",
                            auto_renewal=True, expire=10)
                lock.acquire()
                goods_inv = Inventory.select().where(
                    Inventory.goods == item.goodsId).first()
                # 库存不存在或者库存不足
                if not goods_inv:
                    context.set_code(grpc.StatusCode.NOT_FOUND)
                    context.set_details("inventory not found")
                    txn.rollback()
                    return empty_pb2.Empty()
                # 归还库存
                goods_inv.stocks += item.num
                goods_inv.save()
                lock.release()

        return empty_pb2.Empty()


"""
● Контекст
Предположим, что мы хотим найти элемент в массиве (получить
его индекс). Мы можем это сделать просто перебрав все элементы.
Но что, если массив уже отсортирован? В этом случае можно
использовать бинарный поиск. Принцип прост: сначала берём
элемент находящийся посередине и сравниваем с тем, который мы
хотим найти. Если центральный элемент больше нашего,
рассматриваем массив слева от центрального, а если больше -
справа и повторяем так до тех пор, пока не найдем наш элемент.
● Ваша задача
Написать программу на любом языке в любой парадигме для
бинарного поиска. На вход подаётся целочисленный массив и
число. На выходе - индекс элемента или -1, в случае если искомого
элемента нет в массиве."""

x=[1,3,4,6,7,8,10,11,31]
def findIndex(xx, start, key):
    end = len(xx) - 1
    while start <= end:
        middle = start + (end - start) // 2
        if xx[middle] == key:
            return middle
        elif xx[middle] < key:
            start = middle + 1
        else:
            end = middle - 1
    return -1

find_element = 10
result = findIndex(x, 0, find_element)
print(result)

"Для решения данной задачи используется процедурная и структурная парадигмы, "
"так как используется формат процедуры для нахождения индекса в списке с помощью бинарного поиска,"
"и в процедуре присутствуют циклы и ветвления."


'''
This tool is only designed to work with single cell RNA-seq fastq reads.
'''

import sys
import re
import os
import gzip
import os.path
from Bio import SeqIO
from Bio.Seq import Seq
import argparse
import subprocess

VERSION = '0.2.3'
USAGE = '''%(prog)s [options]'''

def check_status(cmd):
    ''' get command status '''
    status = 0
    try:
        output = subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT)
    except subprocess.CalledProcessError as e:
        status = e.returncode
        output = e.output
    output = output.decode()
    if output[-1] == '\n':
        output = output[:-1]
    return (status, output)

def check_dir(path):
    if not os.path.exists(path):
        os.makedirs(path)
    return(0)

def check_deps():
    status, _ = check_status('fastp --help')
    if (status != 0):
        sys.stderr.write('fastp is required for PathogenTrack!\n')

    status, _ = check_status('STAR --help')
    if (status != 0):
        sys.stderr.write('STAR is required for PathogenTrack!\n')

    status, _ = check_status('umi_tools --help')
    if (status != 0):
        sys.stderr.write('umi_tools is required for PathogenTrack!\n')

    status, _ = check_status('kraken2 --help')
    if (status != 0):
        sys.stderr.write('kraken2 is required for PathogenTrack!\n')

def trim(project_id, barcode, output): ## trim -1 at the end of barcode
    check_deps()
    check_dir(project_id)
    output = project_id + '/' + output
    fout = open(output, "w")
    with open(barcode, 'r') as fin:
        for line in fin:
            cb = line.strip().split("-")[0]
            fout.write(cb + '\n')
    fin.close()
    fout.close()

def extract(project_id, read1, read2, pattern, barcode, output, ignore_suffix): ## add cell barcode
    check_deps()
    check_dir(project_id)
    pattern = str(pattern)
    barcode = project_id + '/' + barcode
    output = project_id + '/' + output
    cmd = 'umi_tools extract --bc-pattern ' + str(pattern)
    cmd += ' --stdin ' + read1 + ' --stdout /dev/null' + ' --read2-in ' + read2
    cmd += ' --read2-out ' + output + ' --filter-cell-barcode' + ' --whitelist ' + barcode
    if (ignore_suffix):
        cmd += ' --ignore-read-pair-suffixes'
    status, stdout = check_status(cmd)
    print("status is %s and output is %s" % (status, stdout))
    return(0)

def filter(project_id, input_reads, thread, output, trim_poly_x, filter_low_complexity, complexity_threshold): ## filter low quality / complexity reads
    check_deps()
    check_dir(project_id)
    input_reads = project_id + '/' + input_reads
    output = project_id + '/' + output
    cmd = 'fastp --thread ' + str(thread) + ' -i ' + input_reads + ' -o ' + output
    if (trim_poly_x):
        cmd += ' --trim_poly_x'
    if (filter_low_complexity):
        cmd += ' --low_complexity_filter'
        if (complexity_threshold):
            cmd += ' --complexity_threshold ' + str(complexity_threshold)
    cmd += ' && rm fastp.json && rm fastp.html'
    status, stdout = check_status(cmd)
    print("status is %s and output is %s" % (status, stdout))
    return(0)

def align(project_id, star_index, input_reads, thread, output): ## do star alignment
    check_deps()
    check_dir(project_id)
    input_reads = project_id + '/' + input_reads
    output = project_id + '/' + output
    cmd = 'STAR --genomeDir ' + star_index + ' --readFilesIn ' + input_reads + ' --readFilesCommand gunzip -c '
    cmd += '--runThreadN ' + str(thread) + ' --outFilterMismatchNmax 6 ' + ' --outSAMtype None ' + ' --outFilterMultimapNmax 20 '
    cmd += '--outFilterIntronMotifs RemoveNoncanonical ' + ' --quantMode - ' + ' --outFileNamePrefix ' + project_id + '/ --outReadsUnmapped Fastx'
    cmd += ' && mv ' + project_id + '/Unmapped.out.mate1 ' + output + ' && rm ' + project_id + '/Log.final.out && rm ' + project_id + '/Log.out && rm ' + project_id + '/Log.progress.out && rm ' + project_id + '/SJ.out.tab'
    status, stdout = check_status(cmd)
    print("status is %s and output is %s" % (status, stdout))
    return(0)

def classify(project_id, kraken_db, input_reads, thread, confidence, out_reads, out_table, out_report): ## run kraken2
    check_deps()
    check_dir(project_id)
    input_reads = project_id + '/' + input_reads
    out_reads = project_id + '/' + out_reads
    out_table = project_id + '/' + out_table
    out_report = project_id + '/' + out_report

    cmd = 'kraken2 --db ' + kraken_db + ' --confidence ' + str(confidence) + ' --threads ' + str(thread) + ' --use-names --classified-out ' + out_reads + ' --report ' + out_report + ' '
    cmd += input_reads + ' | grep -w ^C > ' + out_table
    status, stdout = check_status(cmd)
    print("status is %s and output is %s" % (status, stdout))
    return(0)

def check_rank(rank):
    ranks = ['U', 'R', 'D', 'P', 'C', 'O', 'F', 'G', 'S']
    level = 0
    if rank in ranks:
        level = ranks.index(rank) # rank in comman order, eg 'F', 'G', 'S'
    elif rank[0] in ranks: # rank in sub-comman order, eg 'F1', 'G1', 'S1'
        level = ranks.index(rank[0]) + 0.5
    return(level)

def quant(project_id, barcode, input_reads, input_table, input_report, min_reads, output_reads, output_matrix): ## deduplication and quantification microbes at single-cell levels
    check_deps()
    check_dir(project_id)
    min_reads = int(min_reads)
    barcode = project_id + '/' + barcode
    input_reads = project_id + '/' + input_reads
    input_table = project_id + '/' + input_table
    input_report = project_id + '/' + input_report
    output_reads = project_id + '/' + output_reads
    output_matrix = project_id + '/' + output_matrix

    cells = set()
    with open(barcode) as fcb:
        for line in fcb:
            cb = line.strip().split("-")[0]
            cells.add(cb)
    fcb.close()

    ranks = ['U', 'R', 'D', 'P', 'C', 'O', 'F', 'G', 'S']
    Taxons = dict()
    level_taxid = '1' # initialize
    level_taxname = 'root'
    last_rank = 'R'
    current_rank = 'R'
    selected = False
    selected_taxid = ''
    selected_taxname = ''
    tmp_dict = dict() # store rows containing species/strain
    with open(input_report) as freport:
        for line in freport:
            total_count = int(line.strip().split("\t")[1])
            rank_count = int(line.strip().split("\t")[2])
            current_rank = line.strip().split("\t")[3]
            taxid = line.strip().split("\t")[4]
            taxname = line.strip().split("\t")[5].strip()
            if current_rank == 'U': # skip first line in report
                continue
            if check_rank(current_rank) < check_rank(last_rank) or check_rank(current_rank) == check_rank(last_rank) == 8: # changed organism
                last_rank = current_rank
                if selected == True:
                    for row in dict(sorted(tmp_dict.items(), key=lambda item: item[1], reverse=True)).keys():
                        if not (selected_taxid and selected_taxname):
                            selected_taxid = row.strip().split("\t")[4]
                            selected_taxname = row.strip().split("\t")[5].strip()
                            selected_reads = int(row.strip().split("\t")[2])
                        tmp_taxid = row.strip().split("\t")[4]
                        tmp_taxname = row.strip().split("\t")[5].strip()
                        if selected_reads >= min_reads:
                            Taxons[tmp_taxid] = selected_taxid + '|' + selected_taxname
                    selected = False
                    selected_taxid = ''
                    selected_taxname = ''
                    tmp_dict = dict()
                if check_rank(current_rank) >= 8:
                    if total_count == rank_count:
                        selected = True
                    tmp_dict[line] = rank_count
            else:
                last_rank = current_rank
                if check_rank(current_rank) >= 8:
                    if total_count == rank_count:
                        selected = True
                    tmp_dict[line] = rank_count
        if selected == True:
            for row in dict(sorted(tmp_dict.items(), key=lambda item: item[1], reverse=True)).keys():
                if not (selected_taxid and selected_taxname):
                    selected_taxid = row.strip().split("\t")[4]
                    selected_taxname = row.strip().split("\t")[5].strip()
                    selected_reads = int(row.strip().split("\t")[2])
                tmp_taxid = row.strip().split("\t")[4]
                tmp_taxname = row.strip().split("\t")[5].strip()

                if selected_reads >= min_reads:
                    Taxons[tmp_taxid] = selected_taxid + '|' + selected_taxname
    freport.close()

    Dict = {}
    Pool = {}
    fout = open(output_reads, "w")
    with open(input_reads) as ffastq, open(input_table) as fkraken:
        for record, row in zip(SeqIO.parse(ffastq, "fastq"), fkraken):
            cb, umi = record.id.split(" ")[0].split("_")[-2:]
            if cb not in cells:
                print("CB is: " + cb + " and UMI is: " + umi)
                continue
            taxonomy = row.split("\t")[2]
            taxname, taxid = taxonomy.split(" (taxid ")
            taxid = taxid.split(")")[0]
            if taxid == "9606" or taxid == "10090" or taxid == "28384":
                continue
            if taxid not in Taxons.keys():
                continue
            taxname = Taxons[taxid].split('|')[1]
            fout.write('>' + record.id + ' ' + taxname + '\n' + str(record.seq) + '\n')
            ids = cb + '_' + umi
            if ids not in Pool:
                Pool[ids] = {}
            if taxid not in Pool[ids]:
                Pool[ids][taxname] = 1
            else:
                Pool[ids][taxname] = Pool[ids][taxname] + 1
            if taxname in Dict:
                Dict[taxname].add(ids)
            else:
                Dict[taxname] = set()
                Dict[taxname].add(ids)
    fout.close()

    # find optimal organism with same barcode + umi
    organisms = {}
    for ids in Pool:
        organisms[ids] = sorted(Pool[ids].items(), reverse=True)[0][0]

    # store organisms in set
    organisms_set = {organisms[k] for k in organisms}

    genes = set()
    gene_counts = {}
    for gene in Dict:
        if gene not in organisms_set:
            continue
        for ids in Dict[gene]:
            cell = ids.split("_")[0]
            count = 1
            genes.add(gene)
            if gene not in gene_counts:
                gene_counts[gene] = {}
            if cell not in gene_counts[gene]:
                gene_counts[gene][cell] = 1
            else:
                gene_counts[gene][cell] = gene_counts[gene][cell] + 1

    with open(output_matrix, "w") as fmatrix:
        fmatrix.write("gene" + '\t' + '\t'.join(sorted(cells)) + '\n')
        for gene in sorted(genes):
            counts = []
            for cell in sorted(cells):
                if cell in gene_counts[gene]:
                    counts.append(gene_counts[gene][cell])
                else:
                    counts.append(0)
            if sorted(counts, reverse=True)[0] >= 2: # remove species/strains with maximum UMIs < 2
                positive_counts = str(sum(i > 0 for i in counts))
                fmatrix.write(gene + '\t' + '\t'.join(map(str, counts)) + '\n')
                print(gene + '\t' + positive_counts)
    fmatrix.close()

    return

def count(project_id, star_index, kraken_db, barcode, read1, read2, pattern, thread, confidence, min_reads, ignore_suffix, trim_poly_x, filter_low_complexity, complexity_threshold):
    check_deps()
    check_dir(project_id)
    trim(project_id, barcode, output='barcodes.tsv')
    extract(project_id, read1, read2, pattern, barcode='barcodes.tsv', output='reads_barcoded.fq.gz', ignore_suffix=ignore_suffix)
    filter(project_id, input_reads='reads_barcoded.fq.gz', thread=thread, output='reads_barcoded_clean.fq.gz', trim_poly_x=trim_poly_x, filter_low_complexity=filter_low_complexity, complexity_threshold=complexity_threshold)
    align(project_id, star_index, input_reads='reads_barcoded_clean.fq.gz', thread=thread, output='unmapped_reads.fq')
    classify(project_id, kraken_db, input_reads='unmapped_reads.fq', thread=thread, confidence=confidence, out_reads='classified_reads.fq', out_table='classified_table.txt', out_report='classified_report.txt')
    quant(project_id, barcode='barcodes.tsv', input_reads='classified_reads.fq', input_table='classified_table.txt', input_report='classified_report.txt', min_reads=min_reads, output_reads='microbes.fa', output_matrix='microbes.tsv')
    return(0)

def get_args():
    class Parser(argparse.ArgumentParser):
        def print_message(self, message, color=None):
            if message:
                sys.stderr.write('\033[91m' + message + '\033[0m\n')
        def error(self, message):
            #sys.stderr.write('\nerror: %s\n\n' % message)
            #sys.stderr.write('\033[31m', '\nerror: %s\n\n' % message)
            self.print_message('\nerror: %s\n' % message)
            self.print_help(sys.stderr)
            sys.exit(2)
    #parser = argparse.ArgumentParser(usage=USAGE)
    parser = Parser()
    # Global options
    parser.add_argument('-v', '--version', action='version', version=VERSION)
    subparsers = parser.add_subparsers(dest='command')

    # Command: count
    parser_count = subparsers.add_parser('count',
                        help='one command to count microbes at single-cell levels')
    parser_count.add_argument('--project_id', default='./', action='store',
                        help='project id to store output files', required=True)
    parser_count.add_argument('--star_index', action='store', default='',
                        help='star indices of the reference genome', required=True)
    parser_count.add_argument('--kraken_db', action='store', default='',
                        help='kraken2 database name', required=True)
    parser_count.add_argument('--barcode', action='store', default='barcodes.tsv',
                        help='file name for raw barcodes from cellranger, decompress it before use', required=True)
    parser_count.add_argument('--read1', default='',
                        help='file name for Read1', action='store', required=True)
    parser_count.add_argument('--read2', default='',
                        help='file name for Read2', action='store', required=True)
    parser_count.add_argument('--pattern', action='store', default='CCCCCCCCCCCCCCCCNNNNNNNNNN',
                        help='barcode pattern, default="CCCCCCCCCCCCCCCCNNNNNNNNNN", please refer to umi_tools help manual', required=False)
    parser_count.add_argument('--thread', action='store', default=8, type=int,
                        help='number of threads to use, default is 8', required=False)
    parser_count.add_argument('--confidence', action='store', default=0.11, type=float,
                        help='confidence threshold to use [0-1], default is 0.11', required=False)
    parser_count.add_argument('--min_reads', action='store', default=10,
                        help='minimum number of reads that supports the taxonomy, default is 10', required=False)
    parser_count.add_argument('--trim_poly_x', action='store_true',
                        help='enable polyA/T/C/G/N trimming in 3\' ends', required=False)
    parser_count.add_argument('--filter_low_complexity', action='store_true',
                        help='enable filter out low complexity reads, default is False', required=False)
    parser_count.add_argument('--complexity_threshold', action='store', default=30,
                        help='the threshold for low complexity filter [0-100], default is 30', required=False)
    parser_count.add_argument('--ignore_suffix', action='store_true',
                        help='ignore the read name suffixes, eg., /1 and /2 in the read are ignored, default is False', required=False)

    # Command: trim
    parser_trim = subparsers.add_parser('trim',
                        help='trim -1 at the end of barcode')
    parser_trim.add_argument('--project_id', default='./', action='store',
                        help='project id to store output files', required=True)
    parser_trim.add_argument('--barcode', default='', action='store',
                        help='file name for raw barcodes from cellranger, decompress it before use', required=True)
    parser_trim.add_argument('--output', default='barcodes.tsv', action='store',
                        help='file to output barcodes to, default is barcodes.tsv', required=False)

    # Command: extract
    parser_extract = subparsers.add_parser('extract',
                        help='extract and append barcode and UMI to the read2 name')
    parser_extract.add_argument('--project_id', default='./', action='store',
                        help='project id to store output files', required=True)
    parser_extract.add_argument('--read1', default='',
                        help='file name for Read1', action='store', required=True)
    parser_extract.add_argument('--read2', default='',
                        help='file name for Read2', action='store', required=True)
    parser_extract.add_argument('--pattern', action='store', default='CCCCCCCCCCCCCCCCNNNNNNNNNN',
                        help='barcode pattern, default="CCCCCCCCCCCCCCCCNNNNNNNNNN", please refer to umi_tools help manual', required=False)
    parser_extract.add_argument('--barcode', default='barcodes.tsv',
                        help='file name for valid barcodes', action='store', required=False)
    parser_extract.add_argument('--output', action='store', default='reads_barcoded.fq.gz',
                        help='file to output processed read to', required=False)
    parser_extract.add_argument('--ignore_suffix', action='store_true',
                        help='ignore the read name suffixes, eg., /1 and /2 in the read are ignored, default is False', required=False)
    # Command: filter
    parser_filter = subparsers.add_parser('filter',
                        help='filter out low quality / complexity reads')
    parser_filter.add_argument('--project_id', default='./', action='store',
                        help='project id to store output files', required=True)
    parser_filter.add_argument('--input_reads', action='store', default='reads_barcoded.fq.gz',
                        help='input single-end fastq file produced by "extract" command', required=False)
    parser_filter.add_argument('--thread', action='store', default=8, type=int,
                        help='number of threads to use, default is 8', required=False)
    parser_filter.add_argument('--output', action='store', default='reads_barcoded_clean.fq.gz',
                        help='file to output processed read to, default is reads_barcoded_clean.fq.gz', required=False)
    parser_filter.add_argument('--trim_poly_x', action='store_true',
                        help='enable polyA/T/C/G/N trimming in 3\' ends', required=False)
    parser_filter.add_argument('--filter_low_complexity', action='store_true',
                        help='enable filter out low complexity reads, default is False', required=False)
    parser_filter.add_argument('--complexity_threshold', action='store', default=30,
                        help='the threshold for low complexity filter [0-100], default is 30', required=False)
    # Command: align
    parser_align = subparsers.add_parser('align',
                        help='align clean reads to the reference genome')
    parser_align.add_argument('--project_id', default='./', action='store',
                        help='project id to store output files', required=True)
    parser_align.add_argument('--star_index', action='store', default='',
                        help='star indices of the reference genome', required=True)
    parser_align.add_argument('--input_reads', action='store', default='reads_barcoded_clean.fq.gz',
                        help='input single-end fastq file', required=False)
    parser_align.add_argument('--thread', action='store', default=8, type=int,
                        help='number of threads to use, default is 8', required=False)
    parser_align.add_argument('--output', action='store', default='unmapped_reads.fq',
                        help='file to output unmapped reads to', required=False)
    # Command: classify
    parser_classify = subparsers.add_parser('classify',
                        help='classify unmapped reads to taxons')
    parser_classify.add_argument('--project_id', default='./', action='store',
                        help='project id to store output files', required=True)
    parser_classify.add_argument('--kraken_db', action='store', default='',
                        help='kraken2 database name', required=True)
    parser_classify.add_argument('--input_reads', action='store', default='unmapped_reads.fq',
                        help='input single-end fastq file produced by "align" command', required=False)
    parser_classify.add_argument('--thread', action='store', default=8, type=int,
                        help='number of threads to use, default is 8', required=False)
    parser_classify.add_argument('--confidence', action='store', default=0.11, type=float,
                        help='confidence threshold to use [0-1], default is 0.11', required=False)
    parser_classify.add_argument('--out_reads', action='store', default='classified_reads.fq',
                        help='file to output processed reads to', required=False)
    parser_classify.add_argument('--out_table', action='store', default='classified_table.txt',
                        help='file to output kraken results to', required=False)
    parser_classify.add_argument('--out_report', action='store', default='classified_report.txt',
                        help='file to output kraken report to', required=False)
    # Command: quant
    parser_quant = subparsers.add_parser('quant',
                        help='deduplication and quantification of microbes at single-cell levels')
    parser_quant.add_argument('--project_id', default='./', action='store',
                        help='project id to store output files', required=True)
    parser_quant.add_argument('--barcode', action='store', default='barcodes.tsv',
                        help='file name for valid barcodes', required=False)
    parser_quant.add_argument('--input_reads', action='store', default='classified_reads.fq',
                        help='input fastq file produced by "classify" command', required=False)
    parser_quant.add_argument('--input_table', action='store', default='classified_table.txt',
                        help='input table file produced by "classify" command', required=False)
    parser_quant.add_argument('--input_report', action='store', default='classified_report.txt',
                        help='input report file produced by "classify" command', required=False)
    parser_quant.add_argument('--min_reads', action='store', default=10,
                        help='minimum number of reads that supports the taxonomy, default is 10', required=False)
    parser_quant.add_argument('--output_reads', action='store', default='microbes.fa',
                        help='file to output classified reads to, default is microbes.fa', required=False)
    parser_quant.add_argument('--output_matrix', action='store', default='microbes.tsv',
                        help='file to output microbe quantification matrix to, default is microbes.tsv', required=False)

    return parser

def main():
    parser = get_args()
    args = parser.parse_args()
    if not args.command:
        parser.parse_args(["--help"])
        sys.exit(0)
    if args.command == "count":
        count(args.project_id, args.star_index, args.kraken_db, args.barcode, args.read1, args.read2, args.pattern, args.thread, args.confidence, args.min_reads, args.ignore_suffix, args.trim_poly_x, args.filter_low_complexity, args.complexity_threshold)
    elif args.command == "trim":
        trim(args.project_id, args.barcode, args.output)
    elif args.command == "extract":
        extract(args.project_id, args.read1, args.read2, args.pattern, args.barcode, args.output, args.ignore_suffix)
    elif args.command == "filter":
        filter(args.project_id, args.input_reads, args.thread, args.output, args.trim_poly_x, args.filter_low_complexity, args.complexity_threshold)
    elif args.command == "align":
        align(args.project_id, args.star_index, args.input_reads, args.thread, args.output)
    elif args.command == "classify":
        classify(args.project_id, args.kraken_db, args.input_reads, args.thread, args.confidence, args.out_reads, args.out_table, args.out_report)
    elif args.command == "quant":
        quant(args.project_id, args.barcode, args.input_reads, args.input_table, args.input_report, args.min_reads, args.output_reads, args.output_matrix)
    return

if __name__ == '__main__':
    main()


import faust

app = faust.App(
    'page_views',
    broker='kafka://localhost:9092',
    topic_partitions=4,
)

# model

class PageView(faust.Record):
    id: str
    user: str

# define topc
page_view_topic = app.topic('page_views', value_type=PageView)

# define Table(similar to dict)
page_views = app.Table('page_views', default=int)

# input stream
@app.agent(page_view_topic)
async def count_page_views(views):
    async for view in views.group_by(PageView.id):
        page_views[view.id] += 1

# start worker
# faust -A parse worker -l info
# send data
# faust -A parse send page_views '{"id": "foo", "user": "bar"}'
# print key
# sudo /home/kafka/kafka/bin/kafka-console-consumer.sh --topic page_views-page_views-changelog --bootstrap-server localhost:9092 --property print.key=True --from-beginning


# -*- coding: utf-8 -*-
"""
Created on Mon May 10 09:38:10 2021

@author: 4165306
"""
import pandas as pd
import os

from tkinter import Tk
from tkinter.filedialog import askopenfilename
from tkinter.filedialog import askdirectory
from tkinter.simpledialog import askinteger

Tk().withdraw()

#Demander le type de test
typeTest = 0
codeType = "A"
while typeTest != 1 and typeTest != 2:
    typeTest = askinteger(title = 'Quel est le type de test à formater ?', prompt = 'Entrer 1 pour PCR \nEntrer 2 pour Salivaire')

#En fonction du chiffre reçu, affecter une valeur à codeType
if(typeTest == 1):
    codeType = "BPO"
elif(typeTest == 2):
    codeType = "AUT"

def extreq(filename):
    return pd.read_excel(filename)

def supprimerColonne(L):
    del L['Nom']
    del L['Prenom']
    del L['DDN']
    del L['S']
    del L['Plaque']
    del L['pos']
    return L

def split(L):
    Lres=L.query('Type == @codeType')
    return Lres

def prep(Lres):
    Lres.insert(4, "RESULTAT", 'prélèvement non conforme', allow_duplicates=False)
    Lres['ID']=Lres['Echantillon']
    return Lres

filename = askopenfilename(title = 'Export Résultat à Pousser')

folder = askdirectory(title = 'dossier cible')

os.chdir(folder)

L=extreq(filename)
L = supprimerColonne(L)
Lres=split(L)
Qres=prep(Lres)
if(codeType == "BPO"):
    R=Qres.to_csv('fichier pcr.csv',sep=',')
elif(codeType == "AUT"):
    R=Qres.to_csv('fichier slv.csv',sep=',')


import threading
import socket
import os

def escuchar(socket):
    while(True):
        data = socket.recv(1024)
        print(data.decode('utf-8'))
        print('Escriba su mensaje: ')
def enviar(socket):
    while(True):
        entrada = input()
        socket.sendall(entrada.encode('utf-8'))
        if (entrada == 'quit' or entrada == 'shutdown'):
            print('closing socket')
            socket.close()
            os._exit(1)
# Create a TCP/IP socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# Connect the socket to the port where the server is listening
server_address = ('10.10.17.191', 10000)
print('connecting to %s port %s' % server_address)
sock.connect(server_address)

th1 = threading.Thread( target=escuchar, args=(sock, ) )
th2 = threading.Thread( target= enviar, args=(sock, ) )
th1.start()
th2.start()


import warnings
from math import factorial
import numpy as np
import params as p
import boltz_states as bs
import ovlp_fn as fn
import matplotlib.pyplot as plt
import sys
np.set_printoptions(threshold=sys.maxsize)

warnings.filterwarnings('ignore') # Supresses 'casting to real discards complex part' warning

def g(t):
	D =  p.gamma*(1+0.85*p.k+0.88*p.k**2)/(2.355+1.76*p.k) # D parameter
	L =  p.k*D # LAMBDA parameter
	g = ((D/L)**2)*(L*t-1+np.exp(-L*t))+1j*((p.beta*D**2)/(2*L))*(1-np.exp(-L*t))
	#g = p.gamma*np.abs(t)#
	return g

def A(t):
	#K=np.zeros((len(p.wg),len(t)),dtype=complex)

	if type(t) == np.ndarray:
		K = np.zeros((len(p.wg),len(p.th)),dtype=complex)
	else:
		K=np.zeros((len(p.wg),1),dtype=complex)
	for l in np.arange(len(p.wg)):
		K[l,:] = (1+p.eta[l])*p.S[l]*(1-np.exp(-1j*p.wg[l]*t))+p.eta[l]*p.S[l]*(1-np.exp(1j*p.wg[l]*t))
	A = p.M**2*np.exp(-np.sum(K,axis=0))
	return A

def R(t1,t2):
	Ra = np.zeros((len(p.a),len(p.wg),len(p.wg),len(p.EL)),dtype=complex)
	R = np.zeros((len(p.wg),len(p.wg),len(p.EL)),dtype=complex)
	# for l in np.arange(len(p.wg)):
	# 	for q in p.Q:
	for idxq,q in enumerate(p.Q,start=0):
		for idxl,l in enumerate(q,start=0):

			wg = p.wg[idxl]
			S = p.S[idxl]
			eta = p.eta[idxl]
			if l == 0:
				for idxa,a in enumerate(p.a,start=0):
					Ra[idxa,idxq,idxl,:] = ((1./factorial(a))**2)*((eta*(1+eta))**a)*S**(2*a)*(((1-np.exp(-1j*wg*t1))*np.conj((1-np.exp(-1j*wg*t1))))*((1-np.exp(-1j*wg*t1))*np.conj((1-np.exp(-1j*wg*t1)))))**a
				R[idxq,idxl,:] = np.sum(Ra[:,idxq,idxl,:],axis=0)
			elif l > 0:
				for idxa,a in enumerate(p.a[l:],start=0):
					Ra[idxa,idxq,idxl,:] = ((1./(factorial(a)*factorial(a-l))))*(((1+eta)*S*(1-np.exp(-1j*wg*t1))*(1-np.exp(1j*wg*t2)))**a)*(eta*S*(1-np.exp(1j*wg*t1))*(1-np.exp(-1j*wg*t2)))**(a-l)
				R[idxq,idxl,:] = np.sum(Ra[:,idxq,idxl,:],axis=0)
			elif l < 0:
				for idxa,a in enumerate(p.b[-l:],start=0):
					Ra[idxa,idxq,idxl,:] = ((1./(factorial(a)*factorial(a+l))))*(((1+eta)*S*(1-np.exp(-1j*wg*t1))*(1-np.exp(1j*wg*t2)))**(a+l))*(eta*S*(1-np.exp(1j*wg*t1))*(1-np.exp(-1j*wg*t2)))**(a)
				R[idxq,idxl,:] = np.sum(Ra[:,idxq,idxl,:],axis=0)
	return np.prod(R,axis=1)

def cross_sections(convEL,delta,theta,D,L,M,E0):

	q_r = np.ones((len(p.wg),len(p.wg),len(p.th)),dtype=complex)
	K_r = np.zeros((len(p.wg),len(p.EL),len(p.th)),dtype=complex)
	# elif p.order > 1:
	# 	K_r = np.zeros((len(p.tm),len(p.tp),len(p.wg),len(p.EL)),dtype=complex)
	integ_r1 = np.zeros((len(p.tm),len(p.EL)),dtype=complex)
	integ_r = np.zeros((len(p.wg),len(p.EL)),dtype=complex)
	raman_cross = np.zeros((len(p.wg),len(p.convEL)),dtype=complex)

	if theta == 0.0:
		H = 1. #np.ones(len(p.E0_range))
	else:
		H = (1/(theta*np.sqrt(2*np.pi)))*np.exp(-((p.E0_range)**2)/(2*theta**2))

	thth,ELEL = np.meshgrid(p.th,p.EL,sparse=True)

	K_a = np.exp(1j*(ELEL-(p.E0))*thth-g(thth))*A(thth)
	K_f = np.exp(1j*(ELEL-(p.E0))*thth-np.conj(g(thth)))*np.conj(A(thth))

	## If the order desired is 1 use the simple first order approximation ##
	if p.order == 1:
		for idxq,q in enumerate(p.Q,start=0):
			for idxl,l in enumerate(q,start=0):
				if q[idxl] > 0:
					q_r[idxq,idxl,:] = (1./factorial(q[idxl]))**(0.5)*(((1+p.eta[idxl])**(0.5)*delta[idxl])/np.sqrt(2))**(q[idxl])*(1-np.exp(-1j*p.wg[idxl]*thth))**(q[idxl])
				elif q[idxl] < 0:
					q_r[idxq,idxl,:] = (1./factorial(np.abs(q[idxl])))**(0.5)*(((p.eta[l])**(0.5)*delta[l])/np.sqrt(2))**(-q[idxl])*(1-np.exp(1j*p.wg[idxl]*thth))**(-q[idxl])
			K_r[idxq,:,:] = K_a*(np.prod(q_r,axis=1)[idxq])

	## If the order is greater than 1, carry out the sums R and compute the full double integral
	##### Higher order is still broken, need to fix #####
	elif p.order > 1:

		tpp,tmm,ELEL = np.meshgrid(p.tp,p.tm,p.EL,sparse=True)
		K_r = np.exp(1j*(ELEL-p.E0)*np.sqrt(2)*tmm-g(tpp+tmm)/(np.sqrt(2))-np.conj(g((tpp-tmm)/(np.sqrt(2)))))#*A((tpp+tmm)/(np.sqrt(2)))*np.conj(A((tpp-tmm)/(np.sqrt(2))))#*R((tpp+tmm)/(np.sqrt(2)),(tpp-tmm)/(np.sqrt(2)))

		for idxtm,tm in enumerate(p.tm,start=0):
			integ_r1[idxtm,:] = np.trapz(K_r[(np.abs(len(p.tm)/2-idxtm)):,idxtm,:],axis=0)

		integ = np.trapz(integ_r1,axis=0)
	######################################################

	integ_a = np.trapz(K_a,axis=1)
	abs_cross = p.preA*p.convEL*np.convolve(integ_a,np.real(H),'valid')/(np.sum(H))

	integ_f = np.trapz(K_f,axis=1)
	fl_cross = p.preF*p.convEL*np.convolve(integ_f,np.real(H),'valid')/(np.sum(H))

	# plt.plot(p.convEL,abs_cross)
	# plt.plot(p.convEL,fl_cross)
	# plt.show()

	# plt.plot(integ_a)
	# plt.plot(integ_f)
	# plt.show()
	#print p.s_reorg
	#print p.w_reorg
	#print p.reorg

	for l in range(len(p.wg)):
		if p.order == 1:
			integ_r[l,:] = np.trapz(K_r[l,:,:],axis=1)
			raman_cross[l,:] = p.preR*p.convEL*(p.convEL-p.wg[l])**3*np.convolve(integ_r[l,:]*np.conj(integ_r[l,:]),np.real(H),'valid')/(np.sum(H))
		elif p.order > 1:
			raman_cross[l,:] = p.preR*p.convEL*(p.convEL-p.wg[l])**3*np.convolve(integ_r[l,:],np.real(H),'valid')/(np.sum(H))

	# plt.plot(p.convEL,fl_cross)
	# plt.plot(p.convEL,abs_cross)
	# plt.show()

	# plt.plot(p.convEL,raman_cross[0])
	# plt.plot(p.convEL,raman_cross[1])
	# plt.plot(p.convEL,raman_cross[2])
	# plt.plot(p.convEL,raman_cross[3])
	# plt.show()
	# exit()

	return (abs_cross,fl_cross,raman_cross,p.boltz_states,p.boltz_coef)


import logging

from .error import QMPError
from .events import EventListener
from .message import Message
from .protocol import (
    ConnectError,
    Runstate,
    SocketAddrT,
    StateError,
)
from .qmp_client import ExecInterruptedError, ExecuteError, QMPClient

# Suppress logging unless an application engages it.
logging.getLogger('qemu.qmp').addHandler(logging.NullHandler())

# The order of these fields impact the Sphinx documentation order.
__all__ = (
    # Classes, most to least important
    'QMPClient',
    'Message',
    'EventListener',
    'Runstate',

    # Exceptions, most generic to most explicit
    'QMPError',
    'StateError',
    'ConnectError',
    'ExecuteError',
    'ExecInterruptedError',

    # Type aliases
    'SocketAddrT',
)


from celery import shared_task
from .models import *
import time
# 带参数的分布式任务
@shared_task
def updateData(product_id, value):
    Product.objects.filter(id=product_id).update(weight=value)

# 该任务用于执行定时任务
@shared_task
def timing():
    now = time.strftime("%H:%M:%S")
    with open("E:\\output.txt", "a") as f:
        f.write("The time is " + now)
        f.write("\n")
        f.close()


import json
def parse_student_json_data(file_name):
     """
     :param file_name:
     :return:
     """
     fh = open(file_name)
     for line in fh:
          raw_data = json.loads(line)
          print("{}".format(raw_data['first_name']))

def parse_provisioner_json_data(file_name):
    """
    :param file_name:
    :return:
    """
    # fh = open(file_name)
    # raw_data = json.loads(fh)

    with open(file_name, "r") as read_file:
         data = json.load(read_file)
         #print(json.dumps(data, indent=4, sort_keys=True)) #Sorting
         #print(json.dumps(data, indent=4, sort_keys=False))  # dumps ->printing
         #print(type(data)) # object comes in as a dictionary
         #print(data) # contents of the dictionary are shown for clarity here
         # navigate through the dictionary items
         provisioner_details = data["members"][0]["name"] #- > Molecule Man
         print(type(data["members"])) # ->List
         print(type(data["members"][0]))  # ->Dic
         #provisioner_details = data['name']
         print("Provisioner Details: {}".format(provisioner_details)) # this is a list of dictionaries
         print("\n\nItems in Provisioner List:")

         for item in provisioner_details:
             print(item, "\n") # iterate through the dictionaries in the list of configuration items

if __name__ == "__main__":
     # parse_student_json_data("jsons_prov.jason")
     parse_provisioner_json_data("jsons_prov.json")
     new_data = {"student_id": "L000223344", "first_name": "Jo",
     "last_name": "Michaels"}
     print(new_data)
     with open("jsons", "a") as write_file:
          write_file.write('\n') # move onto a newline before writing object
          json.dump(new_data, write_file, indent=4,)


"""Install file for RADIS.

Typical install procedure, plus:

- auto-convert README.rst to long_description, removing some sphinx-only syntax
so it can be rendered by PyPi
- read version number from __version__.txt
- some dependencies should be installed manually (typically: all packages with
compiled components such as numpy, pandas, etc.)

Examples
--------

Install (normal, use-only)::

    python setup.py install

Or (create an alias, so you can still edit)::

    python setup.py develop

Notes
-----

For developers:

when creating a new version, just update the __version__.txt file

to register it on Pypi see register.py::

    python register.py
"""
import io
import re
import sys
from os.path import abspath, dirname, exists, join

from setuptools import Extension, find_packages, setup

# Build description from README (PyPi compatible)
# -----------------------------------------------

# Utils to format RST
def yield_sphinx_only_markup(lines):
    """Cleans-up Sphinx-only constructs (ie from README.rst), so that *PyPi*
    can format it properly.

    To check for remaining errors, install ``sphinx`` and run::

        python setup.py --long-description | sed -file 'this_file.sed' | rst2html.py  --halt=warning

    :param file_inp:     a `filename` or ``sys.stdin``?
    :param file_out:     a `filename` or ``sys.stdout`?`

    References
    ----------

    https://stackoverflow.com/questions/16367770/my-rst-readme-is-not-formatted-on-pypi-python-org

    Notes
    -----

    Check output with::

        python setup.py --long-description | rst2html.py > output.html
    """
    substs = [
        ## Selected Sphinx-only Roles.
        #
        (r":abbr:`([^`]+)`", r"\1"),
        (r":ref:`([^`]+)`", r"`\1`_"),
        (r":term:`([^`]+)`", r"**\1**"),
        (r":dfn:`([^`]+)`", r"**\1**"),
        (r":(samp|guilabel|menuselection):`([^`]+)`", r"``\2``"),
        ## Sphinx-only roles:
        #        :foo:`bar`   --> foo(``bar``)
        #        :a:foo:`bar` XXX afoo(``bar``)
        #
        # (r'(:(\w+))?:(\w+):`([^`]*)`', r'\2\3(``\4``)'),
        (r":(\w+):`([^`]*)`", r"\1(``\2``)"),
        ## Sphinx-only Directives.
        #
        (r"\.\. doctest", r"code-block"),
        (r"\.\. plot::", r".. "),
        (r"\.\. seealso", r"info"),
        (r"\.\. glossary", r"rubric"),
        (r"\.\. figure::", r".. "),
        ## Other
        #
        (r"\|version\|", r"x.x.x"),
        ## added to make RADIS docs Pypi compatible
        #        (r'\.\. image::',          r'.. '),
        #        (r'\.\. |CO2| replace:: CO\ :sub:`2`',          r'.. '),
    ]

    regex_subs = [(re.compile(regex, re.IGNORECASE), sub) for (regex, sub) in substs]

    def clean_line(line):
        try:
            for (regex, sub) in regex_subs:
                line = regex.sub(sub, line)
        except Exception as ex:
            print(("ERROR: %s, (line(%s)" % (regex, sub)))
            raise ex

        return line

    for line in lines:
        yield clean_line(line)

# (note: README.rst has been converted to README.md by register.py, and cleaned afterwards )
description = "A fast line-by-line code for high-resolution infrared molecular spectra"
readme_path = join(abspath(dirname(__file__)), "README.md")
if not exists(readme_path):
    long_description = description
else:
    with io.open(readme_path, encoding="utf-8") as f:
        long_description = f.read()

# Read version number from file
with open(join(dirname(__file__), "radis", "__version__.txt")) as version_file:
    __version__ = version_file.read().strip()

# %% Cython extensions:
# Ensures RADIS still builds if without Cython

class BuildFailed(Exception):
    pass

from distutils.errors import CCompilerError, DistutilsExecError, DistutilsPlatformError

def show_message(*lines):
    """Note : will only happen if user installs with `pip install -v`"""
    print("=" * 74, file=sys.stderr)
    for line in lines:
        print(line, file=sys.stderr)
    print("=" * 74, file=sys.stderr)

def get_ext_modules(with_binaries):
    """
    Parameters
    ----------
    with_binaries: bool
        if False, do not try to build Cython extensions
    """
    # Based on code from https://github.com/pallets/markupsafe/blob/main/setup.py

    print(sys.version)
    ext_modules = []
    cmdclass = {}

    if not with_binaries:
        # skip building extensions
        return {"cmdclass": cmdclass, "ext_modules": ext_modules}

    # TO-DO: set language level

    try:
        import cython
    except (ModuleNotFoundError) as err:
        raise BuildFailed(
            "Cython not found : Skipping all Cython extensions...!"
        ) from err

    print("Cython " + cython.__version__)

    from Cython.Distutils import build_ext

    class build_ext_subclass(build_ext):
        def build_extensions(self):
            c = self.compiler.compiler_type
            copt = {
                "msvc": ["/openmp", "/Ox", "/fp:fast", "/favor:INTEL64"],
                "mingw32": ["-fopenmp", "-O3", "-ffast-math", "-march=native"],
            }

            lopt = {"mingw32": ["-fopenmp"]}

            print("Compiling with " + c + "...")
            try:
                for e in self.extensions:
                    e.extra_compile_args = copt[c]
            except (KeyError):
                pass
            try:
                for e in self.extensions:
                    e.extra_link_args = lopt[c]
            except (KeyError):
                pass
            try:
                build_ext.build_extensions(self)
            except (CCompilerError, DistutilsExecError, DistutilsPlatformError) as err:
                raise BuildFailed() from err

    from numpy import get_include

    ext_modules.append(
        Extension(
            "radis_cython_extensions",
            sources=[
                "./radis/cython/radis_cython_extensions.pyx",
            ],
            include_dirs=[get_include()],
            language="c++",
            extra_link_args=[],
            define_macros=[("NPY_NO_DEPRECATED_API", "NPY_1_7_API_VERSION")],
        )
    )

    cmdclass["build_ext"] = build_ext_subclass

    return {"cmdclass": cmdclass, "ext_modules": ext_modules}

#%% Main install routine
def run_setup(with_binary):
    setup(
        name="radis",
        version=__version__,
        description=description,
        long_description=long_description,
        long_description_content_type="text/markdown",
        url="https://github.com/radis/radis",
        author="Erwan Pannier",
        author_email="erwan.pannier@gmail.com",
        license="GNU Lesser General Public License v3 (LGPLv3)",
        keywords=[
            "spectrum",
            "infrared",
            "spectra",
            "radiation",
            "nonequilibrium",
            "spectroscopy",
            "molecules",
            "HITRAN",
            "hitemp",
            "exomol",
            "line-by-line",
        ],
        packages=find_packages(),
        install_requires=[],
        # do not add requirements here, add them directly in the requirements.txt file
        # note EP : generate a requirement.txt by Mamba & pip freeze for Pypi deployment ? see https://stackoverflow.com/a/75239980/5622825
        extras_require={
            "dev": [
                "numpydoc",  # for Jedi (autocompletion) to recognize
                "black>=20.8b1",  # for code-linting in accordance to PEP8
                "isort",  # for sorting imports
                "pre-commit",  # to enforce Black before each commit
                "pytest",  # to run test suite
                "ipython>=7.0.0",  # useful for fast debugging
            ],
            "docs": [
                "sphinx-autodoc-annotation",
                "sphinx_autodoc_defaultargs>=0.1.2",
                "sphinx>=1.7.0",
                "astroquery>=0.3.9",
                "sphinxcontrib-apidoc",
                "sphinx-gallery",
                "lmfit",
                "pytest",  # Sphinx autodoc also parses test suite
            ],
        },
        classifiers=[
            "Development Status :: 4 - Beta",
            "Intended Audience :: Science/Research",
            "License :: OSI Approved :: GNU Lesser General Public License v3 (LGPLv3)",
            "Topic :: Scientific/Engineering",
            "Programming Language :: Python",
            "Programming Language :: Python :: 3.7",
            "Programming Language :: Python :: 3.8",
            "Programming Language :: Python :: 3.9",
            "Operating System :: OS Independent",
        ],
        **get_ext_modules(with_binary),
        include_package_data=True,  # add non .py data files in MANIFEST.in
        # package_data={'radis': ['radis/phys/units.txt']},
        zip_safe=False,  # impossible as long as we have external files read with __file__ syntax
        platforms="any",
    )

# %% Run Main install routine
try:
    run_setup(with_binary=True)
except BuildFailed:
    import traceback

    traceback.print_exc()
    show_message(
        "WARNING: RADIS C-extension could not be compiled, speedups",
        " are not enabled.",
        "Failure information, if any, is above.",
        "Retrying the build without the C extension now.",
    )
    run_setup(with_binary=False)
    show_message(
        "WARNING: RADIS C-extension could not be compiled, speedups"
        " are not enabled.",
        "Plain-Python build succeeded.",
    )


#!/usr/bin/env python3

"""
CockroachDB the Definitive Guide sample code
This code  is public domain software, i.e. not copyrighted.

Warranty Exclusion
------------------
You agree that this software is a non-commercially developed program that may
contain "bugs"   and that it may not function as intended.
The software is licensed "as is". The authors make no, and hereby expressly
disclaim all, warranties, express, implied, statutory, or otherwise
with respect to the software, including noninfringement and the implied
warranties of merchantability and fitness for a particular purpose.

@author:  gharriso (guy.a.harrison@gmail.com)

Using AS OF SYSTEM TIME

"""

import sys
import time
import csv

import psycopg2
from psycopg2 import pool

def main():

  if ((len(sys.argv)) !=2):
    sys.exit("Error:No URL provided on command line")
  uri=sys.argv[1]

  pool= psycopg2.pool.ThreadedConnectionPool(10, 40, uri) # min connection=10, max=40

  connection = pool.getconn()

  cursor=connection.cursor()
  connection.autocommit=False
  cursor.execute('ROLLBACK')
  cursor.execute("BEGIN AS OF SYSTEM TIME '-10s'" )
  top10cities=cursor.execute('''SELECT city,count(*)
                                  FROM movr.rides GROUP BY city
                                 ORDER BY 2 DESC LIMIT 10''')
  top10users=cursor.execute('''SELECT name, rides
                                 FROM movr.user_ride_counts
                                ORDER BY  rides DESC LIMIT 10''')
  cursor.execute('COMMIT')

  print (now)
  cursor.close()
  connection.close()

main()

chapters/Ch06 - Application Development/python/asOfSystemTime.py


import tkinter as tk
from tkinter import messagebox
import random as rd

window = tk.Tk()
window.geometry("900x800")
window.resizable(width=False, height=False)

Rock = """
    _______
---'   ____)
      (_____)
      (_____)
      (____)
---.__(___)
"""
Paper = """
     _______
---'    ____)____
           ______)
          _______)
         _______)
---.__________)
"""
Scissors = """
    _______
---'   ____)____
          ______)
       __________)
      (____)
---.__(___)
"""
computer_choice = ["Rock", "Paper", "Scissors"]
c_v = rd.choice(computer_choice)

def reset_game():
    btn["state"] = "active"
    btn1["state"] = "active"
    btn2["state"] = "active"
    entry.delete(0, "end")

# Disable the Button
def button_disable():
    btn["state"] = "disable"
    btn1["state"] = "disable"
    btn2["state"] = "disable"

def is_rock():
    if c_v == "Rock":
        # entry.insert(tk.END, "draw")
        messagebox.showinfo(title="Draw", message=f"Draw!! {Rock}")
    elif c_v == "Scissors":
        # entry.insert(tk.END, "Player win")
        messagebox.showinfo(title="You win!!", message=f"You win {Scissors} \ncomputer chose {Scissors}")
    else:
        # entry.insert(tk.END, "You lose!!")
        messagebox.showinfo(title="You lose!!", message=f"You lose {Rock} \ncomputer chose {Paper}")
    button_disable()

def is_paper():
    if c_v == "Paper":
        # entry.insert(tk.END, "draw")
        messagebox.showinfo(title="Draw", message=f"Draw!! {Paper}")
    elif c_v == "Scissors":
        # entry.insert(tk.END, "Player win")
        messagebox.showinfo(title="You lose!!", message=f"You lose {Paper} \ncomputer chose {Scissors}")
    else:
        # entry.insert(tk.END, "You win!!")
        messagebox.showinfo(title="You win!!", message=f"You win! {Paper} \ncomputer chose {Rock}")
    button_disable()

def is_scissors():
    if c_v == "Scissors":
        # entry.insert(tk.END, "draw")
        messagebox.showinfo(title="Draw", message=f"Draw!! {Scissors}")
    elif c_v == "Paper":
        # entry.insert(tk.END, "Player win")
        messagebox.showinfo(title="You win!!", message=f"You win! {Scissors} \ncomputer chose {Paper}")
    else:
        # entry.insert(tk.END, "Computer wins")
        messagebox.showinfo(title="You lose!!", message=f"You lose! {Scissors} \ncomputer chose {Rock}")
    button_disable()

label = tk.Label(text="""

██████╗░░█████╗░░█████╗░██╗░░██╗  ██████╗░░█████╗░██████╗░███████╗██████╗░
██╔══██╗██╔══██╗██╔══██╗██║░██╔╝  ██╔══██╗██╔══██╗██╔══██╗██╔════╝██╔══██╗
██████╔╝██║░░██║██║░░╚═╝█████═╝░  ██████╔╝███████║██████╔╝█████╗░░██████╔╝
██╔══██╗██║░░██║██║░░██╗██╔═██╗░  ██╔═══╝░██╔══██║██╔═══╝░██╔══╝░░██╔══██╗
██║░░██║╚█████╔╝╚█████╔╝██║░╚██╗  ██║░░░░░██║░░██║██║░░░░░███████╗██║░░██║
╚═╝░░╚═╝░╚════╝░░╚════╝░╚═╝░░╚═╝  ╚═╝░░░░░╚═╝░░╚═╝╚═╝░░░░░╚══════╝╚═╝░░╚═╝

░██████╗░█████╗░██╗░██████╗░██████╗░█████╗░██████╗░░██████╗
██╔════╝██╔══██╗██║██╔════╝██╔════╝██╔══██╗██╔══██╗██╔════╝
╚█████╗░██║░░╚═╝██║╚█████╗░╚█████╗░██║░░██║██████╔╝╚█████╗░
░╚═══██╗██║░░██╗██║░╚═══██╗░╚═══██╗██║░░██║██╔══██╗░╚═══██╗
██████╔╝╚█████╔╝██║██████╔╝██████╔╝╚█████╔╝██║░░██║██████╔╝
╚═════╝░░╚════╝░╚═╝╚═════╝░╚═════╝░░╚════╝░╚═╝░░╚═╝╚═════╝░
""")

label.pack()
empty_label = tk.Label()
empty_label1 = tk.Label()
empty_label2 = tk.Label()

empty_label.pack()
empty_label1.pack()
empty_label2.pack()
entry = tk.Entry(width=50)
entry.pack()

btn = tk.Button(text="Rock", bg="brown", width=8, command=is_rock)
btn1 = tk.Button(text="Paper", bg="white", width=8, command=is_paper)
btn2 = tk.Button(text="Scissors", bg="orange", width=8, command=is_scissors)
btn3 = tk.Button(text="Reset game", width=10, command=reset_game)
btn.place(x=250, y=440)
btn1.place(x=400, y=440)
btn2.place(x=550, y=440)
btn3.place(x=390, y=540)

window.mainloop()


import socket

#create socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) #SOCK_STREAM = TCP , SOCK_DGRAM = UDP

server = 'pythonprogramming.net'
port = 80
serverIP = socket.gethostbyname(server)

request = "GET / HTTP/1.1\nHost: "+server+"\n\n"
s.connect((server,port)) #connect to desired server and port
s.send(request.encode()) #python 3.x different, have to encode.
response = s.recv(4096)

print(response.decode())


import aeidon
import os

class TestPreviewAgent(aeidon.TestCase):

    def setup_method(self, method):
        self.project = self.new_project()
        self.delegate = self.project.preview.__self__

    def test_find_video__avi(self):
        video_path = aeidon.temp.create(".avi")
        sub_path = video_path.replace(".avi", ".srt")
        file = aeidon.files.new(aeidon.formats.SUBRIP,
                                sub_path,
                                "ascii")

        self.project.save_main(file)
        self.project.find_video()
        assert self.project.video_path == video_path
        os.remove(sub_path)

    def test_find_video__none(self):
        self.project.find_video()
        assert self.project.video_path is None

    def test_preview__encoding(self):
        doc = aeidon.documents.MAIN
        self.project.video_path = self.new_subrip_file()
        self.project.preview("00:00:00.000", doc, "echo", 0, "utf_8")
        assert os.path.isfile(self.project.get_file(doc).path)

    def test_preview__main(self):
        doc = aeidon.documents.MAIN
        self.project.video_path = self.new_subrip_file()
        self.project.preview("00:00:00.000", doc, "echo", 0)
        assert os.path.isfile(self.project.get_file(doc).path)

    def test_preview__translation(self):
        doc = aeidon.documents.TRAN
        self.project.video_path = self.new_subrip_file()
        self.project.preview("00:00:00.000", doc, "echo", 0)
        assert os.path.isfile(self.project.get_file(doc).path)


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

Creates a CSV file for the population.

"""
import os
import numpy as np
import pandas as pd
import re
import glob

BASE_PATH = "/home/ad247405/git/scripts/2017_memento_wmh/analysis"
INPUT_CLINIC_FILENAME = '/neurospin/brainomics/2017_memento/documents/MEMENTO_BASELINE_ML_for_catidb.csv'
INPUT_WMH = "/neurospin/cati/MEMENTO/WMH_registration_MNI_space/DB_Memento_Recalage_MNI_M00_v1"

OUTPUT_CSV = "/neurospin/brainomics/2017_memento/analysis/WMH/population.csv"

if not os.path.exists(os.path.dirname(OUTPUT_CSV)):
        os.makedirs(os.path.dirname(OUTPUT_CSV))

# Read clinic data
clinic = pd.read_csv(INPUT_CLINIC_FILENAME)

# Read free surfer assembled_data
input_subjects_wmh = dict()
paths = glob.glob(INPUT_WMH+"/*/Espace_T1/rwmh_lesion_mask*.nii.gz")
for path in paths:
    subject = os.path.basename(path)[-18:-7]
    input_subjects_wmh[subject] = [path]

# Remove if some  is missing
input_subjects_wmh = [[k]+input_subjects_wmh[k] for k in input_subjects_wmh if len(input_subjects_wmh[k]) == 1]

input_subjects_wmh = pd.DataFrame(input_subjects_wmh,  columns=["usubjid", "wmh_path"])
assert input_subjects_wmh.shape == (1757, 2)

# intersect with subject with image
clinic = clinic.merge(input_subjects_wmh, on="usubjid")
assert  clinic.shape == (1755, 26)

pop = clinic

# Save population information
pop.to_csv(OUTPUT_CSV, index=False)


from django.views.generic import DetailView, ListView, TemplateView

from .models import Event

class AboutView(TemplateView):
    template_name = "main/index.html"

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context["event_types"] = Event.TypeChoice.choices
        return context

class EventsView(ListView):
    template_name = "main/events.html"

    def get_queryset(self):
        return Event.objects.filter(type=self.kwargs["event_type"]).order_by("-date")

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context["event_types"] = Event.TypeChoice.choices
        return context

class EventDetailView(DetailView):
    model = Event
    template_name = "main/event_detail.html"

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context["event_types"] = Event.TypeChoice.choices
        return context


from flask import *
from database import *
staff=Blueprint('staff',__name__)

@staff.route('/staffhome')
def staffhome():
	return render_template('staffhome.html')

@staff.route('/staffmanage_category',methods=['get','post'])
def staffmanage_category():
	data={}
	q="select * from categories"
	res=select(q)
	data['category']=res

	if 'action' in request.args:
		action=request.args['action']
		id=request.args['id']
	else:
		action=None
	if action=="delete":
		q="delete from categories where category_id='%s'"%(id)
		delete(q)
		return redirect(url_for('staff.staffmanage_category'))
	if action=="update":
		q="select * from categories where category_id='%s'"%(id)
		res=select(q)
		data['cat']=res
	if 'update' in request.form:
		category=request.form['category']
		q="update categories set category_name='%s' where category_id='%s'"%(category,id)
		update(q)
		return redirect(url_for('staff.staffmanage_category'))

	if 'submit' in request.form:
		category=request.form['category']
		q="insert categories values(null,'%s')"%(category)
		insert(q)
		return redirect(url_for('staff.staffmanage_category'))
	return render_template('staffmanage_category.html',data=data)

@staff.route('/staffviewelection',methods=['get','post'])
def staffviewelection():
	data={}
	q="select * from election"
	res=select(q)
	data['election']=res
	return render_template('staffviewelection.html',data=data)

@staff.route('/staffviewcandidates',methods=['get','post'])
def staffviewcandidates():
	data={}
	q="select * from candidates inner join election using(election_id) inner join student using(student_id)"
	res=select(q)
	data['candidates']=res
	return render_template('staffviewcandidates.html',data=data)

@staff.route('/staffviewresult',methods=['get','post'])
def staffviewresult():
	eid=request.args['eid']
	data={}
	q="SELECT * FROM results INNER JOIN election USING(election_id) INNER JOIN candidates USING(candidate_id) WHERE results.election_id='%s'"%(eid)
	res=select(q)
	data['results']=res
	return render_template('staffviewresult.html',data=data)

@staff.route('/staff_manage_candidates',methods=['get','post'])
def staff_manage_candidates():
	eid=request.args['eid']
	data={}
	data['eid']=eid

	q="select * from student"
	res=select(q)
	data['stud']=res

	q="select * from categories"
	res=select(q)
	data['categ']=res

	q="select * from candidates inner join election using(election_id) inner join student using(student_id) INNER JOIN `categories` USING(`category_id`)"
	res=select(q)
	data['candidates']=res
	if 'action' in request.args:
		action=request.args['action']
		id=request.args['id']
	else:
		action=None
	if action=="delete":
		q="delete from candidates where candidate_id='%s'"%(id)
		delete(q)
		return redirect(url_for('staff.staff_manage_candidates',eid=eid))

	if action=="update":
		q="select * from candidates where candidate_id='%s'"%(id)
		res=select(q)
		data['candi']=res
	if 'update' in request.form:
		sname=request.form['sname']

		q="update candidates set student_id='%s' where candidate_id='%s'"%(sname,id)
		update(q)
		return redirect(url_for('staff.staff_manage_candidates',eid=eid))

	if 'submit' in request.form:
		sname=request.form['sname']
		cat_id=request.form['cat_id']
		q="insert into candidates values(NULL,'%s','%s','%s','pending')"%(sname,eid,cat_id)
		insert(q)
		return redirect(url_for('staff.staff_manage_candidates',eid=eid))
	return render_template('staff_manage_candidates.html',data=data)


from pymongo import MongoClient
import datetime

mongo=MongoClient(host='localhost',port=27017)
a_document={'name':'jane',
                        'age':34,
                        'interests':['python','database','statistics'],
                        'date_added':datetime.datetime.now()}
# 选择一个尚未建立的db
db=mongo.my_data
# 选择一个尚未建立的collection
collection =db.docs
#寻找资料，即使数据库或资料不存在也不会产生例外异常
collection.find_one()
#列出目前db内所有的collection
print(db.list_collection_names())
collection.insert_one(a_document)
print(db.list_collection_names())
#不设条件寻找一笔资料
print(collection.find_one())
#寻找一笔资料
collection.find_one({'name':'jane'})

#MongoDB是用字典(键加上值)来进行搜寻以找出文件
#update
collection.update_one({'name':'jane'},{"$set":{'age':29}})
print(collection.find_one())
#replace 替换
collection.replace_one({'name':'jane'},{'username':'flag','date_added':datetime.datetime.now()})
print(collection.find_one())
#delete 删除
collection.delete_one({'username':'flag'})
print(collection.find_one())
print(db.list_collection_names())
collection.drop()
print(db.list_collection_names())


# -*- coding: utf-8 -*-
"""
 @Time    : 2019/1/24 0:30
 @Author  : Wang Xin
 @Email   : wangxin_buaa@163.com
"""

import numpy as np
import os
import cv2
from tqdm import tqdm
import sys

sys.path.append('../utils')
from tool.utils import *

data_path = '/home/data/UnsupervisedDepth/KITTI-raw/kitti_raw_data/'
train_depth_dir = '/home/data/UnsupervisedDepth/KITTI-raw/train_gt16bit/'
test_depth_dir = '/home/data/UnsupervisedDepth/KITTI-raw/test_gt16bit/'
val_depth_dir = '/home/data/UnsupervisedDepth/KITTI-raw/val_gt16bit/'

if not os.path.isdir(train_depth_dir):
    os.makedirs(train_depth_dir)

if not os.path.isdir(test_depth_dir):
    os.makedirs(test_depth_dir)

if not os.path.isdir(val_depth_dir):
    os.makedirs(val_depth_dir)

max_depth = 80
img_width = 621
img_height = 188

img_files = []
img_labels = []

train_fid = open('./filenames/eigen_train_files.txt', 'r')
test_fid = open('./filenames/eigen_test_files.txt', 'r')
val_fid = open('./filenames/eigen_val_files.txt')

train_lines = train_fid.readlines()
test_lines = test_fid.readlines()
val_lines = val_fid.readlines()

print('train images num is ', len(train_lines))
print('test images num is ', len(test_lines))
print('val images num is ', len(val_lines))

train_rgbd_fid = open('eigen_train_pairs.txt', 'w')
test_rgbd_fid = open('eigen_test_pairs.txt', 'w')
val_rgbd_fid = open('eigen_val_pairs.txt', 'w')

print('Processing training images')
for in_idx in tqdm(range(len(train_lines))):
    # print(train_lines[in_idx])

    img_lines0 = train_lines[in_idx].split(' ')[0]
    index_f = str(in_idx + 1)
    img_name = index_f.zfill(5) + '.png'

    # load image and depth
    gt_file, gt_calib, im_size, im_file, cams = read_file_data_new(train_lines[in_idx], data_path)
    # print('cams:', cams)
    camera_id = cams[0]
    depth = generate_depth_map(gt_calib[0], gt_file[0], im_size[0], camera_id, False, True)
    print(depth)
    print(np.max(depth), np.min(depth))

    im_depth_16 = (depth * 100).astype(np.uint16)
    print(np.max(im_depth_16), np.min(im_depth_16))

    filename2 = os.path.join(train_depth_dir, img_name)
    file_line = os.path.join('kitti_raw_data', img_lines0) + ' ' + os.path.join('train_gt16bit', img_name) + '\n'
    train_rgbd_fid.write(file_line)
    cv2.imwrite(filename2, im_depth_16)
    exit(-1)

print('Processing test images')
for in_idx in tqdm(range(len(test_lines))):
    img_lines0 = test_lines[in_idx].split(' ')[0]
    index_f = str(in_idx + 1)
    img_name = index_f.zfill(5) + '.png'

    # load image and depth
    gt_file, gt_calib, im_size, im_file, cams = read_file_data_new(test_lines[in_idx], data_path)
    camera_id = cams[0]

    depth = generate_depth_map(gt_calib[0], gt_file[0], im_size[0], camera_id, False, True)
    im_depth_16 = (depth * 100).astype(np.uint16)

    filename2 = os.path.join(test_depth_dir, img_name)
    file_line = os.path.join('kitti_raw_data', img_lines0) + ' ' + os.path.join('test_gt16bit', img_name) + '\n'
    test_rgbd_fid.write(file_line)
    cv2.imwrite(filename2, im_depth_16)

print('Processing val images')
for in_idx in tqdm(range(len(val_lines))):
    img_lines0 = val_lines[in_idx].split(' ')[0]
    index_f = str(in_idx + 1)
    img_name = index_f.zfill(5) + '.png'

    # load image and depth
    gt_file, gt_calib, im_size, im_file, cams = read_file_data_new(val_lines[in_idx], data_path)
    camera_id = cams[0]

    depth = generate_depth_map(gt_calib[0], gt_file[0], im_size[0], camera_id, False, True)
    im_depth_16 = (depth * 100).astype(np.uint16)

    filename2 = os.path.join(val_depth_dir, img_name)
    file_line = os.path.join('kitti_raw_data', img_lines0) + ' ' + os.path.join('val_gt16bit', img_name) + '\n'
    val_rgbd_fid.write(file_line)
    cv2.imwrite(filename2, im_depth_16)

train_fid.close()
train_rgbd_fid.close()
test_fid.close()
test_rgbd_fid.close()
val_fid.close()
val_rgbd_fid.close()


sample = open("sample.txt", "r").read()
final_input = open("input.txt", "r").read()

def have_dup(String):
    for c in String:
        cnt = 0
        for i in range(len(String)):
            if String[i] == c: cnt += 1
        if cnt != 1: return True
    return False

def solve(Input, marker_length, start):
    i = start
    while i < len(Input):
        c = Input[i]
        if not have_dup(Input[i:i+marker_length]):
            return i + marker_length
        i += 1
    return -1

def part1(Input):
    return solve(Input,4,0)

def part2(Input):
    return solve(Input,14,0)

print("part1 (sample input) :",part1(sample))
print("part1 (final input)  :",part1(final_input))
print("part2 (sample input) :",part2(sample))
print("part2 (final input)  :",part2(final_input))