import time

import allure
import pytest
from src.config.readconfig import data
from src.config.config import GlobalVar

from src.eufyhome.method.Home_Page import HomePage
from src.eufyhome.method.AddDevice_Page import AddDevicePage
from src.eufyhome.method.ShareSetting_Page import ShareSettingPage
from src.eufyhome.method.Base_Page import BasePage
from src.eufyhome.method.DeviceHelp_Page import DeviceHelpPage

from src.eufyhome.method.app.HelpFAQ_Page import HelpFAQPage
from src.eufyhome.method.app.User_Page import UserPage
from src.eufyhome.method.app.TimeZone_page import TimeZonePage
from src.eufyhome.method.app.System_Page import SystemPage
from src.eufyhome.method.app.Start_page import StartPage
from src.eufyhome.method.app.News_Page import NewsPage
from src.eufyhome.method.app.ChangePW_Page import ChangePWPage
from src.eufyhome.method.app.AllShare_Page import AllSharePage

from src.eufyhome.method.robotic.RoboticCleanModel_Page import RoboticCleanModelPage
from src.eufyhome.method.robotic.RoboticFind_Page import RoboticFindPage
from src.eufyhome.method.robotic.RoboticHome_Page import RoboticHomePage
from src.eufyhome.method.robotic.RoboticSetting_Page import RoboticSettingPage
from src.eufyhome.method.robotic.RoboticSuction_Page import RoboticSuctionPage
from src.eufyhome.method.robotic.RoboticVoice_Page import RoboticVoicePage
from src.eufyhome.method.robotic.RoboticSchedule_Page import RoboticSchedulePage
from src.eufyhome.method.robotic.RoboticUpdate_Page import RoboticUpdatePage
from src.eufyhome.method.robotic.RoboticMaintence_Page import RoboticMaintencePage
from src.eufyhome.method.robotic.RoboticCleanSetting_Page import RoboticCleanSettingPage
from src.eufyhome.method.robotic.RoboticUnit_Page import RoboticUnitPage
from src.eufyhome.method.robotic.RoboticZoneClean_Page import RoboticZoneCleanPage
from src.eufyhome.method.robotic.RoboticManual_Page import RoboticManualPage
from src.eufyhome.method.robotic.RoboticCleanHistory_Page import RoboticCleanHistoryPage

global base_page, start_page, user_page, time_zone_page, system_page, news_page, change_pw_page, home_page, \
            all_share_page, robotic_find_page, robotic_home_page, robotic_setting_page, robotic_suction_page,\
            robotic_voice_page, help_faq_page, robotic_clean_model_page, share_setting_page, add_device_page, \
            device_help_page, robotic_schedule_page, robotic_update_page, robotic_maintence_page, robotic_cleansetting_Page, \
            robotic_unit_page, robotic_zone_clean_page, robotic_manual_page, robotic_clean_history_page

# @pytest.mark.flaky(reruns=0)  # 失败重跑
@pytest.mark.repeat(0)  # 重复执行次数
@pytest.mark.usefixtures('driver_setup')  # 引用conftest.py中的driver_setup方法，创建会话
@pytest.mark.usefixtures('appium_setup')  # 引用conftest.py中的appium_setup方法，启动appium服务
class TestLaserRoboVac(object):
    @pytest.fixture(scope='function')
    def init_setup(self):
        """
        使用 @pytest.fixture(scope='function') 装饰器的方法可以看做是setup方法
        scope指定级别，取值可以是"function"(default),"class","module","package" or "session"
        :return:
        """
        global base_page, start_page, user_page, time_zone_page, system_page, news_page, change_pw_page, home_page, \
            all_share_page, robotic_find_page, robotic_home_page, robotic_setting_page, robotic_suction_page,\
            robotic_voice_page, help_faq_page, robotic_clean_model_page, share_setting_page, add_device_page, \
            device_help_page, robotic_schedule_page, robotic_update_page, robotic_maintence_page, robotic_cleansetting_Page, \
            robotic_unit_page, robotic_zone_clean_page, robotic_manual_page, robotic_clean_history_page

        GlobalVar.set_test_flag('f')

        base_page = BasePage(self.driver)
        start_page = StartPage(self.driver)
        home_page = HomePage(self.driver)
        user_page = UserPage(self.driver)
        time_zone_page = TimeZonePage(self.driver)
        system_page = SystemPage(self.driver)
        news_page = NewsPage(self.driver)
        change_pw_page = ChangePWPage(self.driver)
        all_share_page = AllSharePage(self.driver)
        share_setting_page = ShareSettingPage(self.driver)
        add_device_page = AddDevicePage(self.driver)
        device_help_page = DeviceHelpPage(self.driver)
        help_faq_page = HelpFAQPage(self.driver)

        robotic_find_page = RoboticFindPage(self.driver)
        robotic_home_page = RoboticHomePage(self.driver)
        robotic_setting_page = RoboticSettingPage(self.driver)
        robotic_suction_page = RoboticSuctionPage(self.driver)
        robotic_voice_page = RoboticVoicePage(self.driver)
        robotic_clean_model_page = RoboticCleanModelPage(self.driver)
        robotic_schedule_page = RoboticSchedulePage(self.driver)
        robotic_update_page = RoboticUpdatePage(self.driver)
        robotic_maintence_page = RoboticMaintencePage(self.driver)
        robotic_cleansetting_Page = RoboticCleanSettingPage(self.driver)
        robotic_unit_page = RoboticUnitPage(self.driver)
        robotic_zone_clean_page = RoboticZoneCleanPage(self.driver)
        robotic_manual_page = RoboticManualPage(self.driver)
        robotic_clean_history_page = RoboticCleanHistoryPage(self.driver)

        # 检查ios升级弹窗
        try:
            start_page.ignore_ios_update()
        except Exception as e:
            print('升级弹窗处理失败：\n' + e)

    @staticmethod
    def change_account(account):
        """
        切换登陆账号
        :return:
        """
        home_page.into_system()
        system_page.view_account()
        user_page.logout()
        time.sleep(2)
        start_page.into_login()
        start_page.select_country('login', data.get_country(account))
        start_page.login_phone(data.get_account(account),
                               data.get_account('pw'))
        start_page.loading(10)

    @pytest.fixture(scope='function')
    def is_login(self, init_setup):
        """
        检查并返回登陆状态
        :return:
        """
        return home_page.is_welcome()

    @pytest.fixture(scope='function')
    def not_login(self, init_setup):
        """
        不登陆，如果登陆则退出登录
        :return:
        """
        if home_page.is_welcome():
            home_page.into_system()
            system_page.view_account()
            user_page.logout()

    @pytest.fixture(scope='function')
    def check_account(self, request, init_setup):
        """
        校验当前登陆账号是否正确，不正确则自动切换
        调用的函数需要传参：
        @pytest.mark.parametrize('switch_account', ['robotic'], indirect=True)
        :param init_setup:
        :param request:
        :return:
        """
        account = request.param
        if home_page.is_welcome() is False:
            start_page.into_login()
            if account is not None:
                start_page.select_country('login', data.get_country(account))
                start_page.login_phone(data.get_account(account),
                                       data.get_account('pw'))
            else:
                raise Exception('登陆账号为空')
        else:
            if data.get_username(account) in home_page.read_username():
                return
            if account is not None:
                TestLaserRoboVac.change_account(account)
            else:
                raise Exception('登陆账号为空')

    @pytest.fixture(scope='function')
    def logout(self):
        """
        后置操作，退出登录
        首页》侧边栏》用户中心
        :return:
        """
        yield 1
        base_page.kill_app()
        base_page.open_app()
        if home_page.is_welcome():
            home_page.into_system()
            system_page.view_account()
            user_page.logout()

    @pytest.fixture(scope='function')
    def delete_share_news(self):
        """
        删除被分享人消息列表的通知
        :return:
        """
        yield 1
        if GlobalVar.get_test_flag():
            base_page.kill_app()
            base_page.open_app()
            home_page.into_system()
            system_page.into_news()
            news_page.clear_all()
            news_page.yes
            time.sleep(2.5)

    @staticmethod
    def laser_ready():
        robotic_home_page.skip_robotic_guide()
        if robotic_home_page.is_offline:
            robotic_home_page.ok
            if robotic_home_page.robovac_is_offline() is False:
                assert False, 'laser_robotic 设备处于离线状态'

        robotic_home_page.ingore_update_languge()

    # ********************激光扫地机用例************************** #

    @pytest.mark.robovac
    @pytest.mark.laserrobotic
    @pytest.mark.run(order=200)
    @pytest.mark.parametrize('check_account', ['laser_robotic'], indirect=True)
    def laser_robotic_check_update_icon(self, check_account):
        """
        设备升级提示图标检查:
        1. app首页点击进入设备主页
        【checkpoint】首页设备列表是否显示升级图标
        :param check_account:
        :return:
        """
        home_page.swipe_page('down')
        assert home_page.have_update_icon(data.get_device('laser_robotic')), 'laser_robotic 未显示升级图标'

        home_page.click_update_icon(data.get_device('laser_robotic'))
        assert home_page.text_display('Firmware Update'), 'laser_robotic OTA升级快捷入口进入失败'

    @pytest.fixture(scope='function')
    def stop_laser_robovac(self):
        yield 1
        if home_page.is_welcome():
            home_page.into_device_home_page('laser_robotic')
        if robotic_home_page.read_robovac_status() == data.get_robotic_status('cleanning'):
            robotic_home_page.t2190_play()

    @pytest.mark.robovac
    @pytest.mark.laserrobotic
    @pytest.mark.run(order=202)
    @pytest.mark.parametrize('check_account', ['laser_robotic'], indirect=True)
    @pytest.mark.flaky(reruns=2, reruns_delay=40)
    def test_laser_robotic_play(self, check_account, stop_laser_robovac):
        """
        激光扫地机清扫启动/暂停:
        1. 点击激光扫地机进入扫地机主页
        2. 点击清扫按钮，检查扫地机状态
        【checkpoint】启动扫地机后设备状态变更为：Cleaning  （添加按钮图片的判断）
        3. 再次点击清扫按钮，检查扫地机状态
        【checkpoint】停止清扫后扫地机状态变为：standard  （添加按钮图片的判断）
        :param check_account:
        :return:
        """
        home_page.into_device_home_page(data.get_device('laser_robotic'))

        TestLaserRoboVac.laser_ready()

        # robotic_home_page.skip_robotic_guide()
        # if robotic_home_page.is_offline:
        #     robotic_home_page.ok
        #     if robotic_home_page.robovac_is_offline() is False:
        #         assert False, 'laser_robotic 设备处于离线状态'
        #
        # robotic_home_page.ingore_update_languge()

        robotic_home_page.t2190_play()
        time.sleep(8)
        robotic_home_page.swipe_page('down')
        assert data.get_robotic_status('cleaning') == robotic_home_page.read_robovac_status(), 'laser_robotic 扫地机启动清扫失败'
        assert 'Pause' in robotic_home_page.read_clean_btn_status(), 'laser_robotic 扫地机清扫按钮启动状态未切换'
        robotic_home_page.back_home()
        assert home_page.read_device_status(data.get_device('laser_robotic')) == 'Cleaning', 'laser_robotic 扫地机启动清扫后列表开关状态显示错误'

        home_page.click_device_btn(data.get_device('laser_robotic'))
        time.sleep(8)
        robotic_home_page.swipe_page('down')
        assert home_page.read_device_status(
            data.get_device('laser_robotic')) == 'Standby', 'laser_robotic 扫地机停止清扫后列表开关状态显示错误'
        home_page.into_device_home_page(data.get_device('laser_robotic'))
        assert robotic_home_page.read_robovac_status() == data.get_robotic_status('standard'), 'laser_robotic 扫地机暂停清扫失败'
        assert 'Clean' in robotic_home_page.read_clean_btn_status(), 'laser_robotic 扫地机清扫按钮启动状态未切换'

    @pytest.mark.robovac
    @pytest.mark.laserrobotic
    @pytest.mark.run(order=203)
    @pytest.mark.parametrize('check_account', ['laser_robotic'], indirect=True)
    @pytest.mark.flaky(reruns=2, reruns_delay=40)
    def test_laser_robotic_change_quite_suction(self, check_account):
        """
        激光扫地机quiet吸力模式修改:
        1. 点击激光扫地机进入扫地机主页，点击suctions进入吸力设置
        2. 点击选择 quiet ，在点击 boostiq开关检查开关状态
        【checkpoint】quiet吸力等级选择成功，检查v的位置
        3.在点击 boostiq开关检查开关状态
        【checkpoint】standard模式开关boostiq正常
        :param check_account:
        :return:
        """
        home_page.into_device_home_page(data.get_device('laser_robotic'))

        TestLaserRoboVac.laser_ready()

        robotic_home_page.t2190_suction()
        robotic_suction_page.t2190_quiet()
        assert robotic_suction_page.t2190_is_quiet(), 'laser_robotic quiet吸力模式切换失败'

        flag1 = robotic_suction_page.read_t2190_boostiq_status()
        robotic_suction_page.t2190_click_boostiq()
        time.sleep(5)
        flag2 = robotic_suction_page.read_t2190_boostiq_status()
        robotic_suction_page.t2190_click_boostiq()
        time.sleep(5)
        flag3 = robotic_suction_page.read_t2190_boostiq_status()

        assert flag1 != flag2 and flag1 == flag3, 'laser_robotic quiet档位boostiq开启/关闭失败'

    @pytest.mark.robovac
    @pytest.mark.laserrobotic
    @pytest.mark.run(order=204)
    @pytest.mark.parametrize('check_account', ['laser_robotic'], indirect=True)
    @pytest.mark.flaky(reruns=2, reruns_delay=40)
    def test_laser_robotic_change_standard_suction(self, check_account):
        """
        激光扫地机standard吸力模式修改:
        1. 点击激光扫地机进入扫地机主页，点击suctions进入吸力设置
        2. 点击选择 standard
        【checkpoint】standard吸力等级选择成功
        3.在点击 boostiq开关检查开关状态
        【checkpoint】standard模式开关boostiq正常
        :param check_account:
        :return:
        """
        home_page.into_device_home_page(data.get_device('laser_robotic'))

        TestLaserRoboVac.laser_ready()

        robotic_home_page.t2190_suction()
        robotic_suction_page.t2190_standard()
        assert robotic_suction_page.t2190_is_standard(), 'laser_robotic standard吸力模式切换失败'

        flag1 = robotic_suction_page.read_t2190_boostiq_status()
        robotic_suction_page.t2190_click_boostiq()
        time.sleep(5)
        flag2 = robotic_suction_page.read_t2190_boostiq_status()
        robotic_suction_page.t2190_click_boostiq()
        time.sleep(5)
        flag3 = robotic_suction_page.read_t2190_boostiq_status()

        assert flag1 != flag2 and flag1 == flag3, 'laser_robotic standard档位boostiq开启/关闭失败'

    @pytest.mark.robovac
    @pytest.mark.laserrobotic
    @pytest.mark.run(order=205)
    @pytest.mark.parametrize('check_account', ['laser_robotic'], indirect=True)
    @pytest.mark.flaky(reruns=2, reruns_delay=40)
    def test_laser_robotic_change_turbo_suction(self, check_account):
        """
        激光扫地机turbo吸力模式修改:
        1. 点击激光扫地机进入扫地机主页，点击suctions进入吸力设置
        2.点击选择 turbo
        【checkpoint】turbo吸力等级选择成功
        3.在点击 boostiq开关检查开关状态
        【checkpoint】turbo模式开关boostiq正常
        :param self:
        :param check_account:
        :return:
        """
        home_page.into_device_home_page(data.get_device('laser_robotic'))

        TestLaserRoboVac.laser_ready()

        robotic_home_page.t2190_suction()
        robotic_suction_page.t2190_turbo()
        assert robotic_suction_page.t2190_is_turbo(), 'laser_robotic turbo吸力模式切换失败'

        flag1 = robotic_suction_page.read_t2190_boostiq_status()
        robotic_suction_page.t2190_click_boostiq()
        time.sleep(5)
        flag2 = robotic_suction_page.read_t2190_boostiq_status()
        robotic_suction_page.t2190_click_boostiq()
        time.sleep(5)
        flag3 = robotic_suction_page.read_t2190_boostiq_status()

        assert flag1 != flag2 and flag1 == flag3, 'laser_robotic turbo档位boostiq开启/关闭失败'

    @pytest.mark.robovac
    @pytest.mark.laserrobotic
    @pytest.mark.run(order=206)
    @pytest.mark.parametrize('check_account', ['laser_robotic'], indirect=True)
    @pytest.mark.flaky(reruns=2, reruns_delay=40)
    def test_laser_robotic_change_max_suction(self, check_account):
        """
        激光扫地机max吸力模式修改:
        1. 点击激光扫地机进入扫地机主页，点击suctions进入吸力设置
        2.点击选择 max
        【checkpoint】max吸力等级选择成功
        3.在点击 boostiq开关检查开关状态
        【checkpoint】max模式不能开关boostiq
        :param check_account:
        :return:
        """
        home_page.into_device_home_page(data.get_device('laser_robotic'))

        TestLaserRoboVac.laser_ready()

        robotic_home_page.t2190_suction()
        robotic_suction_page.t2190_max()
        assert robotic_suction_page.t2190_is_max(), 'laser_robotic max吸力模式切换失败'

        flag1 = robotic_suction_page.read_t2190_boostiq_status()
        robotic_suction_page.t2190_click_boostiq()
        time.sleep(5)
        flag2 = robotic_suction_page.read_t2190_boostiq_status()

        assert flag1 == flag2, 'laser_robotic max 档位boostiq开启/关闭会生效'

    @pytest.mark.robovac
    @pytest.mark.laserrobotic
    @pytest.mark.run(order=207)
    @pytest.mark.parametrize('check_account', ['laser_robotic'], indirect=True)
    @pytest.mark.flaky(reruns=1, reruns_delay=60)
    def test_laser_robotic_change_util(self, check_account):
        """
        激光扫地机修改面积单位和面积单位换算：
        1. 点击激光扫地机进入扫地机主页，记录当前面积，单位 为area1， unit1，点击more进入设置
        2. 根据 unit1 切换面积单位
        【checkpoint】修改后设备主页显示正常
        3. 读取新的面积 area2
        【checkpoint】修改单位后面积根据公式计算后求差，误差0. 3以内
        :param check_account:
        :return:
        """
        home_page.into_device_home_page(data.get_device('laser_robotic'))

        TestLaserRoboVac.laser_ready()

        area, unit = robotic_home_page.read_clean_area()
        robotic_home_page.into_setting()
        robotic_setting_page.swipe_page('up')
        robotic_setting_page.into_unit()

        if unit == data.get_area_util('m2'):
            robotic_unit_page.click_ft2()
            time.sleep(5)
            assert robotic_unit_page.check_ft2(), 'laser_robotic 切换清扫面积单位ft2失败'
        else:
            robotic_unit_page.click_m2()
            time.sleep(5)
            assert robotic_unit_page.check_m2(), 'laser_robotic 切换清扫面积单位m2失败'

        robotic_unit_page.back_setting()
        robotic_setting_page.back_robovac()
        area0, unit0 = robotic_home_page.read_clean_area()

        if unit == data.get_area_util('m2'):
            assert unit0 == data.get_area_util('ft2'), 'laser_robotic 切换面积单位为ft2后主页显示错误'
            assert abs(0.093 * area0 - area) < 0.5, 'laser_robotic 切换面积单位m2为ft2后主页的面积转换计算错误'
        else:
            assert unit0 == data.get_area_util('m2'), 'laser_robotic 切换面积单位为m2后主页显示错误'
            assert abs(area0 - area * 0.093) < 0.5, 'laser_robotic 切换面积单位ft2为m2后主页的面积转换计算错误'

    @pytest.fixture(scope='function')
    def laser_robotic_charge(self):
        """
        回充的后置操作：
        恢复为standard状态
        :return:
        """
        yield 1
        if GlobalVar.get_test_flag():  # 设备离线时不执行
            status = robotic_home_page.read_robovac_status()
            if status == data.get_robotic_status('cleaning') or status == data.get_robotic_status('backing'):
                robotic_home_page.t2190_play()
                if robotic_home_page.text_display('Are you sure you want to stop cleaning and send RoboVac home?'):
                    robotic_home_page.yes
                if data.get_robotic_status('cleaning') == robotic_home_page.read_robovac_status():
                    robotic_home_page.t2190_play()

    @pytest.mark.robovac
    @pytest.mark.laserrobotic
    @pytest.mark.run(order=208)
    @pytest.mark.parametrize('check_account', ['laser_robotic'], indirect=True)
    @pytest.mark.flaky(reruns=1, reruns_delay=60)
    def test_laser_robotic_standard_charge(self, check_account, laser_robotic_charge):
        """
        激光扫地机不再充电座回充:
        1. 点击随机扫地机进入扫地机主页，使扫地机状态为standard
        2. 点击 charge 按钮
        【checkpoint】扫地机回充显示toast：Heading Home
        【checkpoint】扫地机状态显示：Heading Home
        :param check_account:
        :return:
        """
        home_page.into_device_home_page(data.get_device('laser_robotic'))

        TestLaserRoboVac.laser_ready()

        status = robotic_home_page.read_robovac_status()

        if status == data.get_robotic_status('charging'):
            robotic_home_page.t2190_play()
            time.sleep(5)
            robotic_home_page.t2190_play()
        elif status == data.get_robotic_status('cleaning'):
            robotic_home_page.t2190_play()

        GlobalVar.set_test_flag('t')
        time.sleep(5)
        robotic_home_page.t2190_charge()
        # toast = robotic_home_page.is_toast_exist('RoboVac is heading home', True, True)
        status = robotic_home_page.read_robovac_status() in [data.get_robotic_status('backing'), data.get_robotic_status('charging')]
        assert status, 'laser_robotic 在standby状态下回充中状态显示:' + str(status)
        if status == data.get_robotic_status('charging'):
            return

        times = 1
        while times < 10:
            times = times + 1
            _ac = robotic_home_page.read_robovac_status()
            if _ac in [data.get_robotic_status('charging'), data.get_robotic_status('standard')]:
                break
            else:
                time.sleep(10)

    @pytest.mark.robovac
    @pytest.mark.laserrobotic
    @pytest.mark.run(order=209)
    @pytest.mark.parametrize('check_account', ['laser_robotic'], indirect=True)
    @pytest.mark.flaky(reruns=1, reruns_delay=60)
    def test_laser_robotic_iscleaning_charge(self, check_account, laser_robotic_charge):
        """
        激光扫地机清扫过程中点击回充按钮:
        1. 点击随机扫地机进入扫地机主页，使扫地机状态为cleaning
        2. 点击 charge 按钮
        【checkpoint】提示是否结束清扫开始回充弹窗
        3.点击 ok按钮
        【checkpoint】扫地机回充显示toast：Heading Home
        【checkpoint】等待5min，每分钟检查一次扫地机状态显示：Heading Home
        :param random_robotic_charge:
        :return:
        """
        home_page.into_device_home_page(data.get_device('laser_robotic'))

        TestLaserRoboVac.laser_ready()

        status = robotic_home_page.read_robovac_status()
        GlobalVar.set_test_flag('t')

        if status == data.get_robotic_status('standard') or status == data.get_robotic_status('charging'):
            robotic_home_page.t2190_play()
            time.sleep(5)

        robotic_home_page.t2190_charge()
        # toast = robotic_home_page.is_toast_exist('RoboVac is heading home', True, True)
        status = robotic_home_page.read_robovac_status() in [data.get_robotic_status('backing'), data.get_robotic_status('charging')]
        assert status, 'laser_robotic 在cleaning状态回充中状态显示:' + str(status)

        times = 1
        while times < 10:
            times = times + 1
            _ac = robotic_home_page.read_robovac_status()
            if _ac in [data.get_robotic_status('charging'), data.get_robotic_status('standard')]:
                break
            else:
                time.sleep(10)

    @pytest.mark.robovac
    @pytest.mark.laserrobotic
    @pytest.mark.run(order=210)
    @pytest.mark.parametrize('check_account', ['laser_robotic'], indirect=True)
    @pytest.mark.flaky(reruns=1, reruns_delay=60)
    def laser_robotic_ischarging_charge(self, check_account, laser_robotic_charge):
        """
        激光扫地机充电中点击清扫按钮:
        1. 点击激光扫地机进入扫地机主页，使扫地机状态为charging
        2. 点击 charge 按钮
        【checkpoint】toast提示充电中
        :param check_account:
        :param random_robotic_charge:
        :return:
        """
        home_page.into_device_home_page(data.get_device('laser_robotic'))

        TestLaserRoboVac.laser_ready()

        status = robotic_home_page.read_robovac_status()
        GlobalVar.set_test_flag('t')

        if status == data.get_robotic_status('standard') or status == data.get_robotic_status('cleaning'):
            robotic_home_page.t2190_charge()
            times = 1
            flag = False
            while times < 20:
                times = times + 1
                _ac = robotic_home_page.read_robovac_status()
                if _ac in [data.get_robotic_status('charging'), data.get_robotic_status('standard')]:
                    flag = True
                    break
                else:
                    time.sleep(10)
            assert flag, 'laser_robotic 前置条件失败，用例不执行'

        robotic_home_page.t2190_charge()

        assert robotic_home_page.is_toast_exist('Charging', True, True), 'laser_robotic 在charging状态点击回充提示语错误'

    @pytest.mark.robovac
    @pytest.mark.skip(reason='t2190扫地机在充电状态能够下达寻找指令')
    @pytest.mark.laserrobotic
    @pytest.mark.run(order=211)
    @pytest.mark.parametrize('check_account', ['laser_robotic'], indirect=True)
    @pytest.mark.flaky(reruns=1, reruns_delay=60)
    def laser_robotic_ischarging_find(self, check_account, laser_robotic_charging):
        """
        充电状态点击find按钮:
        1. 点击激光扫地机进入扫地机主页，点击 find 按钮
        2.点击 start 按钮
        【checkpoint】toast提示：Charging
        :param check_account:
        :return:
        """
        home_page.into_device_home_page(data.get_device('laser_robotic'))

        TestLaserRoboVac.laser_ready()

        status = robotic_home_page.read_status()
        if status in [data.get_robotic_status('standard'), data.get_robotic_status('cleaning')]:
            robotic_home_page.t2190_charge()
            times = 1
            flag = False
            while times < 20:
                times = times + 1
                _ac = robotic_home_page.read_status()
                if data.get_robotic_status('charging') in _ac:
                    flag = True
                    break
                else:
                    time.sleep(10)
            assert flag, 'laser_robotic 前置条件失败，用例不执行'

        robotic_home_page.into_setting()
        robotic_setting_page.into_find()
        robotic_find_page.click_find('laser')

        assert robotic_find_page.check_find_img('laser', 't2190_find_start'), 'laser_robotic 在charging状态点击find不会启动寻找'

    @pytest.mark.robovac
    @pytest.mark.laserrobotic
    @pytest.mark.run(order=212)
    @pytest.mark.parametrize('check_account', ['laser_robotic'], indirect=True)
    @pytest.mark.flaky(reruns=1, reruns_delay=60)
    def test_laser_robotic_manual_find(self, check_account):
        """
        激光扫地机find手动开始/停止测试:
        1. 点击激光扫地机进入扫地机主页，点击 find 按钮
        2. 点击 start 按钮
        【checkpoint】点击后按钮文案变为stoped
        3. 点击stop停止蜂鸣
        【checkpoint】点击stoped后按钮变为start
        :param check_account:
        :return:
        """
        home_page.into_device_home_page(data.get_device('laser_robotic'))

        TestLaserRoboVac.laser_ready()

        status = robotic_home_page.read_robovac_status()
        if status == data.get_robotic_status('charging'):
            robotic_home_page.t2190_play()
            time.sleep(5)
            robotic_home_page.t2190_play()

        robotic_home_page.into_setting()
        robotic_setting_page.into_find()
        robotic_find_page.click_find('laser')
        time.sleep(3)
        assert robotic_find_page.check_find_img('laser', 't2190_find_stop'), 'laser_robotic 手动启动find me失败'
        robotic_find_page.click_find('laser')
        time.sleep(3)
        assert robotic_find_page.check_find_img('laser', 't2190_find_start'), 'laser_robotic 手动停止find me失败'

    @pytest.mark.robovac
    @pytest.mark.laserrobotic
    @pytest.mark.run(order=213)
    @pytest.mark.parametrize('check_account', ['laser_robotic'], indirect=True)
    @pytest.mark.flaky(reruns=1, reruns_delay=60)
    def test_laser_robotic_find_timeout(self, check_account):
        """
        激光扫地机find蜂鸣时间测试：
        1. 点击激光扫地机进入扫地机主页，点击 find 按钮
        2.点击start设备开始蜂鸣
        【checkpoint】点击find启动后按钮变为stoped
        3.等待65s
        【checkpoint】扫地机find蜂鸣i1min后自动结束，按钮变为start
        :param check_account:
        :return:
        """
        home_page.into_device_home_page(data.get_device('laser_robotic'))

        TestLaserRoboVac.laser_ready()

        status = robotic_home_page.read_robovac_status()
        if status == data.get_robotic_status('charging'):
            robotic_home_page.t2190_play()
            time.sleep(5)
            robotic_home_page.t2190_play()

        robotic_home_page.into_setting()
        robotic_setting_page.into_find()
        robotic_find_page.click_find('laser')

        assert robotic_find_page.check_find_img('laser', 't2190_find_stop'), 'laser_robotic 未正常启动find功能'
        robotic_find_page.long_wait(70)
        assert robotic_find_page.check_find_img('laser', 't2190_find_start'), 'laser_robotic 设备find me蜂鸣未在1分钟内结束'

    @pytest.mark.robovac
    @pytest.mark.laserrobotic
    @pytest.mark.run(order=214)
    @pytest.mark.parametrize('check_account', ['laser_robotic'], indirect=True)
    @pytest.mark.flaky(reruns=1, reruns_delay=60)
    def test_laser_robotic_share_error_email(self, check_account):
        """
        激光扫地机分享给错误格式账号:
        1. 点击激光扫地机进入扫地机主页，点击 more进入设置界面，点击share setting进入分享列表
        2. 点击 add 按钮进入添加界面，输入分享账号：a@a并提交
        【checkpoint】分享失败，toast提示：Please enter a vailed email adress
        :return:
        """
        home_page.into_device_home_page(data.get_device('laser_robotic'))

        TestLaserRoboVac.laser_ready()

        robotic_home_page.into_setting()
        robotic_setting_page.into_share()
        share_setting_page.add_share()
        share_setting_page.commit_share('1354253')

        if share_setting_page.platform == 'ios':
            flag = share_setting_page.text_display('Add Member')
        else:
            flag = share_setting_page.share_result() is False
        assert flag, 'laser_robotic 分享错误邮箱的结果异常'

    @pytest.mark.robovac
    @pytest.mark.laserrobotic
    @pytest.mark.run(order=215)
    @pytest.mark.parametrize('check_account', ['laser_robotic'], indirect=True)
    @pytest.mark.flaky(reruns=1, reruns_delay=60)
    def test_laser_robotic_share_nosign_email(self, check_account):
        """
        激光扫地机分享给未注册的账号:
        1. 点击激光扫地机进入扫地机主页，点击 more进入设置界面，点击share setting进入分享列表
        2. 点击 add 按钮进入添加界面，输入分享账号：a@a. com并提交
        【checkpoint】分享失败，弹窗提示：Failed to share
        :return:
        """
        home_page.into_device_home_page(data.get_device('laser_robotic'))

        TestLaserRoboVac.laser_ready()

        robotic_home_page.into_setting()
        robotic_setting_page.into_share()
        share_setting_page.add_share()
        share_setting_page.commit_share('19900002222')
        assert share_setting_page.share_result() is False, 'laser_robotic 分享失败的提示错误'

    @pytest.fixture(scope='function')
    def delete_refuse_share_account(self):
        """
        先删除refuseshare账号分享列表
        :return:
        """
        home_page.into_system()
        system_page.into_sharing()
        all_share_page.into_device(data.get_device('laser_robotic'))
        share_setting_page.delete_share()
        all_share_page.kill
        time.sleep(2)
        all_share_page.open

    @pytest.mark.robovac
    @pytest.mark.laserrobotic
    @pytest.mark.run(order=216)
    @pytest.mark.parametrize('check_account', ['laser_robotic'], indirect=True)
    @pytest.mark.flaky(reruns=1, reruns_delay=60)
    def test_laser_robotic_share_email(self, check_account, delete_refuse_share_account):
        """
        激光扫地机分享给已注册的账号：
        1. 点击激光扫地机进入扫地机主页，点击 more进入设置界面，点击share setting进入分享列表
        2. 点击 add 按钮进入添加界面，输入分享账号：Yi@aa. com并提交
        【checkpoint】 分享邀请发送成功，弹窗提示：Successed to share
        【checkpoint】页面返回到分享列表并显示分享人，状态为：待确认
        :param check_account:
        :return:
        """
        home_page.into_device_home_page(data.get_device('laser_robotic'))

        TestLaserRoboVac.laser_ready()

        robotic_home_page.into_setting()
        robotic_setting_page.into_share()
        share_setting_page.add_share()
        share_setting_page.commit_share(data.get_account('phoneshare'))

        assert share_setting_page.share_result(), 'laser_robotic 正确账号分享失败'
        share_setting_page.ok
        share_setting_page.loading()
        share_setting_page.swipe_page('down')
        status = share_setting_page.read_share_status(data.get_username('phoneshare'))
        assert status == 'Awaiting Confirmation' or status == 'Pending Confirmation', 'laser_robotic 分享列表被分享者状态显示错误'

    @pytest.mark.robovac
    @pytest.mark.laserrobotic
    @pytest.mark.run(order=217)
    @pytest.mark.parametrize('check_account', ['laser_robotic'], indirect=True)
    @pytest.mark.flaky(reruns=1, reruns_delay=60)
    def test_laser_robotic_agree_share(self, check_account, delete_share_news):
        """
        激光扫地机被分享者接受分享:
        1. 登陆账号Yi@aa. com/12345678
        【checkpoint】检查是否显示了分享设备
        2. 点击进入侧边栏界面
        【checkpoint】android消息通知显示分享通知红点标识
        3. 点击news进入消息界面
        【checkpoint】显示分享邀请消息记录
        4. 点击最新一条分享邀请通知，点击ok按钮
        【checkpoint】确认分享设备名称是否正确
        【checkpoint】进入消息通知显示拒绝/确认两个按钮,点击ok按钮弹窗提示分享成功
        :param check_account:
        :return:
        """
        home_page.into_device_home_page(data.get_device('laser_robotic'))

        TestLaserRoboVac.laser_ready()

        robotic_home_page.into_setting()
        robotic_setting_page.into_share()
        status = share_setting_page.read_share_status(data.get_username('phoneshare'))
        if status not in ['Awaiting Confirmation', 'Pending Confirmation']:
            share_setting_page.add_share()
            share_setting_page.commit_share(data.get_account('phoneshare'))

            assert share_setting_page.share_result(), 'laser_robotic 正确账号分享失败,无法执行用例:[id=35]'
            share_setting_page.ok
            share_setting_page.loading()
        share_setting_page.back_setting()
        robotic_setting_page.back_robovac()
        robotic_home_page.back_home()

        TestLaserRoboVac.change_account('phoneshare')

        home_page.into_system()

        system_page.into_sharing()
        assert all_share_page.text_display(data.get_device('laser_robotic')), '被分享列表未显示分享设备信息'
        GlobalVar.set_test_flag('t')  # 到这里后需要执行 tear_down
        all_share_page.into_device(data.get_device('laser_robotic'))
        all_share_page.yes
        all_share_page.loading()

        assert news_page.text_display('Request Accepted. You may now use this device.'), 'laser_robotic 被分享者确认接受分享失败'
        news_page.ok
        assert news_page.text_display(
            'shared a ' + data.get_device('laser_robotic')), 'laser_robotic 被分享者显示的分享设备名称错误'

        news_page.back_system()
        news_page.back_system()
        system_page.back_home()
        home_page.swipe_page('down')
        assert home_page.find_device(data.get_device('laser_robotic')), '被分享者未显示分享的扫地机设备'

    @pytest.fixture(scope='function')
    def t2190_close_yellow_tip(self):
        """
        关闭小黄条提示
        :return:
        """
        yield 1
        if GlobalVar.get_test_flag():
            robotic_schedule_page.close_yellow_tip()

    @pytest.mark.robovac
    @pytest.mark.laserrobotic
    @pytest.mark.run(order=218)
    @pytest.mark.parametrize('check_account', ['phoneshare'], indirect=True)
    @pytest.mark.flaky(reruns=1, reruns_delay=60)
    def laser_robotic_yellow_tip(self, t2190_close_yellow_tip, check_account):
        """
        随机扫地机被分享者修改设备名及小黄条显示:
        1. app首页点击进入设备主页，修改一个定时任务
        2.切换账号 Yi@aaa.com，查看随机扫地机设备
        【checkpoint】显示设备名称修改小黄条
        :return:
        """
        if home_page.find_device(data.get_device('laser_robotic')) is False:
            assert False, '为查找到分享设备，无法执行用:[test_laser_robotic_yellow_tip]'

        home_page.into_device_home_page(data.get_device('laser_robotic'))
        robotic_home_page.skip_robotic_guide()

        if robotic_home_page.is_offline:
            assert False, 'laser_robotic 设备处于离线状态'

        robotic_home_page.ingore_update_languge()
        robotic_home_page.t2190_schedule()
        if robotic_schedule_page.t2190_count_schedule() < 1:
            robotic_schedule_page.t2190_creat_new_schedule()
        robotic_schedule_page.t2190_click_schedule_btn()
        robotic_schedule_page.back_robotic()
        robotic_home_page.back_home()

        TestLaserRoboVac.change_account('laser_robotic')

        home_page.into_device_home_page(data.get_device('laser_robotic'))
        if robotic_home_page.is_offline:
            robotic_home_page.ok
            if robotic_home_page.robovac_is_offline() is False:
                assert False, 'laser_robotic 设备处于离线状态'

        GlobalVar.set_test_flag('t')

        robotic_home_page.ingore_update_languge()
        robotic_home_page.t2190_schedule()
        assert robotic_schedule_page.text_display('modified the schedule'), 'laser_robotic 被分享人修改了定时任务未显示小黄条提示'

    @pytest.mark.robovac
    @pytest.mark.laserrobotic
    @pytest.mark.run(order=219)
    @pytest.mark.parametrize('check_account', ['phoneshare'], indirect=True)
    def test_laser_robotic_delete_share(self, check_account):
        """
        激光扫地机被分享者移除分享设备:
        1. app首页点击进入设备主页，点击更多，点击删除设备
        【checkpoint】弹窗提示确认移除
        2.点击 ok 按钮
        【checkpoint】分享者列表不显示被分享人信息
        3.切换账号Yi@aaa。com，查看设备分享列表
        【checkpoint】分享者列表不显示被分享人信息
        :return:
        """
        time.sleep(5)
        assert home_page.find_device(data.get_device('laser_robotic')), '未查找到分享设备，无法执行用:[test_laser_robotic_delete_share]'

        home_page.into_device_home_page(data.get_device('laser_robotic'))

        TestLaserRoboVac.laser_ready()

        robotic_home_page.into_setting()
        time.sleep(2)
        robotic_setting_page.swipe_page('up')
        robotic_setting_page.click_remove()
        assert robotic_setting_page.text_display('Are you sure you want to remove this device?'), '未显示移除确认弹窗'
        robotic_setting_page.commit_remove()
        home_page.swipe_page('down')
        assert home_page.find_device(data.get_device('laser_robotic')) is False, 'laser_robotic 被分享着移除后设备未删除'

        TestLaserRoboVac.change_account('laser_robotic')

        home_page.into_device_home_page(data.get_device('laser_robotic'))
        if robotic_home_page.is_offline:
            robotic_home_page.ok
            if robotic_home_page.robovac_is_offline() is False:
                assert False, 'laser_robotic 设备处于离线状态'

        robotic_home_page.ingore_update_languge()
        robotic_home_page.into_setting()
        robotic_setting_page.into_share()
        assert data.get_username('phoneshare') not in share_setting_page.read_share_to_me_list(), 'laser_robotic 分享列表显示已移除的分享者信息'

    @pytest.mark.robovac
    @pytest.mark.laserrobotic
    @pytest.mark.run(order=220)
    @pytest.mark.parametrize('check_account', ['laser_robotic'], indirect=True)
    @pytest.mark.flaky(reruns=1, reruns_delay=60)
    def test_laser_robotic_refuse_share(self, delete_share_news, check_account, delete_refuse_share_account):
        """
        激光扫地机被分享者拒绝接受分享：
        1. 点击激光扫地机进入扫地机主页，点击 more进入设置界面，点击share setting进入分享列表
        2. 点击 add 按钮进入添加界面，输入分享账号：Yi@aa.com并提交
        【checkpoint】 分享邀请发送成功，弹窗提示：Successed to share
        3.重启app切换账号Yi@aa.com，进入分享消息记录
        4.点击拒绝接受分享按钮
        【checkpoint】显示已拒绝分享弹窗
        【chenckpoint】app首页不显示分享设备
        :param check_account:
        :return:
        """
        home_page.into_device_home_page(data.get_device('laser_robotic'))

        TestLaserRoboVac.laser_ready()

        robotic_home_page.into_setting()
        robotic_setting_page.into_share()
        share_setting_page.add_share()
        share_setting_page.commit_share(data.get_account('phoneshare'))
        assert share_setting_page.share_result(), 'laser_robotic 正确账号分享失败'
        share_setting_page.ok
        share_setting_page.loading()

        share_setting_page.back_setting()
        robotic_setting_page.back_robovac()
        robotic_home_page.back_home()

        TestLaserRoboVac.change_account('phoneshare')
        GlobalVar.set_test_flag('t')

        home_page.into_system()
        system_page.into_sharing()
        all_share_page.into_device(data.get_device('laser_robotic'))
        all_share_page.no
        assert all_share_page.text_display(
            'Request Declined. This device will be removed.'), 'laser_robotic 被分享者拒绝接受分享失败'
        all_share_page.ok
        all_share_page.loading()

        all_share_page.back_system()
        system_page.back_home()
        home_page.swipe_page('down')
        assert home_page.find_device(data.get_device('laser_robotic')) is False, 'app首页被分享者拒绝分享后显示分享了扫地机设备'

    @pytest.fixture(scope='function')
    def stop_laser_robovac(self):
        """
        停止扫地机工作
        :return:
        """
        yield 1
        if GlobalVar.get_test_flag() and data.get_robotic_status('cleaning') in robotic_home_page.read_robovac_status():
                robotic_home_page.t2190_play()

    @pytest.mark.robovac
    @pytest.mark.laserrobotic
    @pytest.mark.run(order=221)
    @pytest.mark.parametrize('check_account', ['laser_robotic'], indirect=True)
    @pytest.mark.flaky(reruns=1, reruns_delay=60)
    def test_laser_robotic_zone_clean(self, stop_laser_robovac, check_account):
        """
        激光启动指定区域清扫:
        1. app首页点击进入设备主页，点击zone clean
        2. 点击add添加一个区域，点击保存
        【checkpoint】检查是否启动清扫，状态：cleaning
        【checkpoint】检查按钮对应的状态文案
        :param delete_share_news:
        :param check_account:
        :return:
        """
        home_page.into_device_home_page(data.get_device('laser_robotic'))

        TestLaserRoboVac.laser_ready()

        robotic_home_page.t2190_zone_clean()
        robotic_zone_clean_page.close_tip()
        robotic_zone_clean_page.add_zone()
        assert robotic_zone_clean_page.is_toast_exist('No maps added.', True, True) is False, '激光扫地机当前无地图无法开始指定区域清扫'
        robotic_zone_clean_page.start_zone_clean()

        GlobalVar.set_test_flag('t')

        time.sleep(5)
        assert data.get_robotic_status('cleaning') in robotic_home_page.read_robovac_status(), 'laser_robotic 扫地机指定区域清扫失败'

    @pytest.mark.robovac
    @pytest.mark.run(order=222)
    @pytest.mark.parametrize('check_account', ['laser_robotic'], indirect=True)
    @pytest.mark.flaky(reruns=1, reruns_delay=60)
    def test_laser_robotic_add_delete_schedule(self, check_account):
        """
        激光扫地机添加和删除定时任务:
        1. app首页点击进入设备主页，点击schedule
        2. 激光添加一个定时任务，内容不做限制
        【checkpoint】 列表增加一个定时任务
        【checkpoint】新增扫地机任务状态变为开启
        3. 长按修改记录左滑删除
        【checkpoint】不显示定时任务修改记录
        :return:
        """
        home_page.into_device_home_page(data.get_device('laser_robotic'))

        TestLaserRoboVac.laser_ready()

        robotic_home_page.t2190_schedule()
        robotic_schedule_page.t2190_delete_schedule()
        robotic_schedule_page.t2190_creat_new_schedule()
        w = robotic_schedule_page.week_id
        assert robotic_schedule_page.text_display(data.get_week_by_id(str(w))), 'laser_robotic 添加定时任务后列表未显示'
        assert robotic_schedule_page.t2190_read_btn_status() == 'on', '定时任务开关默认状态显示错误'

        robotic_schedule_page.t2190_delete_schedule()
        time.sleep(2)
        assert robotic_schedule_page.t2190_count_schedule() == 0, 'laser_robotic 定时任务删除失败'

    @pytest.mark.robovac
    @pytest.mark.laserrobotic
    @pytest.mark.run(order=222)
    @pytest.mark.parametrize('check_account', ['laser_robotic'], indirect=True)
    @pytest.mark.flaky(reruns=1, reruns_delay=60)
    def test_laser_robotic_check_schedule_icon(self, check_account):
        """
        检查定时任务图标是否显示：
        1.进入app主页，检查是否显示定时任务图标
        2.如果未显示则去开启一个定时任务，并返回app首页
        【checkpoint】检查设备是否显示定时任务图标
        :return:
        """
        home_page.swipe_page('down')
        status = home_page.have_schedule_icon(data.get_device('laser_robotic'))

        if not status:
            home_page.into_device_home_page(data.get_device('laser_robotic'))

            TestLaserRoboVac.laser_ready()

            robotic_home_page.t2190_schedule()
            robotic_schedule_page.t2190_creat_new_schedule()
            robotic_schedule_page.back_robotic()
            robotic_home_page.back_home()
            home_page.swipe_page('down')
            status = home_page.have_schedule_icon(data.get_device('laser_robotic'))

        assert status, 'laser_robotic 未显示定时任务图标'

        home_page.click_schedule_icon(data.get_device('laser_robotic'))
        assert home_page.text_display('Schedules'), 'laser_robotic 定时任务快捷图标进入失败'

    @pytest.mark.robovac
    @pytest.mark.laserrobotic
    @pytest.mark.run(order=223)
    @pytest.mark.parametrize('check_account', ['laser_robotic'], indirect=True)
    def laser_robotic_help_title(self, check_account):
        """
        激光扫地机help列表数量统计:
        1. app首页点击进入设备主页，点击more进入设置界面，点击help
        2. 遍历help页面的问答列表
        【checkpoint】 统计help列表总数=
        【checkpoint】遍历help列表的标题是否正确
        :param check_account:
        :return:
        """
        home_page.into_device_home_page(data.get_device('laser_robotic'))
        robotic_home_page.skip_robotic_guide()
        if robotic_home_page.is_offline:
            robotic_home_page.ok

        robotic_home_page.ingore_update_languge()
        robotic_home_page.into_setting()
        robotic_setting_page.swipe_page('up')
        robotic_setting_page.into_device_help()
        title_list = device_help_page.read_help_title()
        assert len(title_list) != 0, 'laser_robotic help列表显示为空'

        # expect_list = data.read_json(data.get_device('laser_robotic'))
        #
        # num = len(title_list) == len(expect_list)
        # flag = True
        # expect_titles = [x for x in expect_list if x not in title_list]
        # print(expect_titles)
        # actual_titles = [x for x in title_list if x not in expect_list]
        # print(actual_titles)
        # if expect_titles or actual_titles:
        #     flag = False
        #
        # assert num and flag, 'laser_robotic help列表总数：' + str(num) + ',与预期相比缺少：' + str(expect_titles) + ',与实际相比多出：' + str(
        #     actual_titles)

    @pytest.mark.laserrobotic
    @pytest.mark.run(order=224)
    @pytest.mark.parametrize('check_account', ['laser_robotic'], indirect=True)
    @pytest.mark.flaky(reruns=1, reruns_delay=60)
    def laser_robotic_help_feedback(self, check_account):
        """
        激光扫地机help的反馈界面:
        1. app首页点击进入设备主页，点击more进入设置界面，点击help
        2.点击进入feedback页面，点击submit按钮
        【checkpoint】检查是否有toast提示：Feedback field cannot be blank.
        :return:
        """
        home_page.into_device_home_page(data.get_device('laser_robotic'))
        robotic_home_page.skip_robotic_guide()
        if robotic_home_page.is_offline:
            robotic_home_page.ok

        robotic_home_page.ingore_update_languge()
        robotic_home_page.into_setting()
        robotic_setting_page.swipe_page('up')
        robotic_setting_page.into_device_help()
        device_help_page.into_feed_back()
        device_help_page.submit_feed_back('laser test feedback')
        assert device_help_page.is_help_page(), 'laser_robotic 提交反馈失败'

    @pytest.mark.robovac
    @pytest.mark.laserrobotic
    @pytest.mark.run(order=225)
    @pytest.mark.parametrize('check_account', ['laser_robotic'], indirect=True)
    @pytest.mark.flaky(reruns=1, reruns_delay=60)
    def laser_robotic_help_chat(self, check_account):
        """
        激光扫地机help的chat界面：
        1. app首页点击进入设备主页，点击more进入设置界面，点击help
        2.进入chat界面，发送一条消息
        【checkpoint】检查消息回复
        :param check_account:
        :return:
        """
        home_page.into_device_home_page(data.get_device('laser_robotic'))
        robotic_home_page.skip_robotic_guide()
        if robotic_home_page.is_offline:
            robotic_home_page.ok

        robotic_home_page.ingore_update_languge()
        robotic_home_page.into_setting()
        robotic_setting_page.swipe_page('up')
        robotic_setting_page.into_device_help()
        device_help_page.into_chat()
        assert device_help_page.text_display('Chat With Eufy'), 'laser_robotic 进入chat聊天界面无响应'

    @pytest.mark.robovac
    @pytest.mark.laserrobotic
    @pytest.mark.run(order=226)
    @pytest.mark.parametrize('check_account', ['laser_robotic'], indirect=True)
    @pytest.mark.flaky(reruns=1, reruns_delay=60)
    def _laser_robotic_help_telphone(self, check_account):
        """
        激光扫地机help的电话界面：
        1. app首页点击进入设备主页，点击more进入设置界面，点击help
        2.进入call us 界面，检查页面的联系电话
        【checkpoint】遍历电话号码是否显示正确
        :param check_account:
        :return:
        """
        home_page.into_device_home_page(data.get_device('laser_robotic'))
        robotic_home_page.skip_robotic_guide()
        if robotic_home_page.is_offline:
            robotic_home_page.ok

        robotic_home_page.ingore_update_languge()
        robotic_home_page.into_setting()
        robotic_setting_page.swipe_page('up')
        robotic_setting_page.into_device_help()
        device_help_page.into_call_us()

        us = data.get_phone('us') in device_help_page.read_phone_number('us')
        uk = data.get_phone('uk') in device_help_page.read_phone_number('uk')
        de = data.get_phone('de') in device_help_page.read_phone_number('de')
        jp = data.get_phone('jp') in device_help_page.read_phone_number('jp')
        assert us and uk and de and jp, 'laser_robotic 客服联系电话显示错误：us=' + str(us) + ';uk=' + str(uk) + ';de=' + str(
            de) + ';jp=' + str(jp)

    @pytest.mark.robovac
    @pytest.mark.laserrobotic
    @pytest.mark.run(order=227)
    @pytest.mark.parametrize('check_account', ['laser_robotic'], indirect=True)
    @pytest.mark.flaky(reruns=1, reruns_delay=60)
    def test_laser_robotic_manual_controls(self, check_account):
        """
        激光扫地机手动控制界面操作：
        1. app首页点击进入设备主页，点击more
        2. 点击manual controls进入控制界面，点击spot
        【checkpoint】 按钮开关文字变为：puase
        【checkpoint】扫地机状态变为spot
        3. 点击recharge
        【checkpoint】 回充提示tosat：Heading home. . .
        【checkpoint】扫地机状态：Heading home
        :return:
        """
        home_page.into_device_home_page(data.get_device('laser_robotic'))
        robotic_home_page.skip_robotic_guide()

        TestLaserRoboVac.laser_ready()

        robotic_home_page.into_setting()
        robotic_setting_page.swipe_page('up')
        robotic_setting_page.into_manual()

        robotic_manual_page.click_clean()
        time.sleep(2.5)
        assert robotic_manual_page.check_clean_status('manual_stop'), 'laser_robotic 手动启动清扫失败'

        robotic_manual_page.click_clean()
        time.sleep(2.5)
        assert robotic_manual_page.check_clean_status('manual_start'), 'laser_robotic 手动停止清扫失败'

        robotic_manual_page.click_spot()
        time.sleep(2.5)
        assert robotic_manual_page.check_clean_status('manual_stop'), 'laser_robotic 手动启动定点清扫失败'

        robotic_manual_page.click_recharge()
        flag = False
        times = 1
        while times < 7:
            times = times + 1
            if robotic_manual_page.check_clean_status('manual_start'):
                flag = True
                break
            else:
                time.sleep(10)
        assert flag, 'laser_robotic 手动启动回充失败'

    @pytest.mark.robovac
    @pytest.mark.skip(reason="无有效的判断条件")
    @pytest.mark.laserrobotic
    @pytest.mark.run(order=228)
    @pytest.mark.parametrize('check_account', ['laser_robotic'], indirect=True)
    @pytest.mark.flaky(reruns=1, reruns_delay=60)
    def laser_robotic_reset_single_mantenance(self, check_account):
        """
        单个配材重置:
        1. app首页点击进入设备主页，点击more
        2.进入配材重置界面，选择滤网，点击reset
        【checkpoint】弹出重置确认弹窗
        【checkpoint】当前配材主页重置后使用率为100%，使用时间0h
        :param check_account:
        :return:
        """
        home_page.into_device_home_page(data.get_device('laser_robotic'))
        robotic_home_page.skip_robotic_guide()

        TestLaserRoboVac.laser_ready()

        robotic_home_page.into_setting()
        robotic_setting_page.swipe_page('up')
        robotic_setting_page.into_maintenance()
        robotic_maintence_page.clear_filter()

        assert robotic_maintence_page.text_display('Do you want to reset time for the filter?'), '滤网重置未显示弹窗提示'
        if robotic_maintence_page.platform == 'ios':
            robotic_maintence_page.ok
        else:
            robotic_maintence_page.yes

        assert robotic_maintence_page.is_toast_exist('', True, True), 'filter 重置失败，未显示成功toast提示'

    @pytest.mark.robovac
    @pytest.mark.skip(reason="无有效的判断条件")
    @pytest.mark.laserrobotic
    @pytest.mark.run(order=229)
    @pytest.mark.parametrize('check_account', ['laser_robotic'], indirect=True)
    def laser_robotic_reset_all_mantenance(self, check_account):
        """
        全部配材重置:
        1. app首页点击进入设备主页，点击more
        2.进入配材列表界面，点击claer
        【checkpoint】 弹出重置确认弹窗
        【checkpoint】配材列表重置后使用率为100%，使用时间0h
        :param check_account:
        :return:
        """
        home_page.into_device_home_page(data.get_device('laser_robotic'))
        robotic_home_page.skip_robotic_guide()

        TestLaserRoboVac.laser_ready()

        robotic_home_page.into_setting()
        robotic_setting_page.swipe_page('up')
        robotic_setting_page.into_maintenance()

        robotic_maintence_page.clear_all()
        assert robotic_maintence_page.text_display('Do you want to reset time for all of Maintenance?'), '配材重置未显示弹窗提示'

        robotic_maintence_page.yes
        robotic_maintence_page.is_toast_exist('', True, True), '配材一键重置失败，未显示成功toast提示'

    @pytest.mark.parametrize('check_account', ['laser_robotic'], indirect=True)
    def laser_robotic_stop_clean_no_record(self, check_account):
        """
        激光扫地机启动清扫后暂停不生成清扫记录:
        1. app首页点击进入设备主页，点击more进入设置界面，点击help
        2. 点击clean启动清扫，等待30s后点击stop暂停清扫，查看清扫历史记录
        【checkpoint】清扫暂停不显示清扫历史记录
        :return:
        """
        home_page.into_device_home_page(data.get_device('laser_robotic'))

        TestLaserRoboVac.laser_ready()

        robotic_home_page.into_clean_history()
        if robotic_clean_history_page.count_record() > 0:
            robotic_clean_history_page.clear_all()
            robotic_clean_history_page.commit_clear()
            robotic_clean_history_page.loading()
        robotic_clean_history_page.back_robovac()

        robotic_home_page.t2190_play()
        time.sleep(3)
        assert robotic_home_page.text_display('Pause'), 'laser_robotic 启动清扫失败'

        robotic_home_page.long_wait(20)
        robotic_home_page.t2190_play()
        robotic_home_page.into_clean_history()
        assert robotic_clean_history_page.count_record() == 0, 'laser_robotic 暂停清扫也生成了清扫记录'

    @pytest.mark.robovac
    @pytest.mark.laserrobotic
    @pytest.mark.run(order=232)
    @pytest.mark.parametrize('check_account', ['laser_robotic'], indirect=True)
    @pytest.mark.flaky(reruns=1, reruns_delay=60)
    def test_laser_robotic_spot_make_record(self, check_account):
        """
        激光扫地机回充成功生成清扫记录:
        1. app首页点击进入设备主页，点击清扫按钮
        【checkpoint】扫地机状态为cleaning
        2. 点击recharge按钮，等待扫地机状态变为standard，查看清扫记录列表
        【checkpoint】检查历史记录列表是否新增清扫记录
        :return:
        """
        home_page.into_device_home_page(data.get_device('laser_robotic'))

        TestLaserRoboVac.laser_ready()

        robotic_home_page.into_clean_history()
        if robotic_clean_history_page.count_record() > 0:
            robotic_clean_history_page.clear_all()
            robotic_clean_history_page.commit_clear()
        robotic_clean_history_page.back_robovac()

        robotic_home_page.into_setting()
        robotic_setting_page.into_manual()
        robotic_manual_page.click_spot()
        time.sleep(3)
        robotic_manual_page.back_setting()
        robotic_setting_page.back_robovac()
        assert robotic_home_page.read_robovac_status() == data.get_robotic_status('cleaning'), '扫地机定点清扫失败'

        robotic_home_page.long_wait(30)
        robotic_home_page.t2190_play()
        robotic_home_page.t2190_stop_spot_clean()
        robotic_home_page.long_wait(60)
        robotic_home_page.into_clean_history()
        assert robotic_clean_history_page.count_record() == 1, 'laser_robotic 清扫回充成功后未生成清扫记录'

    @pytest.mark.robovac
    @pytest.mark.laserrobotic
    @pytest.mark.run(order=233)
    @pytest.mark.parametrize('desc', ['all', 'single'])
    @pytest.mark.parametrize('check_account', ['laser_robotic'], indirect=True)
    @pytest.mark.flaky(reruns=1, reruns_delay=60)
    def test_laser_robotic_delete_clean_history(self, desc, check_account):
        """
        激光扫地机删除单条清扫记录:
        1. app首页点击进入设备主页，生成一条清扫记录
        2.点击clear全部清除
        【checkpoint】历史记录列表显示为空
        :return:
        """
        home_page.into_device_home_page(data.get_device('laser_robotic'))

        TestLaserRoboVac.laser_ready()

        robotic_home_page.into_clean_history()
        time.sleep(3)
        num = robotic_clean_history_page.count_record()
        if num == 0:
            robotic_clean_history_page.back_robovac()
            robotic_home_page.into_setting()
            robotic_setting_page.into_manual()
            robotic_manual_page.click_spot()
            time.sleep(5)
            robotic_manual_page.back_setting()
            robotic_setting_page.back_robovac()
            robotic_home_page.t2190_play()
            robotic_home_page.t2190_stop_spot_clean()
            robotic_home_page.long_wait(60)
            robotic_home_page.into_clean_history()

            if robotic_clean_history_page.count_record() == 0:
                assert False, 'laser_robotic 生成清扫历史记录失败'

        if desc == 'all':
            robotic_clean_history_page.clear_all()
            robotic_clean_history_page.commit_clear()
        elif desc == 'single':
            robotic_clean_history_page.delete_one_by_one()
        robotic_clean_history_page.back_robovac()
        robotic_home_page.into_clean_history()

        time.sleep(3)
        num_1 = robotic_clean_history_page.count_record()

        assert num_1 == 0, 'laser_robotic ' + desc + ' 删除清扫记录失败'

    @pytest.fixture(scope='function')
    def close_laser_schedule(self):
        """
        关闭扫地机及定时任务
        :return:
        """
        yield 1
        if GlobalVar.get_test_flag():
            if data.get_robotic_status('cleaning') == robotic_home_page.read_robovac_status():
                robotic_home_page.t2190_play()
            robotic_home_page.t2190_schedule()
        robotic_schedule_page.t2190_delete_schedule()

    @pytest.mark.run(order=234)
    @pytest.mark.robovac
    @pytest.mark.parametrize('check_account', ['laser_robotic'], indirect=True)
    def test_laser_robotic_schedule_time(self, check_account, close_laser_schedule):
        """
        激光扫地机设置定时任务：
        1.设置一个基于当前时间5min后的定时任务
        【checklist】检查定时任务列表的时间是否设置正确
        2.等待定时任务启动
        【checklist】检查定时任务启动后扫地机的状态
        :param check_account:
        :return:
        """
        home_page.into_device_home_page(data.get_device('laser_robotic'))
        TestLaserRoboVac.laser_ready()

        # 开启定点清扫，然后让扫地机为默认状态而不是暂停清扫状态
        robotic_home_page.into_setting()
        robotic_setting_page.into_manual()
        robotic_manual_page.click_spot()
        robotic_manual_page.back_setting()
        robotic_setting_page.back_robovac()
        time.sleep(5)

        if robotic_home_page.read_robovac_status() == data.get_robotic_status('cleaning'):
            robotic_home_page.t2190_play()
        robotic_home_page.t2190_schedule()
        robotic_schedule_page.t2190_delete_schedule()
        _t = robotic_schedule_page.t2190_creat_new_schedule(data.get_device('laser_robotic'), 5)

        assert _t == robotic_schedule_page.t2190_read_schedule_time(robotic_schedule_page.week_simple_name), '定时任务设置正确'
        robotic_schedule_page.back_robotic()

        GlobalVar.set_test_flag('t')  # 此处需要判断扫地机状态了

        robotic_home_page.long_wait(320)
        assert data.get_robotic_status('cleaning') in robotic_home_page.read_robovac_status(), '定时任务执行启动成功'

    @pytest.fixture(scope='function')
    def set_laser_robotic_name(self):
        """
        恢复设备名称
        :return:
        """
        yield 1
        if home_page.is_welcome():
            home_page.into_device_home_page(data.get_device('laser_robotic'))
        if robotic_home_page.text_display('T2190'):
            robotic_home_page.into_setting()
        if robotic_setting_page.read_device_name() != data.get_device('laser_robotic'):
            robotic_setting_page.change_device_name(data.get_device('laser_robotic'))
        robotic_setting_page.back_robovac()
        robotic_home_page.t2190_charge()
        robotic_home_page.long_wait(30)

    @pytest.mark.robovac
    @pytest.mark.laserrobotic
    @pytest.mark.run(order=235)
    @pytest.mark.parametrize('check_account', ['laser_robotic'], indirect=True)
    @pytest.mark.flaky(reruns=1, reruns_delay=60)
    def test_laser_robotic_change_device_name(self, check_account, set_laser_robotic_name):
        """
        修改扫地机设备名称:
        1. app首页点击进入设备主页，点击更多，修改设备名称T2190_随机数
        【checkpoint】设备控制页名称显示正确
        【checkpoint】设备主页显示名称正确
        【checkpoint】app主页设备名显示正确
        :param check_account:
        :return:
        """
        home_page.into_device_home_page(data.get_device('laser_robotic'))

        TestLaserRoboVac.laser_ready()

        robotic_home_page.into_setting()
        _name = data.get_device('laser_robotic') + robotic_setting_page.get_str()

        robotic_setting_page.change_device_name(_name)
        assert _name in robotic_setting_page.read_device_name(), 'laser_robotic 扫地机修改名称后设置页面显示的名称不对'

        robotic_setting_page.back_robovac()
        assert _name in robotic_home_page.read_t2190_name(), 'laser_robotic 扫地机修改名称后设备主页面显示的名称不对'

        robotic_home_page.back_home()
        home_page.swipe_page('down')
        assert home_page.find_device(_name), 'laser_robotic 扫地机修改名称后app主页面显示的名称不对'

    @pytest.mark.robovac
    @pytest.mark.laserrobotic
    @pytest.mark.run(order=236)
    @pytest.mark.parametrize('check_account', ['laser_robotic'], indirect=True)
    @pytest.mark.flaky(reruns=1, reruns_delay=60)
    def test_laser_robotic_remove(self, check_account):
        """
        移除激光扫地机设备：
        1. app首页点击进入设备主页，点击more进入设置界面
        2. 点击remove
        【checkpoint】弹出移除成功确认弹窗
        【checkpoint】返回app首页，设备列表不显示T2250
        :param check_account:
        :return:
        """
        if GlobalVar.get_remove_add() == 0:
            pytest.skip('本次指定不执行词条用例')

        home_page.into_device_home_page(data.get_device('laser_robotic'))

        TestLaserRoboVac.laser_ready()

        robotic_home_page.into_setting()
        robotic_setting_page.swipe_page('up')
        robotic_setting_page.click_remove()
        assert robotic_setting_page.text_display(
            'Are you sure you want to remove this device?'), 'laser_robotic 未显示删除设备提示弹窗'
        robotic_setting_page.commit_remove()
        robotic_setting_page.loading()
        home_page.swipe_page('down')
        assert home_page.find_device(data.get_device('laser_robotic')) is False, 'laser_robotic 扫地机移除之后主页还未删除'

    @pytest.fixture(scope='function')
    def reset_phone_network(self):
        """
        检查并重置手机网络，防止配网失败影响网络
        :return:
        """
        yield 1
        add_device_page.set_system_wifi(data.get_wifi('phone')[0])

    @pytest.mark.robovac
    @pytest.mark.laserrobotic
    @pytest.mark.run(order=237)
    @pytest.mark.parametrize('check_account', ['laser_robotic'], indirect=True)
    def test_laser_robotic_add_device(self, check_account, reset_phone_network):
        """
        添加激光扫地机:
        1. app首页点击+，选择robotic，选择 RoboVac 30C max
        2. 点击Next，勾选 Status Confirmed，点击 next
        3. 选择亚添加的设备id
        4. 连接中，等待conecting消失
        【checkpoint】判断是否显示添加成功（文本校验）
        5. 修改设备昵称未T2150，点击保存
        6. 返回设备主页查看设备列表
        【checkpoint】首页列表刷新后显示扫地机T2190
        :param check_account:
        :return:
        """
        if GlobalVar.get_remove_add() == 0:
            GlobalVar.set_test_flag('f')
            pytest.skip('本次指定不执行词条用例')

        home_page.swipe_page('down')
        if home_page.find_device(data.get_device('laser_robotic')):
            home_page.into_device_home_page(data.get_device('laser_robotic'))

            TestLaserRoboVac.laser_ready()

            robotic_home_page.into_setting()
            robotic_setting_page.swipe_page('up')
            robotic_setting_page.click_remove()
            robotic_setting_page.commit_remove()
            robotic_setting_page.loading()

        home_page.click_add_device()
        add_device_page.click_robotic()
        add_device_page.select_robotic('L70 Hybrid')
        wifi_data = data.get_wifi('laser_robotic')
        add_device_page.set_wifi(wifi_data[0], wifi_data[1])
        add_device_page.confirm_status()
        add_device_page.select_robotic_by_id(data.get_device_udid('laser_robotic'))
        add_device_page.loading()

        add_device_page.wait_connect()
        assert add_device_page.connect_result(), 'inertia_robotic 配网连接失败'
        add_device_page.set_device_name(data.get_device('laser_robotic'))
        add_device_page.ok
        add_device_page.loading()

        home_page.swipe_page('down')
        assert home_page.find_device(data.get_device('laser_robotic')), 'laser_robotic 配网成功后首页未查找到T2190设备'


class Solution:
    def lengthOfLongestSubstrig(self, s):
        if not s:
            return 0
        #初始化一个窗口和最大字符串
        window = []
        maxLength = 0
        #对每一个 字符遍历
        for c in s:
            #不在窗口则添加字符进去
            if c not in window:
                window.append(c)
            else:
                #在窗口里面，去除字符之前的字符串，并在后面添加当前字符
                window[:] = window[window.index(c)+1 :]
                window.append(c)
            #更新最大字符
            maxLength = max(maxLength, len(window))
        #处理无重复字符数据
        return maxLength if maxLength != 0 else len(s)

    def fun2(self, s):
        #双指针法 left right 表示窗口边界
        maxLength = left = right = 0
        for c in s:
            #如果char不在窗口，更新右边界
            if c not in s[left:right]:
                right += 1
            else:
                #如果在的话，更新left right边界
                left += s[left:right].index(c) + 1
                right += 1
            #更新最大字符串长度
            maxLength = max(maxLength, (right-left))
        #case全无重复数字情况
        return maxLength if maxLength != 0 else len(s)

[[0] * (3)] * 3

3.无重复字符的最长字串.py


#### we understand the class attribute and
#### the instance attribute
#### there are two type of attribute
#### 1) class atribute
#### 2) instance attribute

## making a class
class Employee:

    ### this is a class attribute
    numberOfWorkingHours = 40

## now instantiate the class
employeeOne = Employee()
employeeTwo = Employee()

print(employeeOne.numberOfWorkingHours)
print(employeeTwo.numberOfWorkingHours)

## we can access the class variable with this
## and when we create an object
## all the object will have ths attribute
## a class attribute have the common data for all the instance of the class

### now we can add attribute directly but it depend on the
### object and only this object can have it

employeeOne.name = "tanvir"

print(employeeOne.name)

### this will show an error
#print(employeeTwo.name)

### this is the instance attribute

employeeTwo.name = "ornob"
print(employeeTwo.name)

## when you try to print the attribute
## it will first look for the instance attribute
## then the class attribute
## and if not found in there then it throw an error


import vanir.api
import vanir.ext
import vanir.vm.adminvm

class AdminExtension(vanir.ext.Extension):
    # pylint: disable=too-few-public-methods
    @vanir.ext.handler(
        'admin-permission:admin.vm.tag.Set',
        'admin-permission:admin.vm.tag.Remove')
    def on_tag_set_or_remove(self, vm, event, arg, **kwargs):
        '''Forbid changing specific tags'''
        # pylint: disable=no-self-use,unused-argument
        if arg.startswith('created-by-') and \
                not isinstance(vm, vanir.vm.adminvm.AdminVM):
            raise vanir.api.PermissionDenied(
                'changing this tag is prohibited by {}.{}'.format(
                    __name__, type(self).__name__))


import random
import numpy as np

def medir_temp(p):
    mediciones= []
    for i in range(p):
        num = 37.5 + random.normalvariate(0, 0.2)
        mediciones.append(num)
    np.save('../Data/temperaturas', mediciones)
    return mediciones

def resumen_temp(n):
    promedio = sum(n)/ len(n)
    maximo = max(n)
    minimo = min(n)
    data = sorted(n)
    index = len(data) // 2
    mediana = 0

    if len(n) % 2 == 0:
        mediana = (data[index - 1] + data[index]) / 2
    else:
        mediana = data[index]

    return (maximo, minimo, promedio, mediana)

def main():
    e =medir_temp(999)


# @Author  : Willpower-chen
# @blog: http://www.cnblogs.com/willpower-chen/
from utils.response import BaseResponse
from .base import BaseServiceList
from repository import models
from utils.pager import PageInfo

class Business(BaseServiceList):
	def __init__(self):
		condition_config = [
			{'name': 'name', 'text': '业务线', 'condition_type': 'input'},
			# {'name': 'name', 'text': '业务联系人', 'condition_type': 'input'},
			{'name': 'manager__name', 'text': '系统管理员', 'condition_type': 'input'},
		]
		table_config = [
			{
				'q': 'id',  # 用于数据库查询的字段，即Model.Tb.objects.filter(*[])
				'title': "ID",  # 前段表格中显示的标题
				'display': 1,  # 是否在前段显示，0表示在前端不显示, 1表示在前端隐藏, 2表示在前段显示
				'text': {'content': "{id}", 'kwargs': {'id': '@id'}},
				'attr': {}  # 自定义属性
			},
			{
				'q': 'name',
				'title': "业务线",
				'display': 1,
				'text': {'content': "{n}", 'kwargs': {'n': '@name'}},
				'attr': {'edit-enable':'true','edit-type':'input'}  # 自定义属性
			},
			# {
			# 	'q': 'contact__name',
			# 	'title': "业务联系人",
			# 	'display': 1,
			# 	'text': {'content': "{n}", 'kwargs': {'n': '@contact__name'}},
			# 	'attr': {'edit-enable': 'true', 'edit-type': 'input'}  # 自定义属性
			# },
			{
				'q': 'manager__name',
				'title': "系统管理员",
				'display': 1,
				'text': {'content': "{n}", 'kwargs': {'n': '@manager__name'}},
				'attr': {'edit-enable': 'true', 'edit-type': 'input'}  # 自定义属性
			},
			{
				'q': 'manager_id',
				'title': "系统管理员ID",
				'display': 0,
				'text': {'content': "{n}", 'kwargs': {'n': '@manager_id'}},
				'attr': {}  # 自定义属性
			},
			{
				'q': None,
				'title': "选项",
				'display': 1,
				'text': {
					'content': "查看详细",
					'kwargs': {'nid': '@id'}},
				'attr': {}
			},
		]
		extra_select = {}
		super(Business, self).__init__(condition_config, table_config, extra_select)

	def fetch_business(self, request):
		response = BaseResponse()
		try:
			ret = {}
			conditions = self.assets_condition(request)

			asset_count = models.BusinessUnit.objects.filter(conditions).count()
			page_info = PageInfo(request.GET.get('pager', None), asset_count)

			asset_list = models.BusinessUnit.objects.filter(conditions).extra(select=self.extra_select).values(
				*self.values_list)[page_info.start:page_info.end]

			ret['table_config'] = self.table_config
			ret['condition_config'] = self.condition_config
			ret['data_list'] = list(asset_list)
			ret['page_info'] = {
				"page_str": page_info.pager(),
				"page_start": page_info.start,
			}
			ret['global_dict'] = {}
			response.data = ret
			response.message = '获取成功'
		except Exception as e:
			response.status = False
			response.message = str(e)

		return response


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

import collections
import errno
import logging
import multiprocessing
import threading
import traceback

from gslib.utils import constants
from gslib.utils import system_util
from six.moves import queue as Queue

# pylint: disable=g-import-not-at-top
try:
  # This module doesn't necessarily exist on Windows.
  import resource
  _HAS_RESOURCE_MODULE = True
except ImportError as e:
  _HAS_RESOURCE_MODULE = False

# Maximum time to wait (join) on the SeekAheadThread after the ProducerThread
# completes, in seconds.
SEEK_AHEAD_JOIN_TIMEOUT = 60

# Timeout for puts/gets to the global status queue, in seconds.
STATUS_QUEUE_OP_TIMEOUT = 5

# Maximum time to wait (join) on the UIThread after the Apply
# completes, in seconds.
UI_THREAD_JOIN_TIMEOUT = 60

ZERO_TASKS_TO_DO_ARGUMENT = ('There were no', 'tasks to do')

# Multiprocessing manager used to coordinate across all processes. This
# attribute is only present if multiprocessing is available, which can be
# determined by calling CheckMultiprocessingAvailableAndInit().
global top_level_manager  # pylint: disable=global-at-module-level

# Cache the values from this check such that they're available to all callers
# without needing to run all the checks again (some of these, such as calling
# multiprocessing.Manager(), are expensive operations).
_cached_multiprocessing_is_available = None
_cached_multiprocessing_check_stack_trace = None
_cached_multiprocessing_is_available_message = None

# This must be defined at the module level for pickling across processes.
MultiprocessingIsAvailableResult = collections.namedtuple(
    'MultiprocessingIsAvailableResult', ['is_available', 'stack_trace'])

# Explicitly set start method to 'fork' since this isn't always the default
# in later versions of Python.
try:
  multiprocessing_context = multiprocessing.get_context('fork')
except (AttributeError, ValueError):
  multiprocessing_context = multiprocessing

class AtomicDict(object):
  """Thread-safe (and optionally process-safe) dictionary protected by a lock.

  If a multiprocessing.Manager is supplied on init, the dictionary is
  both process and thread safe. Otherwise, it is only thread-safe.
  """

  def __init__(self, manager=None):
    """Initializes the dict.

    Args:
      manager: (multiprocessing.Manager or None) Manager instance (required for
          cross-process safety), or none if cross-process safety is not needed.
    """
    if manager:
      self.lock = manager.Lock()
      self.dict = manager.dict()
    else:
      self.lock = threading.Lock()
      self.dict = {}

  def __getitem__(self, key):
    with self.lock:
      return self.dict[key]

  def __setitem__(self, key, value):
    with self.lock:
      self.dict[key] = value

  # pylint: disable=invalid-name
  def get(self, key, default_value=None):
    with self.lock:
      return self.dict.get(key, default_value)

  def delete(self, key):
    with self.lock:
      del self.dict[key]

  def values(self):
    with self.lock:
      return self.dict.values()

  def Increment(self, key, inc, default_value=0):
    """Atomically updates the stored value associated with the given key.

    Performs the atomic equivalent of
    dict[key] = dict.get(key, default_value) + inc.

    Args:
      key: lookup key for the value of the first operand of the "+" operation.
      inc: Second operand of the "+" operation.
      default_value: Default value if there is no existing value for the key.

    Returns:
      Incremented value.
    """
    with self.lock:
      val = self.dict.get(key, default_value) + inc
      self.dict[key] = val
      return val

class ProcessAndThreadSafeInt(object):
  """This class implements a process and thread-safe integer.

  It is backed either by a multiprocessing Value of type 'i' or an internal
  threading lock.  This simplifies the calling pattern for
  global variables that could be a Multiprocessing.Value or an integer.
  Without this class, callers need to write code like this:

  global variable_name
  if isinstance(variable_name, int):
    return variable_name
  else:
    return variable_name.value
  """

  def __init__(self, multiprocessing_is_available):
    self.multiprocessing_is_available = multiprocessing_is_available
    if self.multiprocessing_is_available:
      # Lock is implicit in multiprocessing.Value
      self.value = multiprocessing_context.Value('i', 0)
    else:
      self.lock = threading.Lock()
      self.value = 0

  def Reset(self, reset_value=0):
    if self.multiprocessing_is_available:
      self.value.value = reset_value
    else:
      with self.lock:
        self.value = reset_value

  def Increment(self):
    if self.multiprocessing_is_available:
      self.value.value += 1
    else:
      with self.lock:
        self.value += 1

  def Decrement(self):
    if self.multiprocessing_is_available:
      self.value.value -= 1
    else:
      with self.lock:
        self.value -= 1

  def GetValue(self):
    if self.multiprocessing_is_available:
      return self.value.value
    else:
      with self.lock:
        return self.value

def _IncreaseSoftLimitForResource(resource_name, fallback_value):
  """Sets a new soft limit for the maximum number of open files.

  The soft limit is used for this process (and its children), but the
  hard limit is set by the system and cannot be exceeded.

  We will first try to set the soft limit to the hard limit's value; if that
  fails, we will try to set the soft limit to the fallback_value iff this would
  increase the soft limit.

  Args:
    resource_name: Name of the resource to increase the soft limit for.
    fallback_value: Fallback value to be used if we couldn't set the
                    soft value to the hard value (e.g., if the hard value
                    is "unlimited").

  Returns:
    Current soft limit for the resource (after any changes we were able to
    make), or -1 if the resource doesn't exist.
  """

  # Get the value of the resource.
  try:
    (soft_limit, hard_limit) = resource.getrlimit(resource_name)
  except (resource.error, ValueError):
    # The resource wasn't present, so we can't do anything here.
    return -1

  # Try to set the value of the soft limit to the value of the hard limit.
  if hard_limit > soft_limit:  # Some OS's report 0 for "unlimited".
    try:
      resource.setrlimit(resource_name, (hard_limit, hard_limit))
      return hard_limit
    except (resource.error, ValueError):
      # We'll ignore this and try the fallback value.
      pass

  # Try to set the value of the soft limit to the fallback value.
  if soft_limit < fallback_value:
    try:
      resource.setrlimit(resource_name, (fallback_value, hard_limit))
      return fallback_value
    except (resource.error, ValueError):
      # We couldn't change the soft limit, so just report the current
      # value of the soft limit.
      return soft_limit
  else:
    return soft_limit

def ShouldProhibitMultiprocessing():
  """Determines if the OS doesn't support multiprocessing.

  There are two cases we currently know about:
    - Multiple processes are not supported on Windows.
    - If an error is encountered while using multiple processes on Alpine Linux
      gsutil hangs. For this case it's possible we could do more work to find
      the root cause but after a fruitless initial attempt we decided instead
      to fall back on multi-threading w/o multiprocesing.

  Returns:
    (bool indicator if multiprocessing should be prohibited, OS name)
  """
  if system_util.IS_WINDOWS:
    # Issues have been observed while trying to use multi-processing in Windows
    return (True, 'Windows')
  if system_util.IS_OSX:
    # macOS does not contain /etc/os-release, used in this method. This
    # shortcuts raising an exception and returning 'Unknown' as an OS.
    return (False, 'macOS')
  try:
    with open('/etc/os-release', 'r') as f:
      # look for line that contains 'NAME=' both PRETTY_NAME and NAME should
      # be acceptable to try to find if alpine linux is being used.
      for line in f.read().splitlines():
        if 'NAME=' in line:
          os_name = line.split('=')[1].strip('"')
          return ('alpine linux' in os_name.lower(), os_name)
      # Unable to determine OS. NAME line not found in /etc/os-release file.
      return (False, 'Unknown')
  except IOError as e:
    if e.errno == errno.ENOENT:
      logging.debug('Unable to open /etc/os-release to determine whether OS '
                    'supports multiprocessing: errno=%d, message=%s' %
                    (e.errno, str(e)))
      return (False, 'Unknown')
    else:
      raise
  except Exception as exc:
    logging.debug('Something went wrong while trying to determine '
                  'multiprocessing capabilities.\nMessage: {0}'.format(
                      str(exc)))
    return (False, 'Unknown')

def CheckMultiprocessingAvailableAndInit(logger=None):
  """Checks if multiprocessing is available, and if so performs initialization.

  There are some environments in which there is no way to use multiprocessing
  logic that's built into Python (e.g., if /dev/shm is not available, then
  we can't create semaphores). This simply tries out a few things that will be
  needed to make sure the environment can support the pieces of the
  multiprocessing module that we need.

  See gslib.command.InitializeMultiprocessingVariables for
  an explanation of why this is necessary.

  Args:
    logger: (logging.Logger) Logger to use for debug output.

  Returns:
    (MultiprocessingIsAvailableResult) A namedtuple with the following attrs:
      - multiprocessing_is_available: True iff the multiprocessing module is
            available for use.
      - stack_trace: The stack trace generated by the call we tried that
            failed.
  """
  # pylint: disable=global-variable-undefined
  global _cached_multiprocessing_is_available
  global _cached_multiprocessing_check_stack_trace
  global _cached_multiprocessing_is_available_message
  if _cached_multiprocessing_is_available is not None:
    if logger:
      logger.debug(_cached_multiprocessing_check_stack_trace)
      logger.warn(_cached_multiprocessing_is_available_message)
    return MultiprocessingIsAvailableResult(
        is_available=_cached_multiprocessing_is_available,
        stack_trace=_cached_multiprocessing_check_stack_trace)

  should_prohibit_multiprocessing, os_name = ShouldProhibitMultiprocessing()
  if should_prohibit_multiprocessing:
    message = """
Multiple processes are not supported on %s. Operations requesting
parallelism will be executed with multiple threads in a single process only.
""" % os_name
    if logger:
      logger.warn(message)
    return MultiprocessingIsAvailableResult(is_available=False,
                                            stack_trace=None)

  stack_trace = None
  multiprocessing_is_available = True
  message = """
You have requested multiple processes for an operation, but the
required functionality of Python\'s multiprocessing module is not available.
Operations requesting parallelism will be executed with multiple threads in a
single process only.
"""
  try:
    # Fails if /dev/shm (or some equivalent thereof) is not available for use
    # (e.g., there's no implementation, or we can't write to it, etc.).
    try:
      multiprocessing_context.Value('i', 0)
    except:
      message += """
Please ensure that you have write access to both /dev/shm and /run/shm.
"""
      raise  # We'll handle this in one place below.

    global top_level_manager  # pylint: disable=global-variable-undefined
    top_level_manager = multiprocessing_context.Manager()

    # Check that the max number of open files is reasonable. Always check this
    # after we're sure that the basic multiprocessing functionality is
    # available, since this won't matter unless that's true.
    limit = -1
    if _HAS_RESOURCE_MODULE:
      # Try to set this with both resource names - RLIMIT_NOFILE for most Unix
      # platforms, and RLIMIT_OFILE for BSD. Ignore AttributeError because the
      # "resource" module is not guaranteed to know about these names.
      try:
        limit = max(
            limit,
            _IncreaseSoftLimitForResource(
                resource.RLIMIT_NOFILE,
                constants.MIN_ACCEPTABLE_OPEN_FILES_LIMIT))
      except AttributeError:
        pass

      try:
        limit = max(
            limit,
            _IncreaseSoftLimitForResource(
                resource.RLIMIT_OFILE,
                constants.MIN_ACCEPTABLE_OPEN_FILES_LIMIT))
      except AttributeError:
        pass

    if limit < constants.MIN_ACCEPTABLE_OPEN_FILES_LIMIT:
      message += ("""
Your max number of open files, %s, is too low to allow safe multiprocessing.
On Linux you can fix this by adding something like "ulimit -n 10000" to your
~/.bashrc or equivalent file and opening a new terminal.

On macOS, you may also need to run a command like this once (in addition to the
above instructions), which might require a restart of your system to take
effect:
  launchctl limit maxfiles 10000

Alternatively, edit /etc/launchd.conf with something like:
  limit maxfiles 10000 10000

""" % limit)
      raise Exception('Max number of open files, %s, is too low.' % limit)
  except:  # pylint: disable=bare-except
    stack_trace = traceback.format_exc()
    multiprocessing_is_available = False
    if logger is not None:
      logger.debug(stack_trace)
      logger.warn(message)

  # Set the cached values so that we never need to do this check again.
  _cached_multiprocessing_is_available = multiprocessing_is_available
  _cached_multiprocessing_check_stack_trace = stack_trace
  _cached_multiprocessing_is_available_message = message
  return MultiprocessingIsAvailableResult(
      is_available=_cached_multiprocessing_is_available,
      stack_trace=_cached_multiprocessing_check_stack_trace)

def CreateLock():
  """Returns either a multiprocessing lock or a threading lock.

  Use Multiprocessing lock iff we have access to the parts of the
  multiprocessing module that are necessary to enable parallelism in operations.

  Returns:
    Multiprocessing or threading lock.
  """
  if CheckMultiprocessingAvailableAndInit().is_available:
    return top_level_manager.Lock()
  else:
    return threading.Lock()

# Pylint gets confused by the mixed lower and upper-case method names in
# AtomicDict.
# pylint: disable=invalid-name
def PutToQueueWithTimeout(queue, msg, timeout=STATUS_QUEUE_OP_TIMEOUT):
  """Puts an item to the status queue.

  If the queue is full, this function will timeout periodically and repeat
  until success. This avoids deadlock during shutdown by never making a fully
  blocking call to the queue, since Python signal handlers cannot execute
  in between instructions of the Python interpreter (see
  https://docs.python.org/2/library/signal.html for details).

  Args:
    queue: Queue class (typically the global status queue)
    msg: message to post to the queue.
    timeout: (optional) amount of time to wait before repeating put request.
  """
  put_success = False
  while not put_success:
    try:
      queue.put(msg, timeout=timeout)
      put_success = True
    except Queue.Full:
      pass

# pylint: enable=invalid-name


import subprocess

branch_labels = [	'v2','v3','v4','v5','v6','v7','v8',
									'v9','v10','v11','v12','v13','v14',
									'v15','v16','v17','v18','v19'
								]

for ele in branch_labels:
	git_command = 'git checkout -b {}'.format(ele)
	p = subprocess.Popen(git_command, shell=True, stdout=subprocess.PIPE)
p.wait()


#!/usr/bin/env python
# -*- coding: utf-8 -*-
import numpy as np
import sys
import pandas as pd
import config

def word2id(content_data, label_data):
    '''content_data的word2id'''
    word_list = []
    for idx, sentence in enumerate(content_data):
        for word in sentence:
            if word not in word_list:
                word_list.append(word)
    ids = range(len(word_list))
    word2id = pd.Series(ids, index=word_list).to_dict()
    for sentence_idx, sentence in enumerate(content_data):
        for word_idx, word in enumerate(sentence):
            if word in word2id.keys():
                content_data[sentence_idx][word_idx] = word2id[word] + 1
    '''label_data的word2id'''
    label_list = []
    for idx, sentence in enumerate(label_data):
        for word in sentence:
            if word not in label_list:
                label_list.append(word)
    ids = range(len(label_list))
    label2id = pd.Series(ids, index=label_list).to_dict()
    for sentence_idx, sentence in enumerate(label_data):
        for word_idx, word in enumerate(sentence):
            if word in label2id.keys():
                #之后需添加开始/结尾标识，分别为1和2
                label_data[sentence_idx][word_idx] = label2id[word] + 1
    return content_data, label_data

def data_prepare():
    content_data = np.load(r'C:\Users\lenovo\Desktop\Josie\自学\哥哥的\论文实验_transformer实现多分类\data\symptoms.npy',
                           allow_pickle=True)
    label_data = np.load(r'C:\Users\lenovo\Desktop\Josie\自学\哥哥的\论文实验_transformer实现多分类\data\herbs.npy',
                         allow_pickle=True)
    content_data, label_data = word2id(content_data, label_data)
    def max_len(content_data):
        max_len = 0
        for sentence_idx, sentence in enumerate(content_data):
            if max_len < len(sentence):
                max_len = len(sentence)
        return max_len
    '''用max_len补齐content_data'''
    for sentence in content_data:
        if len(sentence) < max_len(content_data):
            sentence += [0] * (max_len(content_data) - len(sentence))
    '''label_data也不一样长，同理需补齐label_data(begin:1, end:2, 剩余:0)
    算loss值时需是三维[batch_size, max_len, num_dim]'''
    new_label_data = []
    for sentence in label_data:
        #补齐开始/结尾标识
        new_label_data.append([1] + sentence + [2])
    # label_data = new_label_data
    for sentence in label_data:
        if len(sentence) < config.num_category:
            sentence += [0] * (config.num_category - len(sentence))
    return list(content_data), list(label_data)


import argparse
from core.main import Main

def _get_args():
    parser = argparse.ArgumentParser(
        description='Calculates distances between a dataset of audio files',
        formatter_class=argparse.ArgumentDefaultsHelpFormatter
    )
    parser.add_argument("in_path",
                        action="store",
                        help="Name of database")
    args = parser.parse_args()
    return args.in_path

if __name__ == '__main__':
    print('######################################')

    db_name = _get_args()
    if not db_name.endswith('.sqlite'):
        print('Provide a proper database file name. (for eg: db.sqlite)')
    else:
        main_obj = Main(db_name)
        main_obj.calc_feature_new()
        main_obj.show_similarity()


from pbr import version as pbr_version

HSM_VENDOR = "Intel"
HSM_PRODUCT = "Intel"
HSM_PACKAGE = None

loaded = False
version_info = pbr_version.VersionInfo('hsm')
version_string = version_info.version_string


from math import acos, cos, sqrt, pi

def get_l2r_l4(l3, l5, x51, f):
    l4 = trig_arm(l5-l3, l5, x51)
    x41cw = trig_angle(l5-l3, l4, l5)
    x41ccw = 180 - x41cw
    l4b = f*l4
    l4a = l4 - l4b
    l2r = trig_arm(l3, l4b, x41ccw)
    return l2r, l4, l4a, l4b

def trig_angle(a, b, c):
    return rad_to_deg(acos((a ** 2 + b ** 2 - c ** 2) / (2 * a * b)))

def trig_arm(a, b, C):
    C = deg_to_rad(C)
    return sqrt(a ** 2 + b ** 2 - 2 * a * b * cos(C))

def rad_to_deg(x):
    return (180 * x) / pi

def deg_to_rad(x):
    return (pi * x) / 180

class DumpLift:
    def __init__(self, l1, l2, l3, l4a, l4b, l5):
        self.l1 = l1
        self.l2 = l2
        self.l3 = l3
        self.l4a = l4a
        self.l4b = l4b
        self.l5 = l5
        self.l4 = l4a + l4b

        # intermediate vars
        self._a43 = trig_angle(self.l3, self.l4b, self.l2)
        self._l7 = trig_arm(self.l3, self.l4, self._a43)
        self._a51 = trig_angle(self.l1, self.l5, self._l7)
        self._a57 = trig_angle(self.l5, self._l7, self.l1)
        self._a47 = trig_angle(self.l4, self._l7, self.l3)
        self._a54 = self._a57 - self._a47
        self._l8 = trig_arm(self.l5, self.l4, self._a54)
        self._a23 = trig_angle(self.l2, self.l3, self.l4b)

        # calculate angles in radians
        self.a3 = trig_angle(self.l1, self.l3, self._l8)
        self.a2 = self._a23 + self.a3
        self.a4 = (180 - self._a43) + self.a3
        self.a5 = 180 - self._a51

    def angles_deg(self):
        return [self.a2, self.a3, self.a4, self.a5]

    def print_all(self):
        r = [self._l7, self._l8]
        r2 = [self._a23, self._a43, self._a51, self._a54, self._a57, self._a47]
        for i in r:
            print(f"{i:.2f}")
        for i in r2:
            print(f"{i:.2f}")
        for i in self.angles_deg():
            print(f"{i:.2f}")


def extractChaleuriaCom(item):
	'''
	Parser for 'chaleuria.com'
	'''

	vol, chp, frag, postfix = extractVolChapterFragmentPostfix(item['title'])
	if not (chp or vol) or "preview" in item['title'].lower():
		return None

	tagmap = [
		('TLCPS',       'The Long Chase for the President’s Spouse',                      'translated'),
		('UTDS',        'Urban Tales of Demons and Spirits',                              'translated'),
		('RIAH',        'Reborn into a Hamster for 233 Days',                             'translated'),
		('rdf',         'Records of the Dragon Follower',                                 'translated'),
		('RDF',         'Records of the Dragon Follower',                                 'translated'),
		('nmd',         'No Money to Divorce',                                            'translated'),
		('ipc',         'Interstellar Power Couple',                                      'translated'),
		('fs',          'Fake Slackers',                                                  'translated'),
		('aol',         'World Hopping: Avenge Our Love',                                 'translated'),
		('DITA',        'Deep in the Act',                                                'translated'),
		('CGPA',        'The Complete Guide to the Use and Care of a Personal Assistant', 'translated'),
		('RDE',         'Rest in a Demon\'s Embrace',                                     'oel'),
	]

	for tagname, name, tl_type in tagmap:
		if tagname in item['tags']:
			return buildReleaseMessageWithType(item, name, vol, chp, frag=frag, postfix=postfix, tl_type=tl_type)

	return False


from django.shortcuts import render, redirect
from .forms import MyRegisterForm
from django.contrib import messages
from .models import RegisterForm

# Create your views here.
def home(request):
    newdata = RegisterForm.objects.all()
    if (newdata != ''):
        return render(request,"home.html", {'data':newdata})
    else:
        return render(request, 'home.html')

def register(request):
    if request.method == 'POST':
        form = MyRegisterForm(request.POST)
        if form.is_valid():
            try:
                form.save()
                messages.success(request,'Registration completed successfully!')
                return redirect ("home")
            except:
                pass
    else:
        form = MyRegisterForm()
    return render(request, "register.html", {'form':form})

def update(request, id):
    data = RegisterForm.objects.get(id =id)
    if request.method == 'POST':
        name = request.POST['name']
        age = request.POST['age']
        event = request.POST['event']
        contact = request.POST['contact']
        email = request.POST['email']

        data.Name = name
        data.Age = age
        data.Event_Name = event
        data.Contact_Number = contact
        data.Email_ID = email
        data.save()
        messages.success(request,'Registration updated successfully!')
        return redirect('home')

    return render(request, "update.html", {'data':data})

def delete(request, id):
    data = RegisterForm.objects.get(id =id)
    data.delete()
    messages.error(request,'Deleted the record successfully!')
    return redirect('home')