"""Contains tests which reveal broken behavior in QGIS.

.. note:: This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
"""
__author__ = 'Nyall Dawson'
__date__ = '10/08/2022'
__copyright__ = 'Copyright 2022, The QGIS Project'

import os
import shutil
import tempfile

from qgis.PyQt.QtCore import QT_VERSION, QEventLoop, QLocale
from qgis.PyQt.QtGui import QValidator
from qgis.core import QgsDataCollectionItem, QgsLayerItem, QgsVectorLayer
from qgis.gui import QgsFieldValidator
import unittest
from qgis.testing import start_app, QgisTestCase

from utilities import unitTestDataPath

app = start_app()
TEST_DATA_DIR = unitTestDataPath()

class PyQgsLayerItem(QgsLayerItem):

    def __del__(self):
        self.tabSetDestroyedFlag[0] = True

class PyQgsDataConnectionItem(QgsDataCollectionItem):

    def createChildren(self):
        children = []

        # Add a Python object as child
        pyQgsLayerItem = PyQgsLayerItem(None, "name", "", "uri", QgsLayerItem.Vector, "my_provider")
        pyQgsLayerItem.tabSetDestroyedFlag = self.tabSetDestroyedFlag
        children.append(pyQgsLayerItem)

        # Add a C++ object as child
        children.append(QgsLayerItem(None, "name2", "", "uri", QgsLayerItem.Vector, "my_provider"))

        return children

"""
This file contains tests which reveal actual broken behavior in QGIS, where the fix for the
underlying issue is unknown or non-trivial.

(It is not designed for broken *tests*, only for working tests which show broken behavior and
accordingly can't be run on the CI)

DO NOT ADD TESTS TO THIS FILE WITHOUT A DETAILED EXPLANATION ON WHY!!!!
"""

class TestQgsDisabledTests(QgisTestCase):

    @classmethod
    def setUpClass(cls):
        """Run before all tests."""
        super().setUpClass()
        testPath = TEST_DATA_DIR + '/' + 'bug_17878.gpkg'
        # Copy it
        tempdir = tempfile.mkdtemp()
        testPathCopy = os.path.join(tempdir, 'bug_17878.gpkg')
        shutil.copy(testPath, testPathCopy)
        cls.vl = QgsVectorLayer(testPathCopy + '|layername=bug_17878', "test_data", "ogr")
        assert cls.vl.isValid()

    @classmethod
    def tearDownClass(cls):
        """Run after all tests."""
        cls.vl = None
        super().tearDownClass()

    @unittest.skipIf(QT_VERSION >= 0x050d00, 'Crashes on newer Qt/PyQt versions')
    def testPythonCreateChildrenCalledFromCplusplus(self):
        """
        test createChildren() method implemented in Python, called from C++

        This test was originally working under Qt 5.12, but is broken on newer Qt or sip
        versions. The test currently segfaults, as the children created by the python QgsDataCollectionItem
        subclass PyQgsDataConnectionItem are immediately garbage collected.

        The SIP SIP_VIRTUAL_CATCHER_CODE in qgsdataitem.h is supposed to fix this situation by
        adding an extra reference to the returned python objects, but the lines

          // pyItem is given an extra reference which is removed when the C++ instance’s destructor is called.
          sipTransferTo( pyItem, Py_None );

        no longer have any effect and the object is still immediately deleted.

        Attempted solutions include:
        - all combinations of the existing VirtualCatcherCode with the different Factory/TransferBack annotations
        - removing the VirtualCatcherCode and replacing with raw Factory/TransferBack annotations
        - disabling the python garbage collection of the object entirely with sipTransferTo( pyItem, NULL )

        When fixed this test should be moved back to test_qgsdataitem.py
        """

        loop = QEventLoop()
        NUM_ITERS = 10  # set more to detect memory leaks
        for i in range(NUM_ITERS):
            tabSetDestroyedFlag = [False]

            item = PyQgsDataConnectionItem(None, "name", "", "my_provider")
            item.tabSetDestroyedFlag = tabSetDestroyedFlag

            # Causes PyQgsDataConnectionItem.createChildren() to be called
            item.populate()

            # wait for populate() to have done its job
            item.stateChanged.connect(loop.quit)
            loop.exec_()

            # Python object PyQgsLayerItem should still be alive
            self.assertFalse(tabSetDestroyedFlag[0])

            children = item.children()
            self.assertEqual(len(children), 2)
            self.assertEqual(children[0].name(), "name")
            self.assertEqual(children[1].name(), "name2")

            del children

            # Delete the object and make sure all deferred deletions are processed
            item.destroyed.connect(loop.quit)
            item.deleteLater()
            loop.exec_()

            # Check that the PyQgsLayerItem Python object is now destroyed
            self.assertTrue(tabSetDestroyedFlag[0])
            tabSetDestroyedFlag[0] = False

    def _fld_checker(self, field):
        """
        Expected results from validate
        QValidator::Invalid 0 The string is clearly invalid.
        QValidator::Intermediate 1 The string is a plausible intermediate value.
        QValidator::Acceptable 2 The string is acceptable as a final result; i.e. it is valid.
        """
        validator = QgsFieldValidator(None, field, '0.0', '')

        def _test(value, expected):
            ret = validator.validate(value, 0)
            self.assertEqual(ret[0], expected)
            if value:
                self.assertEqual(validator.validate('-' + value, 0)[0], expected, '-' + value)

        # Valid
        _test('0.1234', QValidator.Acceptable)

        # If precision is > 0, regexp validator is used (and it does not support sci notation)
        if field.precision() == 0:
            _test('12345.1234e+123', QValidator.Acceptable)
            _test('12345.1234e-123', QValidator.Acceptable)

    @unittest.skipIf(QT_VERSION >= 0x050d00, 'Fails newer Qt/PyQt versions')
    def test_doubleValidatorCommaLocale(self):
        """Test the double with german locale

        On newer Qt versions QDoubleValidator with comma as decimal locales now
        reports the Intermediate state for values like 0.1234, but we require
        it to report Acceptable as we always allow dot as decimal separator even
        for these locales.

        The underling fix will likely require a refactor of QgsFieldValidator to remove
        the use of the QDoubleValidator class entirely.

        When fixed these tests should be merged back into test_qgsfieldvalidator.py
        """
        QLocale.setDefault(QLocale(QLocale.German, QLocale.Germany))
        self.assertEqual(QLocale().decimalPoint(), ',')
        field = self.vl.fields()[self.vl.fields().indexFromName('double_field')]
        self._fld_checker(field)

if __name__ == '__main__':
    unittest.main()


#!/usr/bin/env python3
# -*- coding: utf-8 -*-

# @Time：2020/5/30 16:35
# @Email: am1122@163.com
# @Author: 'Nemo'

from parsercases import ParserCases
import PySimpleGUI as sg
from case2excel import Case2Excel
import os
from config import ConfigParser, BASE_DIR
from case2zentao import case2zentao

base_dir = os.path.dirname(os.path.abspath(__file__))

default_template = os.path.join(BASE_DIR, 'template.xlsx')

# 模板选择
# 选择xmind文件
# 选择存放位置，默认与 xmind 在同一目录，且后缀名改为 xmind
TIPS = {
    'save_file': '如果不选择则会直接保存在xmind所在目录',
    'r1': '方案1：默认为5级，第一级为模块，最后三级分别为用例标题、步骤和结果',
    'r2': '方案2：使用定义的关键字识别用例，比如"tc:登录失败"，\n\t使用tc作为标识，会识别该节点为测试用例\n\t后面分别为用例、步骤和结果',
    'r3': '方案3：使用定义的关键字作为用例的前置，比如"cases"，\n\t则认为该节点下的所有节点都是用例',
    'trans': '自动保存为 .xlsx 文件',
    'zentao': '自动保存为 .csv 文件',
    'encoding': '如果CSV出现乱码，则修改编码格式，一般为utf-8或GBK，一种不行就换一种咯！',
    'template_text': '通过这里的关键字去识别模板中的用例，比如会根据“标题”去寻找用例标题',
}

# [sg.Radio('My first Radio!', "RADIO1", default=True),
#     sg.Radio('My second radio!', "RADIO1")]
CASE_CONFIG = ConfigParser.get_config(section='cases')
FIELD = ConfigParser.get_config('field', 'template')

case_column = [
    # [sg.T('用例识别方式：')],
    [sg.Radio('默认方案', group_id='case_mark', key='_MARK1_', tooltip=TIPS.get('r1'), enable_events=True)],
    [
        sg.Radio('关键字识别', group_id='case_mark', key='_MARK2_', tooltip=TIPS.get('r2'), enable_events=True),
        sg.In(key='_MARK2STR_', size=(10,))
    ],
    [
        sg.Radio('前置关键字', group_id='case_mark', key='_MARK3_', tooltip=TIPS.get('r3'), enable_events=True),
        sg.In(key='_MARK3STR_', size=(10,))
    ],
]

# field_column = [
#     [sg.T('模板字段设置：', tooltip=TIPS.get('template_text'))],
#     [sg.T('所属模块'), sg.I(default_text=FIELD.get('module'), key='_FIELD_MODULE_')],
#     [sg.T('用例标题'), sg.I(default_text=FIELD.get('test_title'), key='_FIELD_TITLE_')],
#     [sg.T('前置条件'), sg.I(default_text=FIELD.get('preset'), key='_FIELD_PRESET_')],
#     [sg.T('操作步骤'), sg.I(default_text=FIELD.get('test_step'), key='_FIELD_STEP_')],
#     [sg.T('预期结果'), sg.I(default_text=FIELD.get('test_result'), key='_FIELD_RESULT_')],
#     [sg.T('优先级'), sg.I(default_text=FIELD.get('priority'), key='_FIELD_PRIORITY_')],
#     [sg.T('用例类型'), sg.I(default_text=FIELD.get('category'), key='_FIELD_CATEGORY_')],
#     [sg.T('适用阶段'), sg.I(default_text=FIELD.get('stage'), key='_FIELD_STAGE_')],
# ]

config_frame = [
    # [sg.Column(case_column), sg.VerticalSeparator(), sg.Column(field_column)],
    # [sg.Frame('用例识别方式', case_column)],
    [sg.T('_'*60)],
    [sg.T('当没有写步骤或预期结果时，是否直接使用用例标题填充'), sg.Checkbox('', default=False, key='_FILL_')],
    [sg.T('用例字体大小：'), sg.In(key='_FONT_SIZE_', default_text=ConfigParser.get_config('font_size', 'style'), size=(5,))],
    [sg.T('csv 编码：', tooltip=TIPS.get('encoding')), sg.In(key='_CODING_', size=(5, ), default_text=ConfigParser.get_config('encoding', 'sys'))],
    [sg.B('保存配置', key='_SAVE_CONFIG_')]
]

layout = [
    [sg.Frame('配置', case_column + config_frame)],
    [sg.T()],
    [sg.In(key='_TEMPLATE_', default_text=default_template), sg.FileBrowse('选择模板')],
    [sg.In(key='_XMIND_FILE_', enable_events=True), sg.FileBrowse('选择Xmind文件', key='_SELECT_XMIND_', file_types=(('Xmind', '*.xmind'),), initial_folder=base_dir)],
    [sg.In(key='_CASE_FILE_', enable_events=True), sg.FileSaveAs('选择用例保存位置', file_types=(('Excel', '*.xlsx'),), tooltip=TIPS.get('save_file'))],
    [sg.B('转化', key='_TRANSLATE_', tooltip=TIPS.get('trans')), sg.B('转化为禅道CSV文件', key='_TO_ZENTAO_FILE_', tooltip=TIPS.get('zentao'))]
]

window = sg.Window('xmind2excel用例转化', layout=layout, finalize=True).finalize()

while True:
    # 处理配置
    if CASE_CONFIG['mark'] == 1:
        window['_MARK1_'].update(value=True)
    elif CASE_CONFIG['mark'] == 2:
        window['_MARK2_'].update(value=True)
        try:
            window['_MARK3STR_'].update(value='', disabled=True)
            window['_MARK2STR_'].update(value=CASE_CONFIG.get('mark_2_string'))
        except:
            pass
    elif CASE_CONFIG['mark'] == 3:
        window['_MARK3_'].update(value=True)
        try:
            window['_MARK2STR_'].update(value='', disabled=True)
            window['_MARK3STR_'].update(value=CASE_CONFIG.get('mark_3_key'))
        except:
            pass
    if CASE_CONFIG['no_step_or_result_fill_by_case_title']:
        window['_FILL_'].update(value=True)

    # 读取窗口事件
    event, value = window.Read()

    if event == '_MARK1_':
        window['_MARK2STR_'].update(value='', disabled=True)
        window['_MARK3STR_'].update(value='', disabled=True)
        event, value = window.Read()

    elif event == '_MARK2_':
        window['_MARK2_'].update(value=True)
        window['_MARK2STR_'].update(disabled=False, value=CASE_CONFIG.get('mark_2_string'))
        window['_MARK3STR_'].update(value='', disabled=True)
        event, value = window.Read()

    elif event == '_MARK3_':
        window['_MARK3_'].update(value=True)
        window['_MARK3STR_'].update(disabled=False, value=CASE_CONFIG.get('mark_3_key'))
        window['_MARK2STR_'].update(value='', disabled=True)
        event, value = window.Read()

    if event == '_TEMPLATE_':
        event, value = window.Read()

    # 配置保存
    if event == '_SAVE_CONFIG_':
        try:
            if value['_MARK1_']:
                # 写入配置
                ConfigParser.set_config('mark', 1, 'cases')
            elif value['_MARK2_']:
                ConfigParser.set_config('mark', 2, 'cases')
                ConfigParser.set_config('mark_2_string', value['_MARK2STR_'], 'cases')
            elif value['_MARK3_']:
                ConfigParser.set_config('mark', 3, 'cases')
            ConfigParser.set_config('no_step_or_result_fill_by_case_title', value['_FILL_'], 'cases')
            ConfigParser.set_config('font_size', int(value['_FONT_SIZE_']), 'style')
            ConfigParser.set_config('encoding', value['_CODING_'], 'sys')
        except Exception as e:
            sg.popup(e)
        else:
            sg.popup('配置保存成功！')
        event, value =  window.Read()

    # 将生成后的路径与xmind文件在同一路径，并将后缀名修改为xlsx
    if event == '_XMIND_FILE_':
        window['_CASE_FILE_'].update(value=os.path.splitext(value['_XMIND_FILE_'])[0])
        event, value = window.Read()

    # 由于选择excel保存路径时可能会忘记输入后缀名，自动加上.xlsx后缀
    if event == '_CASE_FILE_':
        case_file = value['_CASE_FILE_']
        if os.path.splitext(case_file)[-1] not in ['xlsx', 'xls']:
            case_file = case_file + '.xlsx'
            window['_CASE_FILE_'].update(value=case_file)
        event, value = window.Read()

    # 当点击转化按钮时，获取文件路径，并调用核心代码进行转化
    if event == '_TRANSLATE_':
        template = value['_TEMPLATE_']
        xmind_file = value['_XMIND_FILE_']
        case_file = value['_CASE_FILE_'] + '.xlsx'

        if not template:
            sg.popup('请选择模板文件!')

        elif not xmind_file or not xmind_file.endswith('.xmind'):
            sg.popup('您没有选择xmind文件或文件格式有误!')

        else:
            if not case_file:
                sg.popup('您没有选择用例保存位置，将默认保存在xmind所在的文件夹!')
                case_file = os.path.splitext(xmind_file)[0] + '.xlsx'
                event, value = window.Read()
            xc = ParserCases(xmind_file)
            if xc.msg:
                sg.popup('选择的xmind格式有问题，请检查文件！')
                event, value = window.Read()
            ce = Case2Excel(template, case_file)
            try:
                ce.write_case_to_excel(xc.all_map_case)
            except Exception as e:
                sg.popup('转化出现错误：\n' + str(e))
            else:
                sg.popup('用例生成成功，请前往 {} 查看！'.format(case_file))
                # event, value = window.Read()
        event, value = window.Read()

    if event == '_TO_ZENTAO_FILE_':
        xmind_file = value['_XMIND_FILE_']
        case_file = value['_CASE_FILE_'] + '.csv'

        if not xmind_file or not xmind_file.endswith('.xmind'):
            sg.popup('您没有选择xmind文件或文件格式有误!')
        else:
            if not case_file:
                sg.popup('您没有选择用例保存位置，将默认保存在xmind所在的文件夹!')
                case_file = os.path.splitext(xmind_file)[0] + '.csv'
                event, value = window.Read()
            xc = ParserCases(xmind_file)
            if xc.msg:
                sg.popup('选择的xmind格式有问题，请检查文件！')
                event, value = window.Read()
            try:
                case2zentao(case_file, xc.all_map_case)
            except Exception as e:
                sg.popup('转化出现错误：\n' + str(e))
            else:
                sg.popup('用例生成成功，请前往 {} 查看！'.format(case_file))
        event, value = window.Read()

    if event is None:
        break

window.close()


import numpy as np
from scipy.stats import moyal
import matplotlib.pyplot as plt

x25 = np.linspace(25, 400, int(400/25))
x833 = np.linspace(8.33, 400, int(400/8.33))
x1 = np.linspace(1, 400, 400)

def searchPk(x, y):
    tmp = 0
    pk = 0
    for i in range(len(x)):
        tmp = y[i]
        if tmp > pk:
            pk = tmp
    return pk

def getArea(x, y):
    summ = 0
    for i in range(len(x)):
        summ += y[i]
    return summ

pulses = np.loadtxt("rmdpulses.dat", float)

xtime = pulses.T[0]
yampl = pulses.T[1]

# =======================
# *** Plotting pulses ***
'''
plt.figure(figsize=(16,9))

plt.plot(xtime, yampl, 'o')

plt.ylabel("Amplitude [mV]", fontsize=24)
plt.yticks(fontsize=22)
plt.xlabel("time [ns]", fontsize=24)
plt.xticks(fontsize=22)

plt.tight_layout()
#plt.savefig("../plots/artifitialPulses.png", dpi=100)
plt.show()
'''

sglpulse210 = []
sglpulse212 = []
mv2fadc210 = 1.95 #mV
mv2fadc212 = 0.49 #mV

bintime = [i for i in range(40000)]

tmpbin25 = 0.
tmpcnt = 0

for np in range( int(yampl.size/4e4) ):
  tmp = []
  tmpbin25 = 25.
  for t in bintime:
    if t == int(tmpbin25*1e2):
      tmp.append( int(yampl[tmpcnt]/mv2fadc210) )
      tmpbin25 += 25.
    tmpcnt += 1
  sglpulse210.append( tmp )

tmpbin833 = 0.
tmpcnt = 0
for np in range( int(yampl.size/4e4) ):
  tmp = []
  tmpbin833 = 8.33
  for t in bintime:
    if t == int(1e2*tmpbin833):
      tmp.append( int(yampl[tmpcnt]/mv2fadc212) )
      tmpbin833 += 8.33
    tmpcnt += 1
  sglpulse212.append( tmp )

import numpy as np
pkhist25 = np.zeros(200, int)
pkhist833 = np.zeros(200, int)

chhist25 = np.zeros(400, int)
chhist833 = np.zeros(400, int)

factorCh25 = 25./50.
factorCh833 = 8.33/50.

for i in range(len(sglpulse210)):
  pkhist25[ int(mv2fadc210*searchPk(x25[:-1], sglpulse210[i])) ] += 1
  chhist25[ int((mv2fadc210*factorCh25)*getArea(x25[:-1], sglpulse210[i])) ] += 1

for i in range(len(sglpulse212)):
  pkhist833[ int(mv2fadc212*searchPk(x833[:-1], sglpulse212[i])) ] += 1
  chhist833[ int((mv2fadc212*factorCh833)*getArea(x833[:-1], sglpulse212[i])) ] += 1

plt.figure(figsize=(16,9))

plt.plot(pkhist25, 's', ms=12, label="Peak for Sample/25 ns")
plt.plot(pkhist833, '^', ms=12, label="Peak for Sample/8.33 ns")

plt.legend(fontsize=24)
plt.ylabel("Counts [au]", fontsize=24)
plt.yticks(fontsize=22)
plt.xlabel("Amplitude [mV]", fontsize=24)
plt.xticks(fontsize=22)
plt.xlim(50,80)

plt.tight_layout()
plt.savefig("../plots/samplingDigiPkHistos.png", dpi=100)
#plt.show()

plt.figure(figsize=(16,9))

plt.plot(chhist25, 's', ms=12, label="Charge for Sample/25 ns")
plt.plot(chhist833, '^', ms=12, label="Charge for Sample/8.33 ns")

plt.legend(fontsize=24)
plt.ylabel("Counts [au]", fontsize=24)
plt.yticks(fontsize=22)
plt.xlabel("Charge [pC]", fontsize=24)
plt.xticks(fontsize=22)
plt.xlim(80,140)

plt.tight_layout()
plt.savefig("../plots/samplingDigiChHistos.png", dpi=100)
#plt.show()


import os

import torch

def to_np(x):
    return x.cpu().numpy()

class VisdomLogger(object):
    def __init__(self, id, num_epochs):
        from visdom import Visdom
        self.viz = Visdom()
        self.opts = dict(title=id, ylabel='', xlabel='Epoch', legend=['Loss', 'WER', 'CER'])
        self.viz_window = None
        self.epochs = torch.arange(1, num_epochs + 1)
        self.visdom_plotter = True

    def update(self, epoch, values):
        x_axis = self.epochs[0:epoch + 1]
        y_axis = torch.stack((values.loss_results[:epoch],
                              values.wer_results[:epoch],
                              values.cer_results[:epoch]),
                             dim=1)
        self.viz_window = self.viz.line(
            X=x_axis,
            Y=y_axis,
            opts=self.opts,
            win=self.viz_window,
            update='replace' if self.viz_window else None
        )

    def load_previous_values(self, start_epoch, results_state):
        self.update(start_epoch - 1, results_state)  # Add all values except the iteration we're starting from

class TensorBoardLogger(object):
    def __init__(self, id, log_dir, log_params):
        os.makedirs(log_dir, exist_ok=True)
        from torch.utils.tensorboard import SummaryWriter
        self.id = id
        self.tensorboard_writer = SummaryWriter(log_dir)
        self.log_params = log_params

    def update(self, epoch, results_state, parameters=None):
        loss = results_state.loss_results[epoch]
        wer = results_state.wer_results[epoch]
        cer = results_state.cer_results[epoch]
        values = {
            'Avg Train Loss': loss,
            'Avg WER': wer,
            'Avg CER': cer
        }
        self.tensorboard_writer.add_scalars(self.id, values, epoch + 1)
        if self.log_params:
            for tag, value in parameters():
                tag = tag.replace('.', '/')
                self.tensorboard_writer.add_histogram(tag, to_np(value), epoch + 1)
                self.tensorboard_writer.add_histogram(tag + '/grad', to_np(value.grad), epoch + 1)

    def load_previous_values(self, start_epoch, result_state):
        loss_results = result_state.loss_results[:start_epoch]
        wer_results = result_state.wer_results[:start_epoch]
        cer_results = result_state.cer_results[:start_epoch]

        for i in range(start_epoch):
            values = {
                'Avg Train Loss': loss_results[i],
                'Avg WER': wer_results[i],
                'Avg CER': cer_results[i]
            }
            self.tensorboard_writer.add_scalars(self.id, values, i + 1)


#!/usr/bin/env python

import sys
from xml.etree import ElementTree as ET
import json
import re
import datetime

class DestFileCreator:
    nextTrip = 1

    def __init__(self, firstTrip):
        self.nextTrip = firstTrip

    def next_dest(self, data_file):
        newName = "Trip" + str(self.nextTrip).zfill(3) + "-" + data_file
        self.nextTrip = self.nextTrip + 1
        print(f"Starting {newName}")
        return open(newName, "w")

def get_next_file(trace_file):
    numbers_str = re.findall(r'[0-9]+', trace_file)

    numbers_int = map(int, numbers_str)

    oldFile = datetime.datetime(numbers_int[0], numbers_int[1], numbers_int[2], numbers_int[3])

    dtime = datetime.timedelta(hours=1)

    oldFile = oldFile + dtime

    filename = str(oldFile.date())
    filename += "-"
    if(oldFile.hour < 10):
        filename += "0"
    filename += str(oldFile.hour)
    filename += ".json"

    return filename

def read_trace_file(dataFileValid, destFileGen, destinationFile, trace_file, currentTraceFile):
    lastTimeStamp = 0.0
    currentTimeStamp = 0
    errorCount = 0
    lineCount = 0

    for line in currentTraceFile:
        try:
            lineCount = lineCount + 1
            timestamp, data = line.split(':', 1)
            record = json.loads(data)
        except ValueError:
            sys.stderr.write("Skipping line: %s" % data)
            print(" ")
            errorCount = errorCount + 1
            continue

        if lastTimeStamp is not 0.0:
            if (float(timestamp) - lastTimeStamp) > 600.00:  # Time is in seconds
                print(f"Found a gap of {float(timestamp) - lastTimeStamp} seconds. Creating new Trip file.")
                destinationFile.close()
                lastTimeStamp = 0.0
                destinationFile = destFileGen.next_dest(trace_file)
            elif (float(timestamp) - lastTimeStamp) > 1.00:  # Time is in seconds
                print(f"Momentary dropout of {float(timestamp) - lastTimeStamp} seconds. Ignoring.")
        lastTimeStamp = float(timestamp)
        destinationFile.write(line)

    if dataFileValid is True:
        currentTraceFile.close()
        trace_file = get_next_file(trace_file)

    percentBad = 100.0 * errorCount / lineCount
    print(f"Parsed {lineCount} lines.")

    print(f"Detected {errorCount} errors.")

    print(f"{percentBad}% bad data")

def compile_trip(trace_file, tripNum):
    dataFileValid = True
    destFileGen = DestFileCreator(tripNum)

    destinationFile = destFileGen.next_dest(trace_file)

    while dataFileValid is True:
        try:
            currentTraceFile = open(trace_file, "r")
        except IOError as e:
            print(e)
            dataFileValid = False
            destinationFile.close()
            break
        else:
            print(f'Opened {trace_file}')
            read_trace_file(dataFileValid, destFileGen, destinationFile, trace_file, currentTraceFile)

if __name__ == '__main__':
    if len(sys.argv) is not 3:
        print("Must provide the path to the first trace file in a trip and the trip number.")
        sys.exit(1)

    compile_trip(sys.argv[1], int(sys.argv[2]))


import argparse, os

from mpi4py import MPI

from skopi.radiationDamage import *
import skopi.util as su

def main():
    """
    Main function to implement the master-slave model for parallel execution.

    :return:
    """

    parameters = parse_input()

    # Initialize MPI
    comm = MPI.COMM_WORLD
    rank = comm.Get_rank()
    # Initialize time
    start = time.time()
    if rank == 0:
        master_diffract(comm, parameters)
    else:
        slave_diffract(comm, parameters)

    comm.Barrier()  # Barrier synchronization

    if rank == 0:
        end = time.time()
        print('Finished: ', end - start, ' seconds.')

def master_diffract(comm, parameters):
    """
    Master node. Get the diffraction patterns with mpi

    :param comm: MPI comm
    :param parameters: dictionary of command line arguments
    :return:
    """
    pmi_start_id = int(parameters['pmiStartID'])
    pmi_end_id = int(parameters['pmiEndID'])
    num_dp = int(parameters['numDP'])

    # Number of processes
    num_process = comm.Get_size()
    ntasks = (pmi_end_id - pmi_start_id + 1) * num_dp

    if num_process == 1:
        rotation_axis = parameters['rotationAxis']
        uniform_rotation = parameters['uniformRotation']
        my_quaternion = generate_rotations(uniform_rotation, rotation_axis, ntasks)
        output_name = parameters['outputDir'] + '/diffr_out_0000001.h5'
        if os.path.exists(output_name):
            os.remove(output_name)
        su.prep_h5(output_name)
        for ntask in range(ntasks):
            make_one_diffr(my_quaternion, ntask, parameters, output_name)
    else:
        for ntask in range(ntasks):
            status = MPI.Status()
            # Waiting for messages from slave
            # Successful message reciving means slave is ready for simulation
            comm.recv(source=MPI.ANY_SOURCE, tag=1, status=status)
            rnk = status.Get_source()
            # Trigger calculation on slave.
            comm.send(ntask, dest=rnk)

    # Final send: stop all processes from waiting for tasks
    for process in range(1, num_process):
        comm.send(-1, dest=process)

def slave_diffract(comm, parameters):
    """
    Slave node. Get the diffraction patterns with mpi

    :param comm: MPI comm
    :param parameters: dictionary of command line arguments
    :return:
    """
    pmi_start_id = int(parameters['pmiStartID'])
    pmi_end_id = int(parameters['pmiEndID'])
    num_dp = int(parameters['numDP'])
    ntasks = (pmi_end_id - pmi_start_id + 1) * num_dp
    rotation_axis = parameters['rotationAxis']
    uniform_rotation = parameters['uniformRotation']
    my_quaternion = generate_rotations(uniform_rotation, rotation_axis, ntasks)

    # Setup output file
    output_name = parameters['outputDir'] + '/diffr_out_' + '{0:07}'.format(comm.Get_rank()) + '.h5'
    if os.path.exists(output_name):
        os.remove(output_name)
    su.prep_h5(output_name)

    # Init a local counter
    counter = 0
    # Wave to master, we're good to go.
    comm.send(counter, dest=0, tag=1)
    # Start event loop and generate the diffraction images.
    while True:
        counter = comm.recv(source=0)
        if counter < 0:
            # end of simulation
            return None
        make_one_diffr(my_quaternion, counter, parameters, output_name)
        # Show master we're ready for another task
        comm.send(counter, dest=0, tag=1)

def parse_input():
    """
    Parse the input command arguments and return a dict containing all simulation parameters.

    :return parameters: dictionary of command-line arguments
    """

    # Instantiate the parser
    parser = argparse.ArgumentParser()
    parser.add_argument('--inputDir', help='Input directory for finding /pmi and /diffr')
    parser.add_argument('--outputDir', help='Output directory for saving diffraction')
    parser.add_argument('--beamFile', help='Beam file defining X-ray beam')
    parser.add_argument('--geomFile', help='Geometry file defining diffraction geometry')
    parser.add_argument('--rotationAxis', default='xyz', help='Preferred axis of rotation or xyz if none')
    parser.add_argument('--uniformRotation', type=parse_boolean,
                        help='If 1, rotates the sample uniformly in SO(3),\
                                if 0 random orientation in SO(3),\
                                if None (omitted): no orientation.')
    parser.add_argument('--calculateCompton', type=parse_boolean, default=False,
                        help='If 1, includes Compton scattering in the diffraction pattern')
    parser.add_argument('--sliceInterval', type=int, help='Calculates photon field at every slice interval')
    parser.add_argument('--numSlices', type=int,
                        help='Number of time-slices to use from Photon Matter Interaction (PMI) file')
    parser.add_argument('--pmiStartID', type=int, help='First Photon Matter Interaction (PMI) file ID to use')
    parser.add_argument('--pmiEndID', type=int, help='Last Photon Matter Interaction (PMI) file ID to use')
    parser.add_argument('--numDP', type=int, help='Number of diffraction patterns per PMI file')

    # convert argparse to dict
    return vars(parser.parse_args())

def parse_boolean(b):
    """
    Handle different possible Boolean types.

    :param b:
    :return:
    """
    if b is None:
        return b
    if b is False or b is True:
        return b
    b = b.strip()
    if len(b) < 1:
        raise ValueError('Cannot parse empty string into boolean.')
    b = b[0].lower()
    if b == 't' or b == 'y' or b == '1':
        return True
    if b == 'f' or b == 'n' or b == '0':
        return False
    raise ValueError('Cannot parse string into boolean.')

if __name__ == '__main__':
    main()


from django.urls import path
from usuarios import views

app_name = 'usuarios'
urlpatterns = [
    path('', views.login_view, name='login'),
    path('process/', views.process_login, name='process'),
    path('e/lp/', views.eval_loged, name='success_login_eval'),
    path('e/eval/', views.evaluaciones_evaluador, name='evaluaciones_evaluador'),
    path('a/lp/', views.landingpage, name='landing'), #Landing page de administrador
    path('a/ev/', views.evaluadores),  # Evaluadores visto por admin
    path('a/ev/delete/', views.delete_evaluador),
    path('a/ev/modify/', views.modify_evaluador),
    path('a/eval/delete/', views.deleteEvaluacion),
    path('a/eval/create/', views.createEvaluacion),
    path('a/eval/modify/', views.modifyEvaluacion),
    path('a/eval/', views.evaluaciones),  # Lista de evaluaciones de admin
    path('a/rub/', views.rubricas),  # Rubricas vistas por el admin

]


from mongoengine import *
from incontrol.models import *
from incontrol.app_environment import *
import datetime
connect('in_control')

def populate_database():
	u1 = User(name="Liu Zheng")
	u1.save()

	idea1 = Idea(title='The first idea gave birth to this InControl program', users=[u1, ])
	idea1.content = """
	The development will have 3 stages. First, we build up the database and write
	some tool functions and scripts for command-line usage.
	Second, we think about writing an API server for this. Third, we wrap up
	everything into mobile apps and webpages.
	"""
	idea1.status = 'W'
	idea1.save()

	r1 = Reminder(title="things to do in this weekend", users=[u1, ])
	r1.content="""
	1. Learn beautiful soup and write a crawler and the `parse_logs` function.
	2. Finish watching the NLP Lecture 2.
	3. Read the spec.
	"""
	r1.deadline = datetime.datetime.strptime('2018-09-23T20:00:00', "%Y-%m-%dT%H:%M:%S")
	r1.save()

	p1 = Project(users=[u1, ])
	p1.title = "InControl task management system"
	p1.content = """
	Write a program managing tasks in a logical way.
	This project has 3 stages:
	1. Build up the data model and develop some tool functions and command-line scripts.
	2. After some usage and polishment, start to build an API.
	3. Consider wrapping it up to a webpage or a mobile app.
	"""
	p1.save()

# Project.list_properties()

# populate_database()

u1 = User.objects.first()
app = AppEnvironment(u1)
print(app.current_user)
projects = app.query_tasks(Project)
print("projects:", projects)
current_task = projects[0]
print("current_task:", current_task)

# # # test sprawn_subtask function
# # -------------------------------
# p11 = current_task.sprawn_subtask(Idea)
# p11.title = 'Implement the `parse_logs` and `parse_content` functions'
# p11.content = "Thinks about whether to put these functions and decide whether to use JSON or XML."
# p11.save()

# # # test create_log function, and began to use the functions to create something great
# # -------------------------------------------------------------------------------------
# log1 = current_task.create_log(u1)
# log1.title = "Created 'create_log` function, among others."
# log1.content = "N.A."
# log1.save()

# p12 = current_task.sprawn_subtask(Project)
# p12.title = "Build a mapping between list items and numbers"
# p12.content = """
# For command-line usage, since each query returns a list of
# objects, we should automatically build a mapping between numbers
# and objects.

# Add "Choose task", "switch user", "choose log", etc will help users
# to choose things to work on and switch between one and another.

# This should be added into `AppEnvironment` class. The class should not
# only take 'current_user', but 'current_task', 'current_log', etc.
# 'list_*' methods should show all * objects with an index in front of each
# object, and one can use `switch_*` method to choose the corresponding object.
# """
# p12.deadline = datetime.datetime.utcnow() + datetime.timedelta(hours=5)
# p12.save()

# p13 = current_task.sprawn_subtask(Project)
# p13.title = "Add 'switch_to_parent_task' method"
# p13.deadline = datetime.datetime.utcnow() + datetime.timedelta(hours=5)
# p13.save()

# # # create sub-tasks and logs using the AppEnvironment object
# # ------------------------------------------------------------

# u1 = User.objects.first()
# app = AppEnvironment(u1, "/Users/zheng/.incontrol")
# projects = app.list_main_tasks(Project)
# print(projects)

# app.switch_task(projects[0])
# print(app.current_task.title)
# tasks = app.list_subtasks(Project)
# print(tasks)
# app.switch_task(tasks[1])
# print(app.current_task.title)
# app.switch_to_parent_task()
# print(app.current_task.title)
# 后面就开发显示层，把get到的信息格式化显示。

# # add log
# log_list = app.list_logs()
# print(log_list)
# log1 = app.create_log()
# log1.title = "method added"
# log1.content = "`switch_to_parent_task` added. Now task switching functionality is almost done."
# log1.save()

# log_list = app.list_logs()
# print(log_list)

# app.current_task.update_status('DONE')
# print(app.current_task.status)
# app.switch_to_parent_task()
# subtask = app.create_subtask(task_cls=Idea, switch_to_it=True, users=None)
# print(app.current_task.title)
# print(app.previous_task.title)


import matplotlib.pyplot as plt
import scipy.optimize as opt
import pandas as pd
import seaborn as sns
from sklearn.cluster import KMeans
import sklearn.cluster as cluster
import sklearn.metrics as skmet
import numpy as np

col = [0, 1, 34, 44, 54, 63]

def exp_growth(t, scale, growth):
    """ Computes exponential function with scale and growth as free parameters
    """
    f = scale * np.exp(growth * (t-1950))
    return f

def norm(array):
    """ Returns array normalised to [0,1]."""
    min_val = np.min(array)
    max_val = np.max(array)
    scaled = (array-min_val) / (max_val-min_val)
    return scaled

def norm_df(df, first=0, last=None):
    """
        Returns all columns of the dataframe normalised to [0,1] with the
        exception of the first (containing the names)
        Calls function norm to do the normalisation of one column, but
        doing all in one function is also fine.
        First, last: columns from first to last (including) are normalised.
        Defaulted to all. None is the empty entry. The default corresponds"""
# iterate over all numerical columns
    for col in df.columns[first:last]:  # excluding the first column
        df[col] = norm(df[col])
    return df

# reading the file and data pre-processing
df_GDP = pd.read_csv("agri.csv")
data_GDP = df_GDP.drop(
    columns=["Country Code", "Indicator Name", "Indicator Code"])
data_GDP = data_GDP.replace(np.nan, 0)
countries = ["India", "Colombia", "Japan"]
data_GDP = data_GDP["Country Name"].isin(countries)
data_GDP = df_GDP[data_GDP]
data_GDP = data_GDP.drop(
    columns={"Country Name", "Country Code", "Indicator Name", "Indicator Code"})
GDP_tr = np.transpose(data_GDP)
GDP_tr = GDP_tr.reset_index()
GDP_tr = GDP_tr.rename(columns={"index": "year"})
GDP_tr = GDP_tr.rename(columns={109: "INDIA", 45: "COLOMBIA", 119: "JAPAN"})
GDP_tr = GDP_tr.dropna()
GDP_tr["JAPAN"] = pd.to_numeric(GDP_tr["JAPAN"])
GDP_tr["INDIA"] = pd.to_numeric(GDP_tr["INDIA"])
GDP_tr["year"] = pd.to_numeric(GDP_tr["year"])

# fit exponential growth
popt, covar = opt.curve_fit(exp_growth, GDP_tr["year"], GDP_tr["JAPAN"])

print("Fit parameter", popt)
# use *popt to pass on the fit parameters
GDP_tr["pop_exp"] = exp_growth(GDP_tr["year"], *popt)
plt.figure()
plt.plot(GDP_tr["year"], GDP_tr["JAPAN"], label="data")
plt.plot(GDP_tr["year"], GDP_tr["pop_exp"], label="fit")
plt.legend()
plt.title("Fit")
plt.xlabel("year")
plt.ylabel("Agriculture methane emmision")
plt.show()

# growth of 0.02 gives a reasonable start value
popt = [4e8, 0.01]
GDP_tr["pop_exp"] = exp_growth(GDP_tr["year"], *popt)
plt.figure()
plt.plot(GDP_tr["year"], GDP_tr["JAPAN"], label="data")
plt.plot(GDP_tr["year"], GDP_tr["JAPAN"], label="fit")
plt.legend()
plt.xlabel("year")
plt.ylabel("Agriculture methane emmision")
plt.title("Improved")
plt.show()

# # fit exponential growth
popt, covar = opt.curve_fit(
    exp_growth, GDP_tr["year"], GDP_tr["JAPAN"], p0=[4e8, 0.02])
# # much better
print("Fit parameter", popt)
GDP_tr["pop_exp"] = exp_growth(GDP_tr["year"], *popt)
plt.figure()
plt.plot(GDP_tr["year"], GDP_tr["JAPAN"], label="data")
plt.plot(GDP_tr["year"], GDP_tr["pop_exp"], label="fit")
plt.legend()
plt.xlabel("year")
plt.ylabel("Agriculture methane emission")
plt.title("Graph showing exponential fit")
plt.savefig('exponential.png', bbox_inches="tight", dpi=300)
plt.show()
print()

print(GDP_tr.describe())

pd.plotting.scatter_matrix(GDP_tr, figsize=(9.0, 9.0))
#to avoid overlap of labels
plt.tight_layout()
plt.show()

# extract columns for fitting
df_fit = GDP_tr[["INDIA", "JAPAN"]].copy()
# normalise dataframe and inspect result
# normalisation is done only on the extract columns. .copy() prevents
# changes in df_fit to affect df_fish. This make the plots with the
# original measurements
df_fit = norm_df(df_fit)
print(df_fit.describe())
print()

for ic in range(2, 7):
    # set up kmeans and fit
    kmeans = cluster.KMeans(n_clusters=ic)
    kmeans.fit(df_fit)

# extract labels and calculate silhoutte score
labels = kmeans.labels_
print(ic, skmet.silhouette_score(df_fit, labels))

# Plot for 6 clusters
kmeans = cluster.KMeans(n_clusters=6)
kmeans.fit(df_fit)
# extract labels and cluster centres
labels = kmeans.labels_
cen = kmeans.cluster_centers_
plt.figure(figsize=(6.0, 6.0))
plt.scatter(df_fit["INDIA"], df_fit["JAPAN"], c=labels, cmap="Accent")
# colour map Accent selected to increase contrast between colours
# show cluster centres
for j in range(4):
    cx, cy = cen[j, :]
    plt.plot(cx, cy, "dk", markersize=10)

plt.xlabel("country")
plt.ylabel("y")
plt.title("6 clusters")
plt.savefig('6 cluster.png', bbox_inches="tight", dpi=300)
plt.show()
#-----------------------

# Plot for five clusters
kmeans = cluster.KMeans(n_clusters=5)
kmeans.fit(df_fit)
# extract labels and cluster centres
labels = kmeans.labels_
cen = kmeans.cluster_centers_
plt.figure(figsize=(6.0, 6.0))
plt.scatter(df_fit["INDIA"], df_fit["JAPAN"], c=labels, cmap="Accent")
# colour map Accent selected to increase contrast between colours
# show cluster centres
for i in range(5):
    cx, cy = cen[i, :]

plt.plot(cx, cy, "dk", markersize=10)
plt.xlabel("country")
plt.ylabel("y")
plt.title("5 clusters")
plt.savefig('5 cluster.png', bbox_inches="tight", dpi=300)
plt.show()


import collections

# external
from lxml import etree

# relative
from . import errors, utils, xmlconst, results
from .options import DEFAULT_UPDATE_OPTIONS

# Constants
TAG_VOCAB_REFERENCE = "vocab_reference"
TAG_VOCAB_NAME = 'vocab_name'

class Vocab(object):
    """Controlled Vocabulary update class. This is used on conjunction with a
    dictionary which maps found controlled vocabulary instance names to _Vocab
    implementation classes.

    Attributes:
        VOCAB_NAMESPACE: The namespace which contains the controlled vocabulary
            definition.
        OLD_TYPES: A tuple of XSD type names which when discovered will be
            upgraded.
        NEW_TYPE: The XSD type name for the updated controlled vocabulary
        VOCAB_REFERENCE: The ``vocab_reference`` xml attribute text.
        VOCAB_NAME: The ``vocab_name`` xml attribute text.
        TERMS (dict): A dictionary of vocabulary term mappings. This is useful
            for typo corrections between controlled vocabulary revisions.

    """
    VOCAB_NAMESPACE = None
    OLD_TYPES = ()
    NEW_TYPE = None
    VOCAB_REFERENCE = None
    VOCAB_NAME = None
    TERMS = {}

    @classmethod
    def find(cls, root, typed=None):
        """Finds and returns a list of nodes that are instances of old
        controlled vocabularies.

        """
        if typed is None:
            typed = utils.get_typed_nodes(root)

        found = []
        for node in typed:
            _, typename = utils.get_type_info(node)
            ext_ns = utils.get_ext_namespace(node)

            if ext_ns != cls.VOCAB_NAMESPACE:
                continue
            elif typename not in cls.OLD_TYPES:
                continue
            else:
                found.append(node)

        return found

    @classmethod
    def update(cls, root, typed=None):
        """Updates controlled vocabularies found under the `root` document.

        This performs the following updates:
        * Updates ``xsi:type`` attribute to refer to the new type name.
        * Updates terms to align with new vocabulary in the case of typo fixes.
        * Updates ``vocab_name`` attribute value if present.
        * Updates ``vocab_reference`` attribute value if present.

        """
        if typed is None:
            typed = utils.get_typed_nodes(root)

        vocabs = cls.find(root, typed)

        for node in vocabs:
            alias, _ = utils.get_type_info(node)

            attribs    = node.attrib
            terms      = cls.TERMS
            new_type   = cls.NEW_TYPE
            vocab_ref  = cls.VOCAB_REFERENCE
            vocab_name = cls.VOCAB_NAME

            # Update the xsi:type attribute to identify the new
            # controlled vocabulary
            new_xsi_type = "%s:%s" % (alias, new_type)
            attribs[xmlconst.TAG_XSI_TYPE] = new_xsi_type

            # Update the vocab_reference attribute if present
            if TAG_VOCAB_REFERENCE in attribs:
                attribs[TAG_VOCAB_REFERENCE] = vocab_ref

            # Update the vocab_name attribute if present
            if TAG_VOCAB_NAME in attribs:
                attribs[TAG_VOCAB_NAME] = vocab_name

            # Update the node value if there is a new value in the updated
            # controlled vocabulary
            value = node.text
            if value in terms:
                node.text = terms[value]

class TranslatableField(object):
    """Helper class for translating field instances between versions of a
    language specifications.

    Note:
        The methods defined here may not (likely will not) apply to every
        translation scenario. As such, it is encouraged to override any/all
        of these methods for specific translation requirements.

    Attributes:
        NSMAP: A dictionary of namespace aliases => namespaces used in xpaths
            and type lookups.
        XPATH_NODE: An xpath which locates instances of the field to be
            translated.
        XPATH_VALUE: An xpath to be applied to the nodes discovered via
            `XPATH_NODE` which extracts the value.
        NEW_TAG: The etree tag for the translated field.
        COPY_ATTRIBUTES (boolean): If true, attributes are copied from the node
            discovered by `XPATH_VALUE` to the translated field.
        OVERRIDE_ATTRIBUTES (dict): A dictionary of attribute names => value to
            override during the translation. This will only update existing
            attributes--not add them.

    """
    NSMAP = None
    XPATH_NODE = None
    XPATH_VALUE = '.'
    NEW_TAG = None
    COPY_ATTRIBUTES = False
    OVERRIDE_ATTRIBUTES = {}

    @classmethod
    def _translate_value(cls, old, new):
        xpath, nsmap = cls.XPATH_VALUE, cls.NSMAP
        if xpath:
            value = old.xpath(xpath, namespaces=nsmap)[0]
            new.text = value.text
        else:
            # Used when the fields are the same data type, just different names
            new[:] = old[:]  # TODO: verify that namespaces don't get messed up here

    @classmethod
    def _translate_attributes(cls, old, new):
        """Copies attributes from `old` to `new` (discovered by `XPATH_VALUE`
        or the `old` node ``text`` value).

        If `COPY_ATTRIBUTES` is set to ``True``, attributes from the `old` node
        value are copied to `new`. If an attribute is found that matches a key
        in `OVERRIDE_ATTRIBUTES`, its value is overridden by the value found in
        `OVERRIDE_ATTRIBUTES`.

        """
        xpath, nsmap = cls.XPATH_VALUE, cls.NSMAP

        if xpath:
            source = old.xpath(xpath, namespaces=nsmap)[0]
        else:
            source = old

        if cls.COPY_ATTRIBUTES:
            new.attrib.update(source.attrib)

        for name, val in cls.OVERRIDE_ATTRIBUTES.iteritems():
            if name not in source.attrib:
                continue
            new.attrib[name] = val

    @classmethod
    def _translate_fields(cls, node):
        """Translates values and attributes from `node` to a new XML
        element.

        Returns:
            A translated ``etree._Element``.
        """
        tag = cls.NEW_TAG or node.tag
        new = etree.Element(tag)

        cls._translate_value(node, new)
        cls._translate_attributes(node, new)

        return new

    @classmethod
    def _find(cls, root):
        """Discovers translatable fields in the `root` document.

        Returns:
            A list of nodes discovered via the `XPATH_NODE` xpath.

        """
        return root.xpath(cls.XPATH_NODE, namespaces=cls.NSMAP)

    @classmethod
    def translate(cls, root):
        """Translates and replaces nodes found in `root` with new nodes.

        """
        nodes = cls._find(root)

        for node in nodes:
            new_node = cls._translate_fields(node)
            utils.replace_xml_element(node, new_node)

class RenamedField(TranslatableField):
    """Extension to ``_TranslatableField`` that only performs a renaming
    operation on discovered nodes.

    Note:
        The name of the node is defined by the `NEW_TAG` class-level attribute.

    """
    @classmethod
    def translate(cls, root):
        nodes = cls._find(root)

        for node in nodes:
            node.tag = cls.NEW_TAG

class DisallowedFields(object):
    """Helper class used to discover untranslatable fields within an XML
    instance document.

    Attributes:
        CTX_TYPES: A dictionary of xsi:type contexts to look for or within. If
            CTX_TYPES is ``None`` or empty, the root node is used as the
            context for xpaths.
        XPATH: An xpath used to discover nodes under the contexts determined
            by `CTX_TYPES`. By default, `XPATH` is ``'.'``, meaning the
            context nodes are returned by the `XPATH` by default.
        NSMAP: A dictionary of namespace aliases => namespaces. Used for xpath
            evaluation.

    """
    CTX_TYPES = {}
    XPATH = "."
    NSMAP = {}

    def __init__(self,):
        pass

    @classmethod
    def _interrogate(cls, nodes):
        """Overriden by implemmentation classes if a set of requirments must
        be evaluated before a node is considered untranslatable.

        For example, the `_interrogate()` method could only consider a node
        untranslatable if it has more than one child node.

        Args:
            nodes: A list of nodes to interrogate for untranslatable
                properties.

        Returns:
            A list of untranslatable nodes. By default, this method does not
            perform any inspection of `nodes` and only returns `nodes`.

        """
        return nodes

    @classmethod
    def _get_contexts(cls, root, typed=None):
        """Returns context nodes under `root` discovered by `CTX_TYPES`.

        If `CTX_TYPES` is ``None`` or empty, The entire `root` node is
        considered to be the context for the class-level `XPATH`.

        Args:
            root: The root node for an XML instance document.
            typed: xsi:typed nodes to search through when looking for
                context nodes. If ``None``, the entire `root` document will be
                searched for xsi:typed nodes that match the names and namespaces
                declared by `CTX_TYPES`. This is provided to speed up
                context node discovery.

        Returns:
            A list of context nodes for `XPATH` to be evaluated against.

        """
        ctx = cls.CTX_TYPES

        if not ctx:
            return (root,)

        if typed is None:
            typed = utils.get_typed_nodes(root)

        contexts = []
        for node in typed:
            type_ = utils.get_type_info(node)[1]
            ns = utils.get_ext_namespace(node)

            if ctx.get(type_) == ns:
                contexts.append(node)

        return contexts

    @classmethod
    def find(cls, root, typed=None):
        """Finds disallowed (untranslatable) fields under the `root` node.

        Returns:
            A list of disallowed or untranslatable nodes.

        """
        contexts = cls._get_contexts(root, typed)
        xpath, nsmap = cls.XPATH, cls.NSMAP

        found = []
        for ctx in contexts:
            nodes = ctx.xpath(xpath, namespaces=nsmap)
            interrogated = cls._interrogate(nodes)
            found.extend(interrogated)

        return found

class OptionalAttributes(DisallowedFields):
    """Helper class for discovering empty, optional attributes.

    There are cases where one revision of STIX/CybOX required the presence
    of an attribute which became optional in later revisions. This enables the
    discovery of these attributes which may be present in the input document
    only for schema-validation reasons.

    Attributes:
        ATTRIBUTES: A tuple of attribute tags to look for.

    """
    ATTRIBUTES = ()

    def __init__(self):
        super(OptionalAttributes, self).__init__()

    @classmethod
    def _interrogate(cls, nodes):
        """Inspects each node in `nodes` for the presence of empty attributes
        defined in `ATTRIBUTES`.

        Note:
            This overrides the `_interrogate()` method implemented in
            ``_DisallowedFields``.

        Returns:
            A list of nodes containing empty attributes defined in `ATTRIBUTES`.

        """
        contraband = []
        attrs = cls.ATTRIBUTES

        def is_empty(node, attr):
            if attr in node.attrib:
                val = node.attrib[attr]
                return len(val) == 0
            else:
                return False

        for node in nodes:
            if not any(is_empty(node, x) for x in attrs):
                continue
            contraband.append(node)

        return contraband

class OptionalElements(DisallowedFields):
    """Helper class for discovering empty, optional elements.

    There are cases where one revision of STIX/CybOX required the presence
    of an element which became optional in later revisions. This enables the
    discovery of elements which may be present in the input document only for
    the sake of schema-validation.

    """
    def __init__(self):
        super(OptionalElements, self).__init__()

    @classmethod
    def _is_empty(cls, node):
        """Returns ``False`` if `node` or any of its descendants contain
        attributes or text values.

        """
        nodes = node.iter('*')
        content = any(x.attrib or utils.strip_whitespace(x.text) for x in nodes)
        return content is False

    @classmethod
    def _interrogate(cls, nodes):
        """Checks if any of the nodes in `nodes` are empty.

        Note:
            A node is considered to be emtpy if it has no attributes, no text
            value, and no children with content (attribs or text content).
            These criterion may be overridden by implementations of this class.

        Returns:
            A list of nodes that are empty.

        """
        return [x for x in nodes if cls._is_empty(x)]

class BaseUpdater(object):
    """The base class for all STIX and CybOX updater code.

    Attributes:
        VERSION: Specifies the base langauge version for an updater
            implementation. For example, a STIX v1.0 updater would use '1.0'.
        NSMAP: A dictionary of namespace aliases => namespaces for a given
            language version. This is used for xpath evaluation and xsi:type
            lookup.
        DISALLOWED_NAMESPACES: A tuple of namespaces which cannot be translated
            during the update process. These namespaces will be stripped and
            not appear in the export document.
        UPDATE_NS_MAP: A dictionary of namespaces that are updated between
            language revisions. For example, CybOX 2.1 defines a new namespace
            for the Windows Driver Object. This dictionary would contain the
            old namespace as a key, and the new namespace as a value.
        UPDATE_SCHEMALOC_MAP: A dictionary of language namespaces to their
            updated schemalocations. If a namespace has been updated between
            langauge revisions, the new namespace will be used as the key (as
            is in the case of the CybOX 2.0.1 updater and the Windows Driver
            Object namespace).
        DEFAULT_VOCAB_NAMESPACE: The namespace for the default vocabulary
            schema.
        UPDATE_VOCABS: A tuple of ``_Vocab`` derivations
        XPATH_VERSIONED_NODES: An xpath which discovers all versioned nodes
            that need to be updated within the source document.
        XPATH_ROOT_NODES: An xpath which discovers all "root" nodes
            (implementations of ``STIXType and ObservablesType``) which may
            contain document-level version information.
        DISALLOWED: An iterable collection of DisallowedFields instances.
        OPTIONAL_ELEMENTS: An iterable collection of OptionalElements
            instances.
        OPTIONAL_ATTRIBUTES: An iterable collection of OptionalAttributes
            instances.
        TRANSLATABLE_FIELDS: An iterable collection of TranslatableField
            instances.
        cleaned_fields: A tuple of untranslatable nodes which were removed
            during a forced `update` or `clean` process.
        cleaned_ids: A dictionary of id => [nodes] which contains a list of
            nodes which have had their originally non-unique ids remapped to
            unique ids. This is only populated in a forced `update` or
            `clean` process.

    """
    # OVERRIDE THESE IN IMPLEMENTATIONS
    VERSION = None
    DISALLOWED_NAMESPACES = ()
    NSMAP = {}
    UPDATE_NS_MAP = {}
    UPDATE_SCHEMALOC_MAP = {}

    # Controlled Vocabularies
    DEFAULT_VOCAB_NAMESPACE = None
    UPDATE_VOCABS = ()

    XPATH_VERSIONED_NODES = "."
    XPATH_ROOT_NODES = "."

    DISALLOWED = ()
    OPTIONAL_ELEMENTS = ()
    OPTIONAL_ATTRIBUTES = ()
    TRANSLATABLE_FIELDS = ()

    def _is_leaf(self, node):
        """Returns ``True`` if the `node` has no children."""
        return len(node.xpath(xmlconst.XPATH_RELATIVE_CHILDREN)) == 0

    def _get_ns_alias(self, root, ns):
        """Returns the XML Namespace alias defined for a namespace in a given
        instance document.

        Args:
            root (lxml.etree._Element): The instance document root node.
            ns (string): A namespace in the instance document

        Returns:
            A string namespace alias for the given ``ns`` namespace. If the
            namespace is not found in the ``root`` instance document, ``None``
            is returned.

        """
        return root.nsmap.get(ns)

    def _get_duplicates(self, root):
        """This checks `root` for nodes with duplicate IDs.

        Returns:
            A dictionary where the ID is the key and the values are lists of
            lxml._Element nodes.

        """
        namespaces = self.NSMAP.values()
        id_nodes = collections.defaultdict(list)

        for desc in utils.iterdescendants(root):
            if 'id' not in desc.attrib:
                continue

            ns = utils.get_namespace(desc)

            if ns not in namespaces:
                continue

            id_ = desc.attrib['id']
            id_nodes[id_].append(desc)

        filtered = {}
        for id_, nodes in id_nodes.iteritems():
            if len(nodes) > 1:
                filtered[id_] = nodes

        return filtered

    def _get_versioned_nodes(self, root):
        """Discovers all versioned nodes under `root` defined by the class-level
        `XPATH_VERSIONED_NODES` xpath.

        Args:
            root: The root node to search under.

        Returns:
            A list of nodes discovered by evaluating the class-level
            `XPATH_VERSIONED_NODES` xpath.

        """
        xpath = self.XPATH_VERSIONED_NODES
        namespaces = self.NSMAP
        return root.xpath(xpath, namespaces=namespaces)

    def _get_root_nodes(self, root):
        """Discovers all versioned nodes under `root` defined by the class-level
        `XPATH_ROOT_NODES` xpath. This is used primarily when trying to
        determine the language version of the input document.

        Args:
            root: The root node to search under.

        Returns:
            A list of nodes discovered by evaluating the class-level
            `XPATH_ROOT_NODES` xpath.

        """
        xpath = self.XPATH_ROOT_NODES
        namespaces = self.NSMAP
        return root.xpath(xpath, namespaces=namespaces)

    def _check_version(self, root):
        """Checks that the version of the document matches the expected
        version. Derived classes need to implement this method.

        Note:
            This must be implemented by derived classes.

        Raises:
            NotImplementedError: If a derived class does not implement this
                method.

        """
        raise NotImplementedError()

    def _update_vocabs(self, root):
        """Updates controlled vocabularies found under the `root` document.

        This performs the following updates:
        * Updates ``xsi:type`` attribute to refer to the new type name.
        * Updates terms to align with new vocabulary in the case of typo fixes.
        * Updates ``vocab_name`` attribute value if present.
        * Updates ``vocab_reference`` attribute value if present.

        Vocabulary updates are dictated by the `UPDATE_VOCABS` class-level
        attribute.

        """

        typed_nodes = utils.get_typed_nodes(root)

        for vocab in self.UPDATE_VOCABS:
            vocab.update(root, typed=typed_nodes)

    def _remove_schemalocations(self, root):
        """Removes the ``xsi:schemaLocation`` attribute from `root`."""
        utils.remove_xml_attribute(root, xmlconst.TAG_SCHEMALOCATION)

    def _create_schemaloc_str(self, pairs):
        """Creates a valid ``xsi:schemaLocation`` string from the `pairs`
        list of ``(namespace, schemalocation)`` tuples.

        Args:
            pairs: list of tuples containing (ns, schemaloc).

        Returns:
            An ``xsi:schemaLocation`` value string.

        """
        schemaloc_str = "   ".join("%s %s" % (ns, loc) for ns, loc in pairs)
        return schemaloc_str

    def _clean_schemalocs(self, pairs):
        """Returns a list of ``(namespace, schemalocation)`` tuples that are
        allowed for the updated document.

        Args:
            pairs: a list of (namespace, schemalocation) tuples.

        Note:
            If a namespaces that exist in `DISALLOWED_NAMESPACES` will not be
            found in the return value.

        """
        disallowed = self.DISALLOWED_NAMESPACES
        return [(ns, loc) for ns, loc in pairs if ns not in disallowed]

    def _remap_schemalocs(self, pairs):
        """Updates the ``xsi:schemaLocation`` value to use namespaces and
        schemalocations for the next langauge revision.

        Args:
            pairs: A list of (namespace, schemalocation) tuples.

        Returns:
            A list of updated (namespace, schemalocation) tuples.

        """
        remapped = []

        for ns, loc in pairs:
            updated_ns  = self.UPDATE_NS_MAP.get(ns, ns)
            updated_loc = self.UPDATE_SCHEMALOC_MAP.get(updated_ns, loc)
            remapped.append((updated_ns, updated_loc))

        return remapped

    def _update_schemalocs(self, root):
        """Updates the schemalocations found on `root` to point to
        the schemalocations for the next language version.

        The new schemalocations are defined by the ``UPDATE_SCHEMALOC_MAP``
        class-level attribute.

        Args:
            root (lxml.etree._Element): The top-level xml node.

        """
        if xmlconst.TAG_SCHEMALOCATION not in root.attrib:
            return

        schemalocs = utils.get_schemaloc_pairs(root)
        cleaned = self._clean_schemalocs(schemalocs)
        remapped = self._remap_schemalocs(cleaned)
        updated = self._create_schemaloc_str(remapped)

        root.attrib[xmlconst.TAG_SCHEMALOCATION] = updated

    def _apply_namespace_updates(self, root):
        """Updates the children of `root` to be defined under their updated
        namespace.

        This uses the `UPDATE_NS_MAP` attribute to look up and assign
        an updated namespace to a node.

        If this isn't done, the node will retain its old namespace and receive
        a new `ns0` namespace alias.

        """
        for node in utils.iterdescendants(root):
            node_ns = utils.get_namespace(node)
            updated_ns = self.UPDATE_NS_MAP.get(node_ns, node_ns)
            node.tag = node.tag.replace(node_ns, updated_ns)

    def _remap_namespaces(self, node):
        """Remaps the namespaces found on the input `node` to namespaces
        defined by the ``UPDATE_NS_MAP``. If a namespace for a disallowed
        field/type is discovered, it is removed.

        Note:
            Disallowed namespaces are defined by the ``DISALLOWED_NAMESPACES``
            class-level attribute.

        Args:
            node (lxml.etree._Element): An ``etree`` XML node..

        Returns:
            A dictionary of aliases to namespaces.

        """
        remapped = {}
        for alias, ns in node.nsmap.iteritems():
            if ns in self.DISALLOWED_NAMESPACES:
                continue

            remapped[alias] = self.UPDATE_NS_MAP.get(ns, ns)

        return remapped

    def _get_remapped_tag(self, node):
        """Returns a new tag for `node` which includes an updated namespace
        portion of the tag. This is determined by looking up the tag
        namespace in the ``UPDATE_NS_MAP`` class dictionary.

        Returns:
            A new tag for `node` which contains an updated namespace.

        """
        namespace = utils.get_namespace(node)
        localname = utils.get_localname(node)
        updated_ns = self.UPDATE_NS_MAP.get(namespace, namespace)

        return "{%s}%s" % (updated_ns, localname)

    def _update_tag(self, node):
        """Updates the tag for `node` which a tag that includes an updated
        namespace. This is driven by the ``UPDATE_NS_MAP`` class attribute.

        Returns:
            `node` with an updated tag that includes a new namespace if the
            original namespace existed in ``UPDATE_NS_MAP``.

        """
        node.tag = self._get_remapped_tag(node)
        return node

    def _update_nsmap(self, node):
        """Updates the ``nsmap`` attribute found on `node` to `nsmap`.

        The lxml API does not allow in-place modification of the ``nsmap``
        dictionary. Instead, a copy of the node must be created and initialized
        with an updated ``nsmap`` attribute.

        Args:
            node (lxml.etree._Element): An XML element
            nsmap: A ``namspace alias => namespace`` dictionary.

        Returns:
            A copy of `root` with its ``nsmap`` attribute set to `nsmap`.

        """
        tag = self._get_remapped_tag(node)
        updated_nsmap = self._remap_namespaces(node)
        new  = etree.Element(tag, nsmap=updated_nsmap)
        new.attrib.update(node.attrib)
        new.text  = utils.get_node_text(node)
        new[:] = node[:]

        return new

    def _update_namespaces(self, node):
        """Updates the namespaces in the instance `node` to align with
        with the updated schema. This will also remove any disallowed
        namespaces if found in the instance document.

        Note:
            Only nodes that exist within the namespaces defined by
            the ``NS_MAP`` class attribute will be updated.

        Note:
            The lxml library does not allow you to modify the ``nsmap``
            attribute of an ``_Element`` directly. To modify the ``nsmap``,
            A copy of `root` must be made with a new initial ``nsmap``.

        Returns:
            A copy of the `node` with an updated ``nsmap`` attribute. Each
            of its descendants which belong to known namespaces are updated
            as well.

            If `node` is not an ``etree._Element`` (e.g, a comment node),
            or it does not belong to any namespace defined in the class-level
            ``NSMAP``, then this function returns `node` itself.

        """
        ns = utils.get_namespace(node)
        namespaces = self.NSMAP.itervalues()

        if ns not in namespaces:
            return node

        for child in utils.children(node):
            self._update_namespaces(child)

        new_node = self._update_nsmap(node)
        utils.replace_xml_element(node, new_node)
        return new_node

    def _create_update_results(self, root, remapped=None, removed=None):
        """Creates and returns a :class:`UpdateResults` object instance
        from the input `root` parameter, and the class instance attributes
        ``cleaned_ids`` and ``cleaned_fields``.

        Args:
            root: An instance of ``etree._Element`` or ``etree._ElementTree``.

        Returns:
            An instance of ``ramrod.UpdateResults``.

        """
        update_results = results.UpdateResults(root)
        update_results.remapped_ids = remapped or ()
        update_results.removed = removed or {}

        return update_results

    def _get_disallowed(self, root, options):
        raise NotImplementedError()

    def _clean_disallowed(self, disallowed, options):
        raise NotImplementedError()

    def _clean_duplicates(self, duplicates, options):
        raise NotImplementedError()

    def _clean(self, root, options):
        """Internal handler for public ``clean()`` method. Orchestrates the
        invocation of sub-cleaning methods (e.g., ``_clean_disallowed()``).

        """
        options = options or DEFAULT_UPDATE_OPTIONS
        disallowed = self._get_disallowed(root, options=options)
        duplicates = self._get_duplicates(root)
        remapped, removed = {}, ()

        if duplicates:
            remapped = self._clean_duplicates(duplicates, options=options)

        if disallowed:
            removed = self._clean_disallowed(disallowed, options=options)

        result = results.UpdateResults(root)
        result.remapped_ids = remapped
        result.removed = tuple(removed)

        return result

    def clean(self, root, options=None):
        """Removes disallowed elements from `root` and remaps non-unique
        IDs to unique IDs for the sake of schema-validation.

        Removed items can be retrieved via the ``removed`` attribute on the
        return value:

        >>> results = updater.clean(root)
        >>> print results.removed
        (<Element at 0xffdcf234>, <Element at 0xffdcf284>)

        Items which have been reassigned IDs can be retrieved via the
        ``remapped_ids`` attribute on the return value:

        >>> results = updater.clean(root)
        >>> print results.remapped_ids
        {'example:Observable-duplicate': [<Element {http://cybox.mitre.org...

        Note:
            This does not remap ``idref`` attributes to new ID values because
            it is impossible to determine which entity the ``idref`` was
            pointing to.

        Args:
            root: The XML document. This can be a filename, a file-like object,
                an instance of ``etree._Element`` or an instance of
                ``etree._ElementTree``.
            options (optional): A :class:`ramrod.UpdateOptions` instance. If
                ``None``,  ``ramrod.DEFAULT_UPDATE_OPTIONS`` will be used.

        Returns:
            An instance of
            :class:`ramrod.UpdateResults`.

        """
        root = utils.get_etree_root(root, make_copy=True)
        results = self._clean(root, options)
        return results

    def check_update(self, root, options=None):
        """Checks to see if the `root` document can be updated.

        Note:
            This needs to be overidden by an implementation class.

        Raises:
            NotImplementedError: If this is called directly from _BaseUpdater.

        """
        raise NotImplementedError()

    def _force_update(self, root, options):
        """Removes untranslatable fields from the `root` document and calls
        ``self._update(...)``.

         Returns:
            An instance of ``ramrod.UpdateResults`` for the updated document.

        """
        # Clean the document
        cleaned_results = self._clean(root, options)
        cleaned_doc = cleaned_results.document.as_element()
        remapped = cleaned_results.remapped_ids
        removed = cleaned_results.removed

        # Update the document
        updated = self._update(cleaned_doc, options)
        results = self._create_update_results(
            root=updated,
            remapped=remapped,
            removed=removed
        )

        return results

    def _update(self, root, options):
        """Abstract method that needs to be overriden by concrete base
        classes.

        """
        raise NotImplementedError()

    def update(self, root, options=None, force=False):
        """Attempts to update `root` to the next version of its language
        specification.

        If `force` is set to True, items may be removed during the
        translation process and IDs may be reassigned if they are not
        unique within the document.

        Note:
            This does not remap ``idref`` attributes to new ID values because
            it is impossible to determine which entity the ``idref`` was
            pointing to.

        Removed items can be retrieved via the ``removed`` attribute on the
        return value:

        >>> results = updater.update(root, force=True)
        >>> print results.removed
        (<Element at 0xffdcf234>, <Element at 0xffdcf284>)

        Items which have been reassigned IDs can be retrieved via the
        ``remappped_ids`` attribute on the return value:

        >>> results = updater.update(root, force=True)
        >>> print results.remapped_ids
        {'example:Observable-duplicate-id-1': [<Element {http://cybox.mitre...

        Args:
            root: The XML document. This can be a filename, a file-like object,
                an instance of ``etree._Element`` or an instance of
                ``etree._ElementTree``.
            options: A :class:`ramrod.UpdateOptions` instance. If ``None``,
                ``ramrod.DEFAULT_UPDATE_OPTIONS`` will be used.
            force: Forces the update process to complete by potentially
                removing untranslatable xml nodes and/or remapping non-unique
                IDs. This may result in non-schema=conformant XML. **USE AT
                YOUR OWN RISK!**

        Returns:
            An instance of ``ramrod.UpdateResults``.

        Raises:
            .UpdateError: If untranslatable fields or non-unique IDs are
                discovered in `root` and `force` is ``False``.
            .UnknownVersionError: If the `root` node contains no version
                information.
            .InvalidVersionError: If the `root` node contains invalid
                version information (e.g., the class expects v1.0 content and
                the `root` node contains v1.1 content).

        """
        root = utils.get_etree_root(root, make_copy=True)
        options = options or DEFAULT_UPDATE_OPTIONS

        try:
            self.check_update(root, options)
            updated = self._update(root, options)
            results = self._create_update_results(updated)
        except (errors.UpdateError, errors.UnknownVersionError, errors.InvalidVersionError):
            if force:
                results = self._force_update(root, options)
            else:
                raise

        return results


import pathlib
import cv2 as cv

cascade_path = pathlib.Path(cv.__file__).parent.absolute()/"data/haarcascade_frontalface_default.xml"
print(cascade_path)

classifier = cv.CascadeClassifier(str(cascade_path))

capture  = cv.VideoCapture(1)
# capture = cv.VideoCapture("C:\\Users\\Arqam Nisar\\Downloads\\1.mp4")

while True:
    _, frame = capture.read()
    grayscale = cv.cvtColor(frame, cv.COLOR_BGR2GRAY)

    faces = classifier.detectMultiScale(
        grayscale,
        scaleFactor = 1.1,
        minNeighbors = 7,
        minSize = (30, 30),
        flags = cv.CASCADE_SCALE_IMAGE

    )

    for (x, y, w, h) in faces:
        cv.rectangle(frame, (x, y), (x+w, y+h), (255, 255, 0), 2)

    cv.imshow("Face Detected", frame)
    if cv.waitKey(1) == ord('q'):
        break

capture.release()
cv.destroyAllWindows()


from callsmusic.callsmusic import client as USER
from pyrogram import Client, filters
from pyrogram.types import Message, InlineKeyboardButton, InlineKeyboardMarkup
from pyrogram.errors import UserAlreadyParticipant
from helpers.decorators import errors, authorized_users_only

@Client.on_message(filters.group & filters.command(["joingrp"]))
@authorized_users_only
@errors
async def addchannel(client, message):
    chid = message.chat.id
    try:
        invitelink = await client.export_chat_invite_link(chid)
    except:
        await message.reply_text(
            "tf? Jadiin gw admin dulu tolol! 😄",
        )
        return

    try:
        user = await USER.get_me()
    except:
        user.first_name =  "TG - VC Music Bot" # F this

    try:
        await USER.join_chat(invitelink)
        await USER.send_message(message.chat.id,"Ok! Saya sudah masuk sesuai request mu, jangan spam lagi anjeng! 😂")
    except UserAlreadyParticipant:
        await message.reply_text(
            "Gw sudah ada di group cok! Jangan kaya Bocil 😒",
        )
        pass
    except Exception as e:
        print(e)
        await message.reply_text(
            f"Shit! ❌ Flood Wait Error ❌ \n Sorry! user {user.first_name} Maaf gw gk bisa masuk chat karena banyak yang merintah gw! Jangan sampe gw di ban dari group lu tot. ✅"
            "\n\nOr you can manually add @{(await USER.get_me()).username} to your Group! 😉",
        )
        return
    await message.reply_text(
            "Bot Telah bergabung 😊",
        )

# Remove Bot and Streamer Account From the group
@Client.on_message(filters.group & filters.command(["leavegrp"]))
@authorized_users_only
async def botleavegrp(client, message):
    await message.chat.leave()

@USER.on_message(filters.group & filters.command(["leavegrp"]))
async def strmleavegrp(USER, message):
    try:
        await USER.leave_chat(message.chat.id)
    except:
        await message.reply_text(
            f"Oops! Gw gk bisa keluar dari voice chat banyak yang merintah gw sih 🤔"
            "\n\nAtau kamubisa keluarin gwsecara manual @{(await USER.get_me()).username} 🤗",
        )
        return


from functools import partial

import torch
import torch.nn.functional as F

def _decode(loc, priors, variances):
    """Decode locations from predictions using priors to undo
    the encoding we did for offset regression at train time.
    Args:
        loc (tensor): location predictions for loc layers,
            Shape: [num_priors,4]
        priors (tensor): Prior boxes in center-offset form.
            Shape: [num_priors,4].
        variances: (list[float]) Variances of priorboxes
    Return:
        decoded bounding box predictions
    """

    boxes = torch.cat((
        priors[:, :2] + loc[:, :2] * variances[0] * priors[:, 2:],
        priors[:, 2:] * torch.exp(loc[:, 2:] * variances[1])), 1)
    boxes[:, :2] -= boxes[:, 2:] / 2
    boxes[:, 2:] += boxes[:, :2]
    return boxes

def _soft_nms(boxes, scores, score_threshold, sigma=0.5, top_k=-1):
    """Soft NMS implementation.
    References:
        https://arxiv.org/abs/1704.04503
        https://github.com/facebookresearch/Detectron/blob/master/detectron/utils/cython_nms.pyx
    Args:
        box_scores (N, 5): boxes in corner-form and probabilities.
        score_threshold: boxes with scores less than value are not considered.
        sigma: the parameter in score re-computation.
            scores[i] = scores[i] * exp(-(iou_i)^2 / simga)
        top_k: keep top_k results. If k <= 0, keep all the results.
    Returns:
         picked_box_scores (K, 5): results of NMS.
    """
    picked_box_scores = []
    box_scores = torch.cat((boxes, scores.unsqueeze(-1)), 1)
    while box_scores.size(0) > 0:
        max_score_index = torch.argmax(box_scores[:, 4])
        cur_box_prob = torch.tensor(box_scores[max_score_index, :])
        picked_box_scores.append(cur_box_prob)
        if len(picked_box_scores) == top_k > 0 or box_scores.size(0) == 1:
            break
        cur_box = cur_box_prob[:-1]
        box_scores[max_score_index, :] = box_scores[-1, :]
        box_scores = box_scores[:-1, :]
        ious = iou_of(cur_box.unsqueeze(0), box_scores[:, :-1])
        box_scores[:, -1] = box_scores[:, -1] * torch.exp(-(ious * ious) / sigma)
        box_scores = box_scores[box_scores[:, -1] > score_threshold, :]
    if len(picked_box_scores) > 0:
        box_probs = torch.stack(picked_box_scores)
        return torch.cat([box_probs[..., -1:], box_probs[..., :4]], 1)
    else:
        return torch.tensor([])

def _nms(boxes, scores, overlap=0.5, top_k=200):
    """Apply non-maximum suppression at test time to avoid detecting too many
    overlapping bounding boxes for a given object.
    Args:
        boxes: (tensor) The location preds for the img, Shape: [num_priors,4].
        scores: (tensor) The class predscores for the img, Shape:[num_priors].
        overlap: (float) The overlap thresh for suppressing unnecessary boxes.
        top_k: (int) The Maximum number of box preds to consider.
    Return:
        The indices of the kept boxes with respect to num_priors.
    """

    keep = scores.new(scores.size(0)).zero_().long()
    if boxes.numel() == 0:
        return keep, 0
    x1, y1, x2, y2 = map(lambda x: boxes[:, x], range(4))
    area = torch.mul(x2 - x1, y2 - y1)
    v, idx = scores.sort(0)  # sort in ascending order
    idx = idx[-top_k:]  # indices of the top-k largest vals
    count = 0
    while idx.numel() > 0:
        i = idx[-1]  # index of current largest val
        keep[count] = i
        count += 1
        if idx.size(0) == 1:
            break
        idx = idx[:-1]  # remove kept element from view
        # load bboxes of next highest vals
        xx1, yy1, xx2, yy2 = map(lambda x: torch.index_select(x, 0, idx), (x1, y1, x2, y2))
        # store element-wise max with next highest score
        xx1, yy1 = map(lambda x: torch.clamp(x[0], min=x[1][i]), zip([xx1, yy1], [x1, y1]))
        xx2, yy2 = map(lambda x: torch.clamp(x[0], max=x[1][i]), zip([xx2, yy2], [x2, y2]))
        w = xx2 - xx1
        h = yy2 - yy1
        # check sizes of xx1 and xx2.. after each iteration
        w, h = map(partial(torch.clamp, min=0.0), (w, h))
        inter = w * h
        rem_areas = torch.index_select(area, 0, idx)  # load remaining areas)
        union = (rem_areas - inter) + area[i]
        iou = inter / union  # store result in iou
        idx = idx[iou.le(overlap)]
    return keep, count

def get_area(left_top, right_bottom) -> torch.Tensor:
    hw = torch.clamp(right_bottom - left_top, min=0.0)
    return hw[..., 0] * hw[..., 1]

def iou_of(boxes0, boxes1, eps=1e-5):
    overlap_left_top = torch.max(boxes0[..., :2], boxes1[..., :2])
    overlap_right_bottom = torch.min(boxes0[..., 2:], boxes1[..., 2:])

    overlap_area = get_area(overlap_left_top, overlap_right_bottom)
    area0 = get_area(boxes0[..., :2], boxes0[..., 2:])
    area1 = get_area(boxes1[..., :2], boxes1[..., 2:])
    return overlap_area / (area0 + area1 - overlap_area + eps)

def _nms_mean(boxes, scores, overlap=0.5, top_k=200):
    picked_indexes = []
    _, indexes = scores.sort(descending=True)
    indexes = indexes[:top_k]
    while len(indexes) > 0:
        current = indexes[0]
        picked_indexes.append([current.item()])
        if 0 < top_k == len(picked_indexes) or len(indexes) == 1:
            break
        current_box = boxes[current, :]
        indexes = indexes[1:]
        rest_boxes = boxes[indexes, :]
        iou = iou_of(
            rest_boxes,
            current_box.unsqueeze(0),
        )
        picked_indexes[-1].extend(indexes[iou > overlap].detach().cpu().numpy())
        indexes = indexes[iou <= overlap]

    averaged_boxes = []

    for indexes_group in picked_indexes:
        scores_group = scores[indexes_group]
        score = scores_group[0]
        boxes_group = boxes[indexes_group]

        # weigh picked bboxes using their scores
        scores_group = scores_group / scores_group.sum()
        averaged_box = (scores_group.unsqueeze(-1) * boxes_group).sum(0)
        averaged_boxes.append(torch.cat([score.unsqueeze(0), averaged_box]))

    res = torch.stack(averaged_boxes)
    return res

class Detect(object):
    """At test time, Detect is the final layer of SSD.  Decode location preds,
    apply non-maximum suppression to location predictions based on conf
    scores and threshold to a top_k number of output predictions for both
    confidence score and locations.
    """

    def __init__(self, num_classes, variance=(0.1, 0.2), bkg_label=0, top_k=200, conf_thresh=0.01, nms_thresh=0.45):
        self.num_classes = num_classes
        self.background_label = bkg_label
        self.top_k = top_k
        # Parameters used in nms.
        self.nms_thresh = nms_thresh
        if nms_thresh <= 0:
            raise ValueError('nms_threshold must be non negative.')
        self.conf_thresh = conf_thresh
        self.variance = variance

    def __call__(self, loc_data, conf_data, prior_data):
        """
        Args:
            loc_data: (tensor) Loc preds from loc layers
                Shape: [batch,num_priors*4]
            conf_data: (tensor) Shape: Conf preds from conf layers
                Shape: [batch*num_priors,num_classes]
            prior_data: (tensor) Prior boxes and variances from priorbox layers
                Shape: [1,num_priors,4]
        """
        num = loc_data.size(0)  # batch size
        num_priors = prior_data.size(0)
        output = torch.zeros(num, self.num_classes, self.top_k, 5)
        conf_preds = conf_data.view(num, num_priors,
                                    self.num_classes).transpose(2, 1)

        # Decode predictions into bboxes.
        for i in range(num):
            decoded_boxes = _decode(loc_data[i], prior_data, self.variance).cpu()
            # For each class, perform nms
            conf_scores = conf_preds[i].cpu()

            for cl in range(1, self.num_classes):
                c_mask = conf_scores[cl].gt(self.conf_thresh)
                scores = conf_scores[cl][c_mask]
                if scores.size(0) == 0:
                    continue
                l_mask = c_mask.unsqueeze(1).expand_as(decoded_boxes)
                boxes = decoded_boxes[l_mask].view(-1, 4)
                # idx of highest scoring and non-overlapping boxes per class
                box_scores = _nms_mean(boxes, scores, self.nms_thresh, self.top_k)
                count = box_scores.size(0)
                output[i, cl, :count] = box_scores
        flt = output.contiguous().view(num, -1, 5)
        _, idx = flt[:, :, 0].sort(1, descending=True)
        _, rank = idx.sort(1)
        flt[(rank < self.top_k).unsqueeze(-1).expand_as(flt)].fill_(0)
        return output

class DetectorPostProcessing(object):
    def __init__(self, config):
        self.detect = Detect(config['num_classes'], conf_thresh=config.get('filter_thr', 0.01))
        self.visual_thr = config["visual_thr"]

    def __call__(self, loc, conf, priors, img_shape, multiclass_suppression=True):
        bboxes, labels, scores = self.get_detections(loc, conf, priors, img_shape)
        # if multiclass_suppression:
        #     bboxes, labels, scores = self.multiclass_suppression(bboxes, labels, scores)
        return bboxes, labels, scores

    def get_detections(self, loc, conf, priors, img_shape):
        detections = self.detect(loc, F.softmax(conf, dim=-1), priors)

        # scale each detection back up to the image
        scale = torch.Tensor([img_shape[1], img_shape[0], img_shape[1], img_shape[0]])

        bboxes, labels, scores = [], [], []
        # ii -> category id, 0 - background class
        for ii in range(1, detections.size(1)):
            j = 0
            while detections[0, ii, j, 0] >= self.visual_thr:
                score = detections[0, ii, j, 0].tolist()
                pt = (detections[0, ii, j, 1:] * scale).tolist()
                bbox = [pt[0], pt[1], pt[2] - pt[0], pt[3] - pt[1]]

                bboxes.append(bbox)
                labels.append(ii)
                scores.append(score)
                j += 1
        return bboxes, labels, scores

    def multiclass_suppression(self, bboxes, labels, scores, nms_thresh=0.5):
        bboxes, labels, scores = torch.Tensor(bboxes), torch.IntTensor(labels), torch.Tensor(scores)

        ids, count = _nms(bboxes, scores, nms_thresh, top_k=len(bboxes))
        to_keep = ids[:count]
        bboxes, labels, scores = bboxes[to_keep].tolist(), labels[to_keep].tolist(), scores[to_keep].tolist()

        return bboxes.tolist(), labels.tolist(), scores.tolist()


import os
import shutil
import cv2
import glob
import numpy as np
def Parse_Path(path):
    file = path.split(os.sep)[-1]
    file_name = file.split(".")[0]
    return file,file_name

import numpy as np

def FilterImg(img_dir,
              save_dir,
              mask=True,
              stop_sign=False,
              equalize=True,
              roi_th=None):
    os.makedirs(os.path.join(save_dir,"roi"),exist_ok=True)
    os.makedirs(os.path.join(save_dir,"mask"),exist_ok=True)
    c = 1
    img_path_list = glob.glob(os.path.join(img_dir,'*.jpg'))
    for img_path in img_path_list:
        print(img_path)
        file,file_name = Parse_Path(img_path)
        img = cv2.imread(img_path)
        h,w = img.shape[0],img.shape[1]
        print("{}:{}".format(c,img_path))
        if h*w < roi_th*roi_th or h/w < 0.10 or h/w > 10:
            print("too small (<30*30 pixels) or ratio is <0.10 or <10.0, skip this ROI")
        else:
            #roi_dir = os.path.join(save_dir,"roi")
            #shutil.copy(img_path,roi_dir)
            #print("save img")

            if mask:
                img_gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
                ## Get the mean value of gray image
                img_gray_mean = img_gray.mean()
                print(img_gray_mean)
                #var = ((img_gray - img_gray_mean) ** 2).mean()
                #std_rgb = np.sqrt(var)
                if stop_sign:
                    _,img_binary = cv2.threshold(img_gray,img_gray_mean,255,cv2.THRESH_BINARY_INV) #THRESH_BINARY_INV
                    dilate_erode=False
                    if dilate_erode:
                        kernel = np.ones((3,3), np.uint8)
                        img_binary = cv2.dilate(img_binary, kernel, iterations = 10)
                        img_binary = cv2.erode(img_binary, kernel, iterations = 10)

                else:
                    _,img_binary = cv2.threshold(img_gray,img_gray_mean+10,255,0)
                mask_dir = os.path.join(save_dir,"mask")
                #study code from https://cloud.tencent.com/developer/article/1016690
                if stop_sign:
                    contours, hierarchy = cv2.findContours(img_binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
                    mask_img = np.zeros(img.shape, np.uint8)
                    #cv2.drawContours(mask_img, contours, -1, (255,255,255),cv2.FILLED)
                    #cv2.drawContours(mask_img, contours, -1, (255,255,255), 3)
                    c_max = []
                    max_area = 0
                    max_cnt = 0
                    for i in range(len(contours)):
                        cnt = contours[i]
                        area = cv2.contourArea(cnt)

                        # 处理掉小的轮廓区域，这个区域的大小自己定义。
                        if(area < (h*2/3*w*2/3)):
                            c_min = []
                            c_min.append(cnt)
                            # thickness不为-1时，表示画轮廓线，thickness的值表示线的宽度。
                            cv2.drawContours(mask_img, c_min, -1, (0,0,0), thickness=-1)
                            continue
                        #
                        c_max.append(cnt)
                    cv2.drawContours(mask_img, c_max, -1, (255, 255, 255), thickness=-1)
                    GET_BEAUTIFUL_MASK=False
                    if np.mean(mask_img) > 100:
                        GET_BEAUTIFUL_MASK=True

                    if GET_BEAUTIFUL_MASK:
                        kernel = np.ones((3,3), np.uint8)
                        mask_img = cv2.dilate(mask_img, kernel, iterations = 2)
                        cv2.imwrite(mask_dir+"/"+file,mask_img)
                        print("{}:Save mask".format(c))

                if not stop_sign:
                    GET_BEAUTIFUL_MASK=True
                    if GET_BEAUTIFUL_MASK:
                        os.makedirs(mask_dir,exist_ok=True)
                        print(mask_dir)
                        print("file:{}".format(file))
                        save_mask_path = os.path.join(mask_dir,file)
                        print("save_mask_path:{}".format(save_mask_path))
                        cv2.imwrite(save_mask_path,img_binary)
                        print("{}:Save mask".format(c))

                if equalize:
                    if img_gray_mean/1.0 +50 <=255:
                        img_tmp = int(img_gray_mean/1.0 + 50) * np.ones((int(img.shape[0]),int(img.shape[1]), 3), dtype=np.uint8)
                    else:
                        img_tmp = int(img_gray_mean/2.0 + 50) * np.ones((int(img.shape[0]),int(img.shape[1]), 3), dtype=np.uint8)

                    ##lighter the landmark roi foreground
                    if img[img_binary>20].mean() < 100:
                        value = int(255 - img[img_binary>20].mean())/2.0
                    elif img[img_binary>20].mean() >=  100 and img[img_binary>20].mean() <=  180:
                        value = int(255 - img[img_binary>20].mean())/2.5
                    else:
                        value = 0

                    ##darker the landmark roi background
                    if img[img_binary<=20].mean() > 127:
                        value_bg = int(img[img_binary<=20].mean())/2.0
                    else:
                        value_bg = 10

                    ##lighter/darker the landmark roi foreground/background
                    img[img_binary>20] = img[img_binary>20] + (value,value,value)
                    img[img_binary<=20] = img[img_binary<=20] - (value_bg,value_bg,value_bg)
                    roi_dir = os.path.join(save_dir,"roi")
                    if GET_BEAUTIFUL_MASK:
                        cv2.imwrite(roi_dir+"/"+file,img)
                        print("save new img")
                else:
                    img[img_binary>20] = img[img_binary>20]
                    img[img_binary<=20] = img[img_binary<=20]
                    roi_dir = os.path.join(save_dir,"roi")
                    if GET_BEAUTIFUL_MASK:
                        cv2.imwrite(roi_dir+"/"+file,img)
                        print("save new img")
                #=====================================================================================
                #Because it is already the ROI image, so l do not need use contour method to get ROI
                #======================================================================================
                # contours, hierarchy = cv2.findContours(img_binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
                # contours_poly = [None]*len(contours)
                # boundRect = [None]*len(contours)
                # for i, c in enumerate(contours):
                #     contours_poly[i] = cv2.approxPolyDP(c,3, True)#3
                #     boundRect[i] = cv2.boundingRect(contours_poly[i])

                # for i in range(len(contours)):
                #     x = boundRect[i][0]
                #     y = boundRect[i][1]
                #     w = boundRect[i][2]
                #     h = boundRect[i][3]

        c+=1

        #cv2.imshow("img",img)
        #cv2.waitKey(500)
        #cv2.destroyAllWindows()
        print(img_path)

    return

if __name__=="__main__":
    img_dir = "/home/ali/Downloads/roi_backup/merge_openlanev2_taiwan"
    save_dir = "/home/ali/Downloads/lanemarking_roi_new"
    stop_sign = False
    FilterImg(img_dir,
              save_dir,
              mask=True,
              stop_sign=stop_sign,
              equalize=False,
              roi_th=80)


from operator import and_
from flask import Blueprint, jsonify, request
from sqlalchemy import asc, and_

from capstone_api.models import db,States,State_Attractions,Popular_Activities,visitedStates

states = Blueprint('states',__name__)

@states.route('/API/States')
def stateAPI():
    states = States.query.order_by(asc(States.state)).all()
    return jsonify([state.to_dict() for state in states])

@states.route('/API/States/<state>')
def grabStateAPI(state):
    grabbed = States.query.filter_by(state=state).first()
    return jsonify([grabbed.to_dict()])

@states.route('/API/States/attractions/<state>')
def AttAPI(state):
    attns = State_Attractions.query.filter_by(state_name=state).all()
    return jsonify([attn.to_dict() for attn in attns])

@states.route('/API/States/reasons/<state>')
def ReasonsAPI(state):
    reasons=Popular_Activities.query.filter_by(state_name=state).all()
    return jsonify([r.to_dict() for r in reasons])

@states.route('/API/States/handlevisited', methods=['GET','POST'])
def handleVisited():
    data = request.json
    print(data)

    state = data['state']
    user = data['user']
    status = data['filler']

    if status == 'red':
        state_query = visitedStates.query.filter_by(state_name=state,user=user).first()
        db.session.delete(state_query)
        db.session.commit()
        return jsonify({'status': 'success', 'message': 'visited state removed!'})
    else:
        add = visitedStates(state,user)
        db.session.add(add)
        db.session.commit()
        return jsonify({'status': 'success', 'message': 'visited state added!'})

@states.route('/API/States/get_visited_states/<user>')
def GrabVisitedStates(user):
    grab = visitedStates.query.filter_by(user=user).all()
    return jsonify([state.to_dict() for state in grab])


#!/usr/bin/env python

from __future__ import with_statement, print_function
from os import mkfifo, remove
from blessings import Terminal

DEFAULT_FILENAME = 'simulator.fifo'
SEGMENTS = { # change numbers before ':' according to your wiring
        7: [(6, 0, '______')], # a
        6: [(5, 1, '/'), (4, 2, '/'), (3, 3, '/')], # f
        0: [(11, 1, '/'), (10, 2, '/'), (9, 3, '/')], # b
        1: [(4, 3, '_____')], # g
        5: [(2, 4, '/'), (1, 5, '/'), (0, 6, '/')], # e
        2: [(8, 4, '/'), (7, 5, '/'), (6, 6, '/')], # c
        4: [(1, 6, '_____')], # d
        3: [(8, 6, 'o')], # DP
        }
DIGIT_WIDTH = 10
NUM_DIGITS = 3
SERIAL_COMMAND = None

T = Terminal()

def simulator(filename):
    serial_digit = SERIAL_COMMAND
    framebuf = [0xFF for _ in xrange(NUM_DIGITS)]
    mkfifo(filename)
    try:
        dump(framebuf)
        while True:
            with file(filename) as fifo:
                while True:
                    chunk = fifo.read(1)
                    if not chunk:
                        break
                    byte = ord(chunk)
                    if byte & 0x80:
                        serial_digit = byte
                    elif serial_digit is not SERIAL_COMMAND:
                        digit = (serial_digit & 0x70) >> 4
                        framebuf[digit] = (serial_digit << 4) | byte
                        serial_digit = SERIAL_COMMAND
                        dump(framebuf)
    finally:
        remove(filename)

def dump(framebuf):
    for n, digit in enumerate(framebuf):
        for offset, elements in SEGMENTS.iteritems():
            mapper = T.red if (1 << offset) & digit else T.bold_yellow
            for x, y, element in elements:
                with T.location(x + n * DIGIT_WIDTH, y):
                    print(mapper(element))

if __name__ == '__main__':
    simulator(DEFAULT_FILENAME)


"""empty message

Revision ID: 3f765179d267
Revises: 6c38e63acb5f
Create Date: 2021-04-20 09:34:46.965871

"""
from alembic import op
import sqlalchemy as sa

# revision identifiers, used by Alembic.
revision = '3f765179d267'
down_revision = '6c38e63acb5f'
branch_labels = None
depends_on = None

def upgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    op.add_column('business_info', sa.Column('b_relieve_date', sa.String(length=15), server_default='-', nullable=True))
    # ### end Alembic commands ###

def downgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    op.drop_column('business_info', 'b_relieve_date')
    # ### end Alembic commands ###