from __future__ import absolute_import, division, print_function

__metaclass__ = type

import re

from ansible.module_utils.six import iteritems
from ansible_collections.ansible.netcommon.plugins.module_utils.network.common import utils
from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.rm_base.network_template import (
    NetworkTemplate,
)

from ansible_collections.cisco.ios.plugins.module_utils.network.ios.argspec.acls.acls import (
    AclsArgs,
)
from ansible_collections.cisco.ios.plugins.module_utils.network.ios.rm_templates.acls import (
    AclsTemplate,
)

class AclsFacts(object):
    """The ios_acls fact class"""

    def __init__(self, module, subspec="config", options="options"):
        self._module = module
        self.argument_spec = AclsArgs.argument_spec

    def get_acl_data(self, connection):
        # Get the access-lists from the ios router
        # Get the remarks on access-lists from the ios router
        # alternate command 'sh run partition access-list' but has a lot of ordering issues
        # and incomplete ACLs are not viewed correctly
        _acl_data = connection.get("show access-list")
        _remarks_data = connection.get("show running-config | include ip(v6)* access-list|remark")
        if _remarks_data:
            _acl_data += "\n" + _remarks_data
        return _acl_data

    def sanitize_data(self, data):
        """removes matches or extra config info that is added on acl match"""
        re_data = ""
        for da in data.split("\n"):
            if "match" in da:
                mod_da = re.sub(r"\([^()]*\)", "", da)
                re_data += mod_da[:-1] + "\n"
            else:
                re_data += da + "\n"
        return re_data

    def populate_facts(self, connection, ansible_facts, data=None):
        """Populate the facts for acls
        :param connection: the device connection
        :param ansible_facts: Facts dictionary
        :param data: previously collected conf
        :rtype: dictionary
        :returns: facts
        """

        if not data:
            data = self.get_acl_data(connection)

        if data:
            data = self.sanitize_data(data)

        rmmod = NetworkTemplate(lines=data.splitlines(), tmplt=AclsTemplate())
        current = rmmod.parse()

        temp_v4 = []
        temp_v6 = []

        if current.get("acls"):
            for k, v in iteritems(current.get("acls")):
                if v.get("afi") == "ipv4" and v.get("acl_type") in ["standard", "extended"]:
                    del v["afi"]
                    temp_v4.append(v)
                elif v.get("afi") == "ipv6":
                    del v["afi"]
                    temp_v6.append(v)

            temp_v4 = sorted(temp_v4, key=lambda i: str(i["name"]))
            temp_v6 = sorted(temp_v6, key=lambda i: str(i["name"]))

            def factor_source_dest(ace, typ):
                temp = ace.get(typ, {})
                if temp.get("address"):
                    _temp_addr = temp.get("address", "")
                    ace[typ]["address"] = _temp_addr.split(" ")[0]
                    ace[typ]["wildcard_bits"] = _temp_addr.split(" ")[1]

            def process_protocol_options(each):
                for each_ace in each.get("aces"):
                    if each.get("acl_type") == "standard":
                        if len(each_ace.get("source", {})) == 1 and each_ace.get("source", {}).get(
                            "address",
                        ):
                            each_ace["source"]["host"] = each_ace["source"].pop("address")
                        if each_ace.get("source", {}).get("address"):
                            addr = each_ace.get("source", {}).get("address")
                            if addr[-1] == ",":
                                each_ace["source"]["address"] = addr[:-1]
                    else:  # for extended acl
                        if each_ace.get("source", {}):
                            factor_source_dest(each_ace, "source")
                        if each_ace.get("destination", {}):
                            factor_source_dest(each_ace, "destination")

                    if each_ace.get("icmp_igmp_tcp_protocol"):
                        each_ace["protocol_options"] = {
                            each_ace["protocol"]: {
                                each_ace.pop("icmp_igmp_tcp_protocol").replace("-", "_"): True,
                            },
                        }
                    if each_ace.get("protocol_number"):
                        each_ace["protocol_options"] = {
                            "protocol_number": each_ace.pop("protocol_number"),
                        }

            def collect_remarks(aces):
                """makes remarks list per ace"""
                ace_entry = []
                rem = []
                for i in aces:
                    if i.get("remarks"):
                        rem.append(i.pop("remarks"))
                    else:
                        ace_entry.append(i)
                if rem:
                    ace_entry.append({"remarks": rem})
                return ace_entry

            for each in temp_v4:
                if each.get("aces"):
                    each["aces"] = collect_remarks(each.get("aces"))
                    process_protocol_options(each)

            for each in temp_v6:
                if each.get("aces"):
                    each["aces"] = collect_remarks(each.get("aces"))
                    process_protocol_options(each)

        objs = []
        if temp_v4:
            objs.append({"afi": "ipv4", "acls": temp_v4})
        if temp_v6:
            objs.append({"afi": "ipv6", "acls": temp_v6})

        facts = {}
        if objs:
            facts["acls"] = []
            params = utils.validate_config(self.argument_spec, {"config": objs})
            for cfg in params["config"]:
                facts["acls"].append(utils.remove_empties(cfg))
        ansible_facts["ansible_network_resources"].update(facts)

        return ansible_facts


import pickle
from collections import defaultdict
import itertools
import operator
from torch.utils.data import DataLoader, Dataset
import torch
import json
from functools import reduce
from itertools import accumulate
import random
import numpy as np

U_PATH, B_PATH = {}, {}
U_PATH['wq'] = '../data/WQ/main_exp'
U_PATH['wq_train1test2'] = '../data/WQ/train1test2_exp'
U_PATH['sq'] = '../data/SQ'
for i in [1,2,3]:
    U_PATH[f'pq{i}'] = f'../data/PQ/PQ{i}'
    U_PATH[f'pql{i}'] = f'../data/PQ/PQL{i}'
for i in range(11):
    U_PATH[f'wpq{i}'] = f'../data/PQ/exp3/UHop/{i}'
U_PATH['exp4'] = '../data/PQ/exp4'
U_PATH['grid2_4'] = '../data/grid-world/problem_16_4_2'
U_PATH['grid4_6'] = '../data/grid-world/problem_16_6_4'
U_PATH['grid6_8'] = '../data/grid-world/problem_16_8_6'
U_PATH['grid8_10'] = '../data/grid-world/problem_16_10_8'
B_PATH['wq'] = '../data/baseline/KBQA_RE_data/webqsp_relations/MODE_data.txt'
#PATH['wq'] = '../data/baseline/KBQA_RE_data/webqsp_relations/WebQSP.RE.MODE.with_boundary.withpool.dlnlp.txt'
B_PATH['sq'] = '../data/baseline/KBQA_RE_data/sq_relations/MODE.replace_ne.withpool'
for i in [1,2,3]:
    B_PATH[f'pq{i}'] = f'../data/PQ/baseline/PQ{i}/MODE_data1.txt'
    B_PATH[f'pql{i}'] = f'../data/PQ/baseline/PQL{i}/MODE_data1.txt'
for i in range(11):
    B_PATH[f'wpq{i}'] = f'../data/PQ/exp3/baseline/{i}/MODE_data.txt'
B_PATH['exp4'] = '../data/PQ/exp4/baseline/MODE_data.txt'

from itertools import accumulate

def quick_collate(batch):
    return batch[0]

def random_split(dataset, train_p, valid_p):
    random.shuffle(dataset.data_objs)
    return Subset(dataset.data_objs[:int(len(dataset)*train_p)]), Subset(dataset.data_objs[int(len(dataset)*train_p):])

class Subset(Dataset):
    def __init__(self, data_objs):
        self.data_objs = data_objs
    def __getitem__(self, idx):
        return self.data_objs[idx]
    def __len__(self):
        return len(self.data_objs)

class PerQuestionDataset(Dataset):
    def __init__(self, args, mode, word2id, rela2id):
        super(PerQuestionDataset, self).__init__()
        self.data_objs = self._get_data(args, mode, word2id, rela2id)
    def _get_data(self, args, mode, word2id, rela2id):
        data_objs = []
        if args.framework == 'UHop':
            file_path = U_PATH[args.dataset]
            print(file_path)
            with open(f'{file_path}/{mode}_data.txt', 'r') as f:
                for i, line in enumerate(f):
                    print(f'\rreading line {i}', end='')
                    data = json.loads(line)
                    data = self._numericalize(data, word2id, rela2id, args.q_representation, 'UHop')
                    data_objs.append(data)
        elif args.framework == 'baseline':
            file_path = B_PATH[args.dataset.lower()]
            print(file_path)
            with open(file_path.replace('MODE', mode), 'r') as f:
                for i, line in enumerate(f):
                    print(f'\rreading line {i}', end='')
                    anses, candidates, question = line.strip().split('\t')
                    # modify because of 'noNegativeAnswer' in sq data
                    candidates = [[x, [], 0] for x in candidates.split() if x not in anses.split() and x!='noNegativeAnswer']
                    # modify for "#head_entity#" label in sq dataset
                    ques = question.replace('$ARG1', '').replace('$ARG2', '')
                    ques = ques.replace('<e>', 'TOPIC_ENTITY').replace('#head_entity#', 'TOPIC_ENTITY').strip()
                    for ans in anses.split():
                        data = (i, ques, [[[ans, [], 1]]+candidates])
                        data = self._numericalize(data, word2id, rela2id, args.q_representation, 'baseline')
                        data_objs.append(data)
        return data_objs
    def _numericalize(self, data, word2id, rela2id, q_representation, framework):
        index, ques, step_list = data[0], data[1], data[2]
        if q_representation == "bert":
            ques = self._bert_numericalize_str(ques)
        else:
            ques = self._numericalize_str(ques, word2id, [' '])
        if framework == 'baseline':
            tuples = []
            for t in step_list[0]:
                num_rela = self._numericalize_str(t[0], rela2id, ['.'])
                num_rela_text = self._numericalize_str(t[0], word2id, ['.', '_'])
                num_prev = [self._numericalize_str(prev, rela2id, ['.']) for prev in t[1]]
                num_prev_text = [self._numericalize_str(prev, word2id, ['.', '_']) for prev in t[1]]
                tuples.append((num_rela, num_rela_text, num_prev, num_prev_text, t[2]))
            new_step_list = tuples
        else:
            new_step_list = []
            for step in step_list:
                new_step = []
                for t in step:
                    num_rela = self._numericalize_str(t[0], rela2id, ['.'])
                    num_rela_text = self._numericalize_str(t[0], word2id, ['.', '_'])
                    num_prev = [self._numericalize_str(prev, rela2id, ['.']) for prev in t[1]]
                    num_prev_text = [self._numericalize_str(prev, word2id, ['.', '_']) for prev in t[1]]
                    new_step.append((num_rela, num_rela_text, num_prev, num_prev_text, t[2]))
                new_step_list.append(new_step)
        return index, ques, new_step_list
    def _numericalize_str(self, string, map2id, dilemeter):
        #print('original str:', string)
        if len(dilemeter) == 2:
            string = string.replace(dilemeter[1], dilemeter[0])
        dilemeter = dilemeter[0]
        tokens = string.strip().split(dilemeter)
        tokens = [map2id[x] if x in map2id else map2id['<unk>'] for x in tokens]
        #print('tokens:', tokens)
        return tokens
    def _bert_numericalize_str(self, seq):
        tokens = self.bert_tokenizer.tokenize(seq)
        tokens = self.bert_tokenizer.convert_tokens_to_ids(tokens)
        return tokens
    def __len__(self):
        return len(self.data_objs)
    def __getitem__(self, index):
        return self.data_objs[index]

if __name__ == '__main__':
    with open('../data/WQ/main_exp/rela2id.json', 'r') as f:
        rela2id =json.load(f)
    word2id_path = '../data/glove.300d.word2id.json'
    with open(word2id_path, 'r') as f:
        word2id = json.load(f)
    class ARGS():
        def __init__(self):
            self.dataset = 'wq'
            self.mode = 'train'
        pass
    args = ARGS()
    dataset = PerQuestionDataset(args, 'train', word2id, rela2id)
    print()
    print(0, dataset[100][0])
    print(1, dataset[100][1])
    print(2, dataset[100][2])
    print(len(dataset[100]))


#!/usr/bin/env python3

import time
from caproto.server import pvproperty, PVGroup, ioc_arg_parser, run
import numpy as np
from caproto import ChannelType

image_shape = (768, 216)

class Server(PVGroup):
    t1 = pvproperty(value=2.0)
    shape = pvproperty(value=image_shape)
    image = pvproperty(
        value=np.random.randint(0, 255, image_shape, dtype = 'uint8').flatten(), dtype=bytes, max_length = 470448000
    )
    x = []
    y = []

    @t1.startup
    async def t1(self, instance, async_lib):
        # Loop and grab items from the queue one at a time
        while True:
            await self.t1.write(time.monotonic())
            self.x.append(self.t1.value)
            self.y.append(np.random.randint(0,256))
            image_shape = self.shape.value
            arr = self.figure_to_array(self.chart_one(x=self.x,y=self.y,shape = image_shape)).flatten()
            await self.image.write(arr)

            await async_lib.library.sleep(1)

    @shape.putter
    async def shape(self, instance, value):
        print('shape putter:',value)

    def chart_one(self,x,y, shape, dpi = 100):
        """
        charting function that takes x and y
        """
        xs_font = 10
        s_font = 12
        m_font = 16
        l_font = 24
        xl_font = 32

        import io
        from matplotlib.figure import Figure
        from matplotlib import pyplot
        from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg
        from scipy import stats
        figure = Figure(figsize=(shape[0]/dpi,shape[1]/dpi),dpi=dpi)#figsize=(7,5))
        axes = figure.add_subplot(1,1,1)
        from numpy import nonzero, zeros,nan, ones, argwhere, mean, nanmean, arange
        from scipy import stats

        axes.plot(x,y,'-o',color = 'lightblue')

        axes.set_title("Last Depressurize Event",fontsize=m_font, color = 'g')
        axes.set_xlabel("Time (ms)",fontsize=m_font)
        axes.set_ylabel("Pressure",fontsize=m_font)
        axes.tick_params(axis='y', which='both', labelleft=True, labelright=False, labelsize = m_font)

        axes.grid(True)
        axes.set_facecolor('xkcd:salmon')

        figure.tight_layout()
        return figure

    def figure_to_array(self, figure):
        from io import BytesIO
        from PIL.Image import open
        from numpy import asarray
        figure_buf = BytesIO()
        figure.savefig(figure_buf, format='jpg')
        figure_buf.seek(0)
        image = asarray(open(figure_buf))
        return image

if __name__ == "__main__":
    from tempfile import gettempdir
    print(f'temp-dir {gettempdir()}')

    from caproto import config_caproto_logging

    config_caproto_logging(file=gettempdir()+'/big_image_noisy_neibhor.log', level='DEBUG')

    ioc_options, run_options = ioc_arg_parser(
        default_prefix="bitmap_generator:",
        desc="Run an IOC that updates via I/O interrupt on key-press events.",
    )

    ioc = Server(**ioc_options)
    print(ioc.image)
    run(ioc.pvdb, **run_options)

{'io': 'io', 'Figure': 'matplotlib.figure.Figure', 'pyplot': 'matplotlib.pyplot', 'FigureCanvasWxAgg': 'matplotlib.backends.backend_wxagg.FigureCanvasWxAgg', 'stats': 'scipy.stats', 'nonzero': 'numpy.nonzero', 'zeros': 'numpy.zeros', 'nan': 'numpy.nan', 'ones': 'numpy.ones', 'argwhere': 'numpy.argwhere', 'mean': 'numpy.mean', 'nanmean': 'numpy.nanmean', 'arange': 'numpy.arange', 'BytesIO': 'io.BytesIO', 'open': 'PIL.Image.open', 'asarray': 'numpy.asarray'}


#이진분류
#1. 마지막 아웃풋레이어, activation = 'sigmoid'사용
#2. loss = 'binary_crossentropy'사용
#값이 0과 1로만 나올 수 있게 해줘야함!

import numpy as np
from tensorflow.python.keras.models import Sequential, Model
from tensorflow.python.keras.layers import Dense, Input
from sklearn.model_selection import train_test_split
import pandas as pd
from sklearn.experimental import enable_iterative_imputer
from sklearn.impute import IterativeImputer
from sklearn.covariance import EllipticEnvelope  #reshape필요
from xgboost import XGBRegressor

#1. 데이터
path = 'd:/study/_data/dacon_diabetes/'
path_save = './_save/dacon_diabetes/'

train_csv= pd.read_csv(path+'train.csv', index_col=0)
print(train_csv)
# [652 rows x 9 columns] #(652,9)

test_csv= pd.read_csv(path+'test.csv', index_col=0)
print(test_csv)
#(116,8) #outcome제외

# print(train_csv.isnull().sum()) #결측치 없음
# print(train_csv.columns)
# Index(['Pregnancies', 'Glucose', 'BloodPressure', 'SkinThickness', 'Insulin',
#        'BMI', 'DiabetesPedigreeFunction', 'Age', 'Outcome'],
#       dtype='object')

x = train_csv.drop(['Outcome'], axis=1)
# print(x)
y = train_csv['Outcome']
# print(y)

###이상치 처리###

#이상치 찾는 함수(df)
def outliers(data_out):
    quartile_1, q2, quartile_3 = np.percentile(data_out, [25, 50, 75], axis=0)
    print('1사분위 : ', quartile_1)
    print('q2 : ', q2)
    print('3사분위 : ', quartile_3)
    iqr = quartile_3 - quartile_1
    print('iqr : ', iqr)
    lower_bound = quartile_1 - (iqr * 1.5)
    upper_bound = quartile_3 + (iqr * 1.5)
    return np.where((data_out>upper_bound) | (data_out<lower_bound))
outliers_loc = outliers(x)

print(outliers_loc)
print('이상치의 위치 : ', list(outliers_loc))

# outliers_loc = 9999
x[outliers_loc] = 9999
import matplotlib.pyplot as plt
plt.boxplot(x)
plt.show()

# ###결측치제거###
# train_csv = train_csv.dropna()   #결측치 삭제함수 .dropna()
# print(train_csv.isnull().sum())
# # print(train_csv.info())
# print(train_csv.shape)  #(1328, 10)

imputer = IterativeImputer(estimator=XGBRegressor())
x = imputer.fit_transform(x)
train_csv =x
train_csv = pd.DataFrame(train_csv)
test_csv = pd.DataFrame(test_csv)
train_csv.columns = ['Pregnancies', 'Glucose', 'BloodPressure', 'SkinThickness', 'Insulin','BMI', 'DiabetesPedigreeFunction', 'Age']
test_csv.columns = ['Pregnancies', 'Glucose', 'BloodPressure', 'SkinThickness', 'Insulin','BMI', 'DiabetesPedigreeFunction', 'Age']
print(train_csv)
print(test_csv)

x_train, x_test, y_train, y_test = train_test_split(
    x, y, shuffle=True, random_state=640, test_size=0.2,
    stratify=y
)

#data scaling(스케일링)
from sklearn.preprocessing import MinMaxScaler, StandardScaler
from sklearn.preprocessing import RobustScaler, MaxAbsScaler
# scaler = MinMaxScaler()
scaler = MaxAbsScaler()
scaler.fit(x_train) #x_train범위만큼 잡아라
x_train = scaler.transform(x_train) #변환
#x_train의 변환 범위에 맞춰서 하라는 뜻이므로 scaler.fit할 필요x
x_test = scaler.transform(x_test)
test_csv = scaler.transform(test_csv)

#2. 모델구성
input1 = Input(shape=(8, ))
dense1 = Dense(8, activation='linear')(input1)
dense2 = Dense(4, activation='relu')(dense1)
dense3 = Dense(8, activation='relu')(dense2)
dense4 = Dense(4, activation='relu')(dense3)
output1 = Dense(1, activation='sigmoid')(dense4)
model = Model(inputs=input1, outputs=output1)
#이진분류 - 마지막 아웃풋레이어, 'sigmoid'사용 (0,1사이로 한정)

#3. 컴파일, 훈련

model.compile(loss='binary_crossentropy', optimizer='adam',   #이진분류 - loss, 'binary_crossentropy'사용
              metrics=['accuracy','mse']
              )

from tensorflow.python.keras.callbacks import EarlyStopping
es = EarlyStopping(monitor='val_loss', patience=10, mode='min',
              verbose=1,
              restore_best_weights=True
             )

hist = model.fit(x_train, y_train, epochs=999, batch_size=32,
          validation_split=0.1,
          verbose=1,
          callbacks=[es]
          )

#4. 평가, 예측
results = model.evaluate(x_test, y_test)
print('results:', results)

y_predict = np.round(model.predict(x_test)) #np.round:반올림 / 예측값을 반올림해서 0,1의 값이 나올 수 있도록해줌 (0.5까지는 0으로, 0.6부터는 1로)

from sklearn.metrics import r2_score, accuracy_score
acc = accuracy_score(y_test, y_predict)
print('acc: ', acc)

#submission.csv생성
y_submit = np.round(model.predict(test_csv))  #np.round y_submit에도 해야함!!****
# print(y_submit)

submission = pd.read_csv(path + 'sample_submission.csv', index_col=0)
submission['Outcome'] = y_submit
# print(submission)

submission.to_csv(path_save + 'submit_0313_1800_MaxScaler.csv') # 파일생성

import matplotlib.pyplot as plt
import matplotlib
matplotlib.rcParams['font.family'] = 'Malgun Gothic'
plt.figure(figsize=(9,6))
plt.plot(hist.history['loss'], marker='.', c='red')
plt.plot(hist.history['val_loss'], marker='.', c='blue')
plt.title('따릉이')
plt.xlabel('epochs')
plt.ylabel('loss, val_loss')
plt.legend(('로스', '발_로스'))
plt.grid()
plt.show()

'''
1. 0.65점
acc:0.70/seed: 640784
2. 0.65점
acc:0.74/seed: 88463

3. 0.75점*
acc:0.73
4. 0.78점**
acc:  0.72 /seed:321847
5. [1410]
results: [0.6158730387687683, 0.7022900581359863, 0.2031799852848053]
acc:  0.7022900763358778
6. [0309_1420]/ 0.818점***2등
*stratify=y
results: [0.7886713743209839, 0.7175572514533997, 0.19658119976520538]
acc:  0.71
seed:640, Dense(8,4,8,4,1), batch_size=32

7. [0310_1830]0.810점
results: [0.5848807096481323, 0.694656491279602, 0.20382462441921234]
acc:  0.6946564885496184
patience=310, epochs=10010

8. RobScaler
Epoch 00423: early stopping
results: [0.5853256583213806, 0.7633587718009949, 0.17271968722343445]
acc:  0.7633587786259542
9. MaxScaler

'''


import json
import os
import sys
import urllib.error
import urllib.parse
import urllib.request

this_module_path = sys.modules[__name__].__file__

def fetch_remote_files():
    r"""Fetch remote files before any test runs"""
    data_dir = os.path.dirname(this_module_path)
    remote_info_file = os.path.join(data_dir, "remote_files.json")
    remote_info = json.load(open(remote_info_file, "r"))

    remote_address = remote_info["address"]
    remote_files = remote_info["files"]

    for basename, md5 in remote_files.items():
        file_path = os.path.join(data_dir, basename)
        if not os.path.isfile(file_path):
            print("Fetching data file " + basename)
            urllib.request.urlretrieve(os.path.join(remote_address, md5), file_path)

if __name__ == "__main__":
    fetch_remote_files()


import collections

class Solution(object):

    def dfs(self, v):
        #if self.visited[v]:
        #    return True

        #self.visited[v] = True
        #self.on_the_path[v] = True

        self.visited.add(v)
        self.on_the_path.add(v)

        for w in self.adjList[v]:
            if w not in self.visited:
                if self.dfs(w):
                    return True
            elif w in self.on_the_path:
                print(f"Cycle detected: found a back edge from {v} to {w}.")
                return True
            #if not self.visited[w]:
            #    if self.dfs(w):
            #        return True
            #elif self.on_the_path[w]:
            #     return True
        #self.on_the_path[v] = False
        self.on_the_path.remove(v)

        return False

    def detectCycles(self, edges):
        """
        :type edges: List[List[int]]
        :rtype: Bool
        """

        n = len(edges)
        #self.adjList = [[] for i in range(n+1)]
        self.adjList = collections.defaultdict(list)

        for e in edges:
            w, v = e[0], e[1]
            self.adjList[w].append(v)

        #self.visited = [False] * (n+1)
        #self.on_the_path = [False] * (n+1)
        self.visited = set()
        self.on_the_path = set()

        return self.dfs(edges[0][0])

print(Solution().detectCycles([[1,2], [2,3], [3,4], [4,1], [1,5]]))
print(Solution().detectCycles([[1,2], [1,3], [2,3]]))
print(Solution().detectCycles([[2,1],[3,1],[4,2],[1,4]]))
print(Solution().detectCycles([('u', 'v'),
        ('u', 'x'),
        ('v', 'y'),
        ('w', 'y'),
        ('w', 'z'),
        ('x', 'v'),
        ('y', 'x')]))

#import collections

class Graph(object):
    def __init__(self, edges):
        self.edges = edges
        self.adj = Graph._build_adjacency_list(edges)

    @staticmethod
    def _build_adjacency_list(edges):
        adj = collections.defaultdict(list)
        for edge in edges:
            adj[edge[0]].append(edge[1])
        return adj

def dfs(G):
    discovered = set()
    finished = set()

    for u in G.adj:
        if u not in discovered and u not in finished:
            discovered, finished = dfs_visit(G, u, discovered, finished)

def dfs_visit(G, u, discovered, finished):
    discovered.add(u)
    finished.add(u)
    for v in G.adj[u]:
        # Detect cycles
        if v in discovered:
            print(f"Cycle detected: found a back edge from {u} to {v}.")
            #return discovered, finished
        # Recurse into DFS tree
        if v not in finished:
            dfs_visit(G, v, discovered, finished)

    discovered.remove(u)

    return discovered, finished

if __name__ == "__main__":
    G = Graph([
        ('u', 'v'),
        ('u', 'x'),
        ('v', 'y'),
        ('w', 'y'),
        ('w', 'z'),
        ('x', 'v'),
        ('y', 'x'),
        ('z', 'z')])

    dfs(G)


import unittest
from helper import Sparkfn

class TestStringMethods(unittest.TestCase):
    'Testing UDF spark function'

    def test_pattern(self):
        urlList = ['https://domain1.com/display-product/1   ','  https://domain1.com/search-products','https://domain1.com/buy-product']
        for url in urlList:
            self.assertIsNotNone(Sparkfn.getPattern(url))

    def test_is_numeric(self):
        self.assertTrue(Sparkfn.is_numeric('1.12'))
        self.assertTrue(Sparkfn.is_numeric('1123'))
        self.assertFalse(Sparkfn.is_numeric('asc!'))
        self.assertFalse(Sparkfn.is_numeric('123.A'))

    def test_totimestamp(self):
        st_ts ='2020-10-10 10:10:10'
        self.assertTrue(isinstance(Sparkfn.to_timestamp(st_ts),int))

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


# Implementation of algorithm from https://stackoverflow.com/a/22640362/6029703
import numpy as np
import h5py
import os
import argparse
from shutil import copyfile

def thresholding_algo(y, lag):
    min_length = 5000
    signals = np.zeros(len(y))
    blockage = np.zeros(len(y))
    avg = [0]*len(y)
    std = [0]*len(y)
    avg[lag - 1] = np.mean(y[0:lag])
    std[lag - 1] = np.std(y[0:lag])
    current = 0
    first_occurence = 0
    for i in range(lag, len(y)):
        avg[i] = np.mean(y[(i-lag+1):i+1])
        std[i] = np.std(y[(i-lag+1):i+1])
        if abs(avg[i]-avg[i-100]) < 0.015*avg[i]:
            signals[i] = 1
            current += 1
            if current>min_length:
                blockage[i-min_length:i] = 1
                if first_occurence==0:
                    first_occurence = i-min_length
                    print("std:", std[i])
        else:
            current = 0

    return dict(signals = np.asarray(signals),
                blockage = np.asarray(blockage),
                avg = np.asarray(avg),
                first_occurence = first_occurence)

def locate_blk(fast5):
    lag = 400

    for key in fast5['Raw']['Reads'].keys():
        y = fast5['Raw']['Reads'][key]['Signal'][()]
        y = y.astype(np.int16)
    result = thresholding_algo(y, lag=lag)

    return result["first_occurence"]

def find_read(name):
    if 'Read_' in name:
        return name

ap = argparse.ArgumentParser()
ap.add_argument("-i", "--input", required=True,
    help="path to fast5 files")
ap.add_argument("-b", "--blk", required=True,
    help="path to blk savedir")
ap.add_argument("-n", "--norm", required=True,
    help="path to norm savedir")
args = vars(ap.parse_args())

files = os.listdir(args["input"])
k = 0

for file in files:

    if file.endswith("fast5"):

        fast5 = h5py.File(os.path.join(args["input"], file), 'r')
        k += 1
        CUT = locate_blk(fast5)

        for key in fast5['Raw']['Reads'].keys():
            signal = fast5['Raw']['Reads'][key]['Signal'][()]
            signal = signal.astype(np.int16)
            key_str = fast5['Raw']['Reads'].visit(find_read)

        if CUT>5000:
            print(file)
            copyfile(os.path.join(args["input"], file), os.path.join(args["blk"], file))
        else:
            copyfile(os.path.join(args["input"], file), os.path.join(args["norm"], file))

        if k>4000:
            break


import tflite_runtime.interpreter as tflite
import os
import numpy as np
from io import BytesIO
from urllib import request
from PIL import Image

def download_image(url):
    with request.urlopen(url) as resp:
        buffer = resp.read()
    stream = BytesIO(buffer)
    img = Image.open(stream)
    return img

def prepare_image(img, target_size):
    if img.mode != 'RGB':
        img = img.convert('RGB')
    img = img.resize(target_size, Image.NEAREST)
    return img

def prepare_input(x):
    return x / 255.0

interpreter = tflite.Interpreter('vegetables-model.tflite')
interpreter.allocate_tensors()

input_index = interpreter.get_input_details()[0]['index']
output_index = interpreter.get_output_details()[0]['index']

def predict(url):
    img = download_image(url)
    img = prepare_image(img, target_size=(224, 224))

    x = np.array(img, dtype='float32')
    X = np.array([x])
    X = prepare_input(X)

    interpreter.set_tensor(input_index, X)
    interpreter.invoke()

    preds = interpreter.get_tensor(output_index)

    classes = [
        'Bean',
        'Bitter_Gourd',
        'Bottle_Gourd',
        'Brinjal',
        'Broccoli',
        'Cabbage',
        'Capsicum',
        'Carrot',
        'Cauliflower',
        'Cucumber',
        'Papaya',
        'Potato',
        'Pumpkin',
        'Radish',
        'Tomato'
    ]

    return classes[np.argmax(preds)], preds[0][np.argmax(preds)]

def lambda_handler(event, context):
    url = event['url']
    pred, proba = predict(url)
    result = {
        'prediction': pred,
        'probability':float(proba)
    }

    return result


import os
import struct
import sys
from io import BytesIO

def insert_gim_files(rssa_file, gim_directory, output_directory):
    original_rssa_name = os.path.basename(rssa_file)
    with open(rssa_file, 'rb') as original_f:
        temp_f = BytesIO(original_f.read())

    temp_f.seek(0)
    header = temp_f.read(0x60)  # read 60 bytes header
    magic = struct.unpack_from('=4s', header, 0)[0]
    fname = struct.unpack_from('=28s', header, 0x4)[0]
    ssad_count = struct.unpack_from('<H', header, 0x2C)[0]
    gim_count = struct.unpack_from('<H', header, 0x2E)[0]
    ssad_pos_foffset = struct.unpack_from('<I', header, 0x30)[0]
    ssad_pos_fsize = struct.unpack_from('<I', header, 0x34)[0]
    gim_pos_foffset = struct.unpack_from('<I', header, 0x38)[0]
    gim_pos_fsize = struct.unpack_from('<I', header, 0x3C)[0]
    print('header=', header.hex())
    print('magic=', magic.decode('utf-8'))
    print('fname=', fname.decode('utf-8'))
    print('ssad_count=', hex(ssad_count))
    print('gim_count=', hex(gim_count))
    print('ssad_pos_foffset=', hex(ssad_pos_foffset))
    print('ssad_pos_fsize=', hex(ssad_pos_fsize))
    print('gim_pos_foffset=', hex(gim_pos_foffset))
    print('gim_pos_fsize=', hex(gim_pos_fsize))

    # Read the structures from the binary file
    structures_pos = []
    temp_f.seek(gim_pos_foffset)
    for _ in range(gim_count):
        structure_pos = struct.unpack('<I', temp_f.read(4))[0]
        structures_pos.append(structure_pos)
        #print('structure_pos=', hex(structure_pos[0]))

    structures_size = []
    temp_f.seek(gim_pos_fsize)
    for _ in range(gim_count):
        structure_size = struct.unpack('<I', temp_f.read(4))[0]
        structures_size.append(structure_size)
        #print('structure_size=', hex(structure_size[0]))

    # insert the gim in the temp_f
    for gim_file in sorted(os.listdir(gim_directory)):
        if gim_file.endswith('.gim'):  # Check if the file has the .gim extension
            with open(os.path.join(gim_directory, gim_file), 'rb') as gim:
                gim_data = gim.read()
                gim_name = os.path.splitext(gim_file)[0]  # Get the gim file name without the .gim extension
                print(gim_name)
                gim_pos = structures_pos[int(gim_name)]  # Retrieve the file offset for this gim file
                print(hex(gim_pos))
                temp_f.seek(gim_pos)  # Move the pointer in temp_f to the specified offset
                temp_f.write(gim_data)  # Write the gim data at the specified position in temp_f
    # Save the modified content to a new file in the output directory

    output_file = os.path.join(output_directory, f"{original_rssa_name}")
    with open(output_file, 'w+b') as new_f:
        new_f.write(temp_f.getbuffer())

if __name__ == '__main__':
    if len(sys.argv) != 4:
        print("Usage: python gim_insertion.py <rssa_file> <gim_directory> <output_directory>")
    else:
        rssa_file = sys.argv[1]
        gim_directory = sys.argv[2]
        output_directory = sys.argv[3]
        insert_gim_files(rssa_file, gim_directory, output_directory)


import serial
from NeuroPy import NeuroPy
from time import sleep
import os
import sys

ser = serial.Serial("COM3",9600)
ser1 = serial.Serial("COM5",9600)
#if not ser.isOpen():
#	ser.open()
#print('COM3 is open', ser.isOpen())
#print("hello:"+str(ser.read(1)))

#neuropy = NeuroPy.NeuroPy("COM3",9600)

def attention_callback(attention_value):
    """this function will be called everytime NeuroPy has a new value for attention"""
    print ("Value of attention is: ", attention_value)
    return None

def rawValue_callback(rawValue):
    """this function will be called everytime NeuroPy has a new value for attention"""
    print ("rawValue is: ", rawValue)
    return None

def blink_callback(value):
    print("Blink ", value)

#neuropy.setCallBack("attention", attention_callback)
#neuropy.setCallBack("rawValue", rawValue_callback)
#neuropy.setCallBack("blinkStrength",blink_callback)
#neuropy.start()

try:
    while True:
	    print("i'm running")
	    print("MrESP:"+str(ser.read(1).hex()))
	    print("Mindwave:"+str(ser1.read(1).hex()))
	    sleep(0.2)
finally:
    neuropy.stop()


import argparse
import logging
import os
import shutil

import tensorflow as tf
from tensorflow.python.saved_model import tag_constants

class ModelManager:
    INPUT_NAME = "input"
    OUTPUT_NAME = "output"

    def __init__(self, save_folder, input_dimensions):
        self.save_folder = save_folder
        self.input_dimensions = input_dimensions

    def _remove_folder_if_exists(self, path):
        if os.path.exists(path):
            shutil.rmtree(path)

    def save_model(self, sess, model):
        input_placeholder = tf.placeholder(tf.float32,
                                           shape=self.input_dimensions,
                                           name=self.INPUT_NAME)
        output_placeholder = model.sample(input_placeholder)
        output_placeholder = tf.identity(output_placeholder,
                                         name=self.OUTPUT_NAME)

        # simple_save creates a new folder and fails if the folder already
        # exists
        self._remove_folder_if_exists(self.save_folder)

        tf.saved_model.simple_save(
            sess,
            self.save_folder,
            {'in': input_placeholder},
            {'out': output_placeholder}
        )

        logging.info("Model saved in folder: {}".format(self.save_folder))

    def load_model(self, sess, graph):
        tf.saved_model.loader.load(
            sess,
            [tag_constants.SERVING],
            self.save_folder,
        )
        in_tensor = graph.get_tensor_by_name("{}:0".format(self.INPUT_NAME))
        out_tensor = graph.get_tensor_by_name("{}:0".format(self.OUTPUT_NAME))

        logging.info("Model loaded from folder: {}".format(self.save_folder))
        return in_tensor, out_tensor

"""
graph = tf.Graph()
with graph.as_default():
    with tf.Session() as sess:
        input_dimensions = [2, 72, 120, 3]

        input_image = np.random.randint(0, 10, input_dimensions)

        tf.saved_model.loader.load(
            sess,
            [tag_constants.SERVING],
        '../checkpoints_gazenet/20181226-1725_debug_gazenet_m2u/saved_model',
        )
        in_tensor = graph.get_tensor_by_name('input_image:0')
        out_tensor = graph.get_tensor_by_name('output_gaze:0')

        r = sess.run(out_tensor, feed_dict={
            in_tensor: input_image
        })
        print(r)
"""

# The original freeze_graph function
# from tensorflow.python.tools.freeze_graph import freeze_graph

dir = os.path.dirname(os.path.realpath(__file__))

def freeze_graph(model_dir, output_node_names):
    """Extract the sub graph defined by the output nodes and convert
    all its variables into constant
    Args:
        model_dir: the root folder containing the checkpoint state file
        output_node_names: a string, containing all the output node's names,
                            comma separated
    """
    if not tf.gfile.Exists(model_dir):
        raise AssertionError(
            "Export directory doesn't exists. Please specify an export "
            "directory: %s" % model_dir)

    if not output_node_names:
        print("You need to supply the name of a node to --output_node_names.")
        return -1

    # We retrieve our checkpoint fullpath
    checkpoint = tf.train.get_checkpoint_state(model_dir)
    input_checkpoint = checkpoint.model_checkpoint_path

    # We precise the file fullname of our freezed graph
    absolute_model_dir = "/".join(input_checkpoint.split('/')[:-1])
    output_graph = absolute_model_dir + "/frozen_model.pb"

    # We clear devices to allow TensorFlow to control on which device it will load operations
    clear_devices = True

    # We start a session using a temporary fresh Graph
    with tf.Session(graph=tf.Graph()) as sess:
        # We import the meta graph in the current default Graph
        saver = tf.train.import_meta_graph(input_checkpoint + '.meta',
                                           clear_devices=clear_devices)

        # We restore the weights
        saver.restore(sess, input_checkpoint)

        print([n.name for n in tf.get_default_graph().as_graph_def().node])

        # We use a built-in TF helper to export variables to constants
        output_graph_def = tf.graph_util.convert_variables_to_constants(
            sess,  # The session is used to retrieve the weights
            tf.get_default_graph().as_graph_def(),
            # The graph_def is used to retrieve the nodes
            output_node_names.split(",")
            # The output node names are used to select the usefull nodes
        )

        # Finally we serialize and dump the output graph to the filesystem
        with tf.gfile.GFile(output_graph, "wb") as f:
            f.write(output_graph_def.SerializeToString())
        print("%d ops in the final graph." % len(output_graph_def.node))

    return output_graph_def

def load_graph(frozen_graph_filename):
    # We load the protobuf file from the disk and parse it to retrieve the
    # unserialized graph_def
    with tf.gfile.GFile(frozen_graph_filename, "rb") as f:
        graph_def = tf.GraphDef()
        graph_def.ParseFromString(f.read())

    # Then, we import the graph_def into a new Graph and returns it
    with tf.Graph().as_default() as graph:
        # The name var will prefix every op/nodes in your graph
        # Since we load everything in a new graph, this is not needed
        tf.import_graph_def(graph_def, name="prefix")
    return graph

if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument("--model_dir", type=str, default="",
                        help="Model folder to export")
    parser.add_argument("--output_node_names", type=str, default="",
                        help="The name of the output nodes, comma separated.")
    args = parser.parse_args()

    freeze_graph(args.model_dir, args.output_node_names)


import tensorflow as tf
from tensorflow import keras

import numpy as np
import matplotlib.pyplot as plt

import random

def main_1():
    mnist = tf.keras.datasets.mnist

    (x_train, y_train), (x_test, y_test) = mnist.load_data()
    x_train, x_test = x_train/255.0, x_test/255.0

    model = tf.keras.models.Sequential([
        tf.keras.layers.Flatten(input_shape=(28, 28)),
        tf.keras.layers.Dense(128, activation='relu'),
        tf.keras.layers.Dropout(0.2),
        tf.keras.layers.Dense(10, activation='softmax')
    ])

    model.compile(optimizer='adam',
                  loss='sparse_categorical_crossentropy',
                  metrics=['accuracy'])

    model.fit(x_train, y_train, epochs=5)
    model.evaluate(x_test, y_test, verbose=2)

def main_2():
    fashion_mnist = keras.datasets.fashion_mnist
    (train_images, train_labels), (test_images, test_labels) = fashion_mnist.load_data()
    class_names = ['T-shirt/top', 'Trouser', 'Pullover', 'Dress', 'Coat',
                   'Sandal', 'Shirt', 'Sneaker', 'Bag', 'Ankle boot']
    print("image的格式为：" + str(train_images.shape))

    model = keras.Sequential([
        keras.layers.Flatten(input_shape=(28, 28)),
        keras.layers.Dense(128, activation='relu'),
        keras.layers.Dense(10)
    ])

    model.compile(optimizer='adam',
                  loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
                  metrics=['accuracy'])

    model.fit(train_images, train_labels, epochs=10)

    test_loss, test_acc = model.evaluate(test_images, test_labels, verbose=2)
    print("\nTest accuracy:", test_acc)
    print("\nTest Loss:", test_loss)

    probability_model = tf.keras.Sequential([model, tf.keras.layers.Softmax()])
    predictions = probability_model.predict(test_images)
    print(predictions[0])
    print("---------------------------------------------------")

    print(np.argmax(predictions[0]))
    print("This image is an " + class_names[int(np.argmax(predictions[0]))])

    img = test_images[124]
    print(img.shape)
    img = (np.expand_dims(img, 0))
    print(img.shape)

    predictions_single = probability_model.predict(img)
    print(predictions_single)
    print("The result is " + class_names[int(np.argmax(predictions_single))])
    print("The true label is " + class_names[test_labels[124]])

    i = 12
    plt.figure(figsize=(6, 3))
    plt.subplot(1, 2, 1)
    plot_image(i, predictions[i], test_labels, test_images, class_names)
    plt.subplot(1, 2, 2)
    plot_value_array(i, predictions[i], test_labels)
    plt.show()

def plot_image(i, predictions_array, true_label, img, class_names):
    predictions_array, true_label, img = predictions_array, true_label[i], img[i]
    plt.grid(False)
    plt.xticks([])
    plt.yticks([])

    plt.imshow(img, cmap=plt.cm.binary)

    predicted_label = np.argmax(predictions_array)
    if predicted_label == true_label:
        color = 'blue'
    else:
        color = 'red'

    plt.xlabel("{} {:2.0f}% ({})".format(class_names[predicted_label],
                                         100*np.max(predictions_array),
                                         class_names[true_label]),
               color=color)

def plot_value_array(i, predictions_array, true_label):
    predictions_array, true_label = predictions_array, true_label[i]
    plt.grid(False)
    plt.xticks(range(10))
    plt.yticks([])
    thisplot = plt.bar(range(10), predictions_array, color="#777777")
    plt.ylim([0, 1])
    predicted_label = np.argmax(predictions_array)

    thisplot[predicted_label].set_color('red')
    thisplot[true_label].set_color('blue')

def build_data():
    num_sha1 = 0
    num_md5 = 0
    num_mysql = 0
    with open("jiami_v3.txt", "w") as f:
        with open("sha1.txt", "r") as ff:
            while 1:
                h = ff.readline()
                if h:
                    num_sha1 += 1
                    index = h.find(":")
                    h = h[:index+1] + "0\n"
                    # SHA1
                    f.write(h)
                else:
                    break
        with open("sha1_2.txt", "r") as ff:
            while 1:
                h = ff.readline()
                if h:
                    num_sha1 += 1
                    index = h.find(":")
                    h = h[:index+1] + "0\n"
                    # SHA1
                    f.write(h)
                else:
                    break
        with open("MD5_401.txt", "r") as ff:
            while 1:
                h = ff.readline().strip('\n')
                if h:
                    num_md5 += 1
                    h = h + ":1\n"
                    # MD5
                    f.write(h)
                else:
                    break
        with open("mysql5.txt", "r") as ff:
            while 1:
                h = ff.readline()
                if h:
                    num_mysql += 1
                    index = h.find(":")
                    h = h[:index+1] + "2\n"
                    # MYSQL
                    f.write(h)
                else:
                    break
        with open("mysql_2.txt", "r") as ff:
            while 1:
                h = ff.readline()
                if h:
                    num_mysql += 1
                    index = h.find(":")
                    h = h[:index+1] + "2\n"
                    f.write(h)
                else:
                    break
        with open("mysql_3.txt", "r") as ff:
            while 1:
                h = ff.readline()
                if h:
                    num_mysql += 1
                    index = h.find(":")
                    h = h[:index+1] + "2\n"
                    f.write(h)
                else:
                    break
        with open("mysql_4.txt", "r") as ff:
            while 1:
                h = ff.readline()
                if h:
                    num_mysql += 1
                    index = h.find(":")
                    h = h[:index+1] + "2\n"
                    f.write(h)
                else:
                    break
        with open("mysql_5.txt", "r") as ff:
            while 1:
                h = ff.readline().strip("*")
                if h:
                    num_mysql += 1
                    index = h.find(":")
                    h = h[:index+1] + "2\n"
                    f.write(h)
                else:
                    break
    print("SHA1数量：" + str(num_sha1))
    print("MD5数量：" + str(num_md5))
    print("MYSQL数量：" + str(num_mysql))

    data_s = []
    with open("jiami_v3.txt", "r") as f:
        while 1:
            h = f.readline().strip("\n")
            if h:
                data_s.append(h)
            else:
                break

    random.shuffle(data_s)

    i = len(data_s) * 0.3
    train = data_s[int(i):]
    test = data_s[:int(i)]

    train_x = []
    train_y = []
    test_x = []
    test_y = []

    for i in train:
        h = i.split(":")
        x = np.array([[ord(str(i))] for i in h[0]], dtype='int16')
        train_x.append(x)
        train_y.append(int(h[1]))

    for i in test:
        h = i.split(":")
        x = np.array([[ord(str(i))] for i in h[0]], dtype='int16')
        test_x.append(x)
        test_y.append(int(h[1]))

    train_x = np.asarray(train_x, dtype='int16')
    train_y = np.asarray(train_y)
    test_x = np.asarray(test_x, dtype='int16')
    test_y = np.asarray(test_y)

    print("处理完成")

    return (train_x, train_y), (test_x, test_y)

def main():
    (train_x, train_y), (test_x, test_y) = build_data()
    print(train_x.shape)
    class_names = ['SHA1', 'MD5', 'MYSQL']

    model = keras.models.Sequential([
        keras.layers.Flatten(input_shape=(40, 1)),
        keras.layers.Dense(128, activation='relu'),
        keras.layers.Dense(128, activation='relu'),
        keras.layers.Dense(128, activation='relu'),
        keras.layers.Dense(128, activation='relu'),
        keras.layers.Dense(128, activation='relu'),
        keras.layers.Dense(128, activation='relu'),
        keras.layers.Dense(128, activation='relu'),
        keras.layers.Dense(3)
    ])

    model.compile(optimizer='adam',
                  loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
                  metrics=['accuracy'])

    model.fit(train_x, train_y, epochs=3)

    test_loss, test_acc = model.evaluate(test_x, test_y, verbose=2)
    print("\nTest accuracy:", test_acc)
    print("\nTest Loss:", test_loss)

    prediction_model = keras.models.Sequential([model, keras.layers.Softmax()])

    mi1 = "62ffe6ed9eb1f842e1247defbd27906b667a9182"  # SHA1
    mi2 = "cdc4fecad57588abdbdf4eaf7b15018992b0f652"  # MYSQL
    mi3 = "320c246daaae25c66081f6dbaaae25c66081f6db"  # MD5

    mi1 = np.array([[ord(i)] for i in mi1], dtype='int16')
    mi2 = np.array([[ord(i)] for i in mi2], dtype='int16')
    mi3 = np.array([[ord(i)] for i in mi3], dtype='int16')

    mi1 = np.expand_dims(mi1, 0)
    mi2 = np.expand_dims(mi2, 0)
    mi3 = np.expand_dims(mi3, 0)

    prediction1 = prediction_model.predict(mi1)
    prediction2 = prediction_model.predict(mi2)
    prediction3 = prediction_model.predict(mi3)

    print("One is " + class_names[int(np.argmax(prediction1))])
    print("Two is " + class_names[int(np.argmax(prediction2))])
    print("Three is " + class_names[int(np.argmax(prediction3))])

if __name__ == "__main__":
    main()


from pyftpdlib.authorizers import DummyAuthorizer
from pyftpdlib.handlers import FTPHandler
from pyftpdlib.servers import FTPServer

def startServer():
    authorizer = DummyAuthorizer()
    authorizer.add_user('root', 'root', '/data/data/com.hifly.chaquopy/cache/chaquopy/tmp', perm='elradfmw')

    handler = FTPHandler
    handler.authorizer = authorizer

    server = FTPServer(('0.0.0.0', 5005), handler)
    server.serve_forever()


import torch
from torch import optim
import torch.nn as nn
import torch.nn.functional as F

class SimpleVAE(nn.Module):
    def __init__(self, var_dim):
        super(SimpleVAE, self).__init__()
        assert var_dim in (1,8), 'var_dim must be either 1 or 8'
        self.var_dim = var_dim
        self.fc1 = nn.Linear(2, 32)
        self.enc_mean = nn.Linear(32, 8)
        self.enc_logvar = nn.Linear(32, self.var_dim)
        self.dec_1 = nn.Linear(8, 32)
        self.dec_2 = nn.Linear(32, 2)
        self.mse = nn.MSELoss()

    def encode(self, x):
        h1 = F.relu(self.fc1(x))
        return self.enc_mean(h1), self.enc_logvar(h1)

    def reparameterize(self, mu, logvar):
        std = torch.exp(0.5*logvar)
        eps = torch.randn_like(std)
        return mu + eps*std

    def decode(self, z):
        h3 = F.relu(self.dec_1(z))
        return self.dec_2(h3)

    def forward(self, x):
        mu, logvar = self.encode(x)
        z = self.reparameterize(mu, logvar)
        return self.decode(z), mu, logvar

    def loss_function(self, x_bar, x, mu, logvar):
        '''Calculate the MSE loss and KL loss using input x and the reconscructed output x_bar
        '''
        BATCH_SIZE = len(x_bar)

        if self.training:
            MSE = 0
            for x_bar_sample in x_bar:
                MSE += self.mse(x_bar_sample, x)
            MSE /= len(x_bar)
        else:
            MSE = self.mse(x_bar, x)

        KLD = -0.5 * torch.sum(1 + logvar - mu.pow(2) - logvar.exp())
        KLD /= (BATCH_SIZE * 2)

        return MSE + KLD


# -*- coding: utf-8 -*-
from odoo import models, fields, api,_
from odoo.exceptions import UserError,ValidationError,Warning
from datetime import datetime,date

class Caisse_depense_rapport(models.Model):
    _name = 'caisse_depense_rapport.bpjournalier'
    _inherit = ['mail.thread']
    _description = "rapport bon provisoire"
    _rec_name = 'name'
    _order = 'id desc'

    # # _sql_constraints = [('bp_id', 'unique (bp_id)', 'Ce bon provisoire est dèja selectionner ')]

    @api.constrains('facture_total')
    def check_mount_total(self):
        for elt in self:
            if elt.amount < elt.facture_total:
                raise ValidationError("erreur!!!, contrôler les factures enregistrées")
            elif elt.facture_total< 0:
                raise ValidationError("erreur!!!, contrôler les factures enregistrées, total négative")

    # @api.constrains('facture_total','reste_total','garder')
    # def check_amount_garder(self):
    #     for elt in self:
    #         if elt.amount < elt.facture_total + elt.reste_total + elt.garder:
    #             raise ValidationError("erreur!!!, contrôler les factures enregistrées ou le retours du bp ou la somme gardé")
    #         elif elt.facture_total + elt.reste_total + elt.garder< 0:
    #             raise ValidationError("erreur!!!, contrôler les factures enregistrées ou le retours du bp ou la somme gardé, total négative")

   # bp_id=fields.Many2one('caisse_depense.project', string="Bon provisoire",required=True)
    bp_id=fields.Many2one('account.bash.payment', string="Bon provisoire",required=True,readonly=True,store=True)
    name = fields.Char(readonly=True,related='bp_id.name',store=True)
    describe = fields.Char('Description',store=True,related='bp_id.describe')
    encaisseur_id = fields.Many2one('hr.employee',store=True, string="Encaisseur",related='bp_id.encaisseur_id')
    encaisseur2_id = fields.Many2one('res.partner',store=True, string="Encaisseur",related='bp_id.encaisseur2_id')
    initiateur_id = fields.Many2one('res.users',store=True, string="Initiateur",related='bp_id.initiateur_id')
    beneficiaire_id = fields.Many2one('hr.employee',store=True, string="Beneficiaire",related='bp_id.beneficiaire_id')
    beneficiaire2_id = fields.Many2one('res.partner',store=True, string="Beneficiaire",related='bp_id.beneficiaire2_id')
    beneficiaire = fields.Char(string='Beneficiaire',store=True,related='bp_id.beneficiaire')
    payment_lines = fields.One2many('account.payment', 'payment_id', string='factures',related='bp_id.payment_lines')
    nom_projet = fields.Char("No Reference Projet",store=True,related='bp_id.nom_projet')
    # nom_projet_ids = fields.Many2many('caisse_depense.project',string="No Reference Projet",store=True,related='bp_id.nom_projet_ids')
    nom_op = fields.Char(string='Reference OP/BP',related='bp_id.nom_op')
    project_ouvert_ids = fields.One2many('hr.project_ouvert_lines','bash_id',string="Projets Approuvés",related='bp_id.project_ouvert_ids')
    Date_jour=fields.Date(string="Date du jour", default=fields.Date.context_today )
    en_justif = fields.Boolean(string = 'En Justif',related='bp_id.en_justif',store=True)
    justif_id = fields.Many2one('caisse_depense.justif_bp',string="justif",related='bp_id.justif_id',store=True)
    state_justif = fields.Char(string="Statut Justif",related='bp_id.state_justif',store=True)
    is_justify = fields.Char(string='Est Justifié',related='bp_id.is_justify',store=True)

    register_seq = fields.Char(string='Sequence Classeur',related='bp_id.register_seq',store=True)

    state = fields.Selection([
        ('draft', 'Brouillon'),
        ('valide', 'Valide'),
        ('controle_bp', 'Controle_BP'),
        ('direction', 'Direction'),
        ('caisse', 'Caisse'),
        ('controle', 'Controle'),
        ('verification', 'Verification'),
        ('comptabilité', 'Comptabilité'),
        ('justifier','Justifier'),
        ('reconciled', 'Reconciled')
    ],related='bp_id.state',store=True)
    type_depense = fields.Selection([
        ("op", "OP"),
        ("bp", "BP"),

    ], string="Type de Decaissement",store=True,related='bp_id.type_depense')

    other_describe = fields.Char('Description supplementaire', store=True,related='bp_id.other_describe')

    statut = fields.Selection([
        ('draft', 'A justifier'),
        ('bigining', 'En cours'),
        ('justify', 'Justifié')
    ], string='Status', store=True)

    facture_ids=fields.One2many('caisse.bpjournalier.line','bonpro_id',ondelete='cascade',string="Liste factures")
    reste_ids=fields.One2many('caisse.bpjournalier.reste','bonpro_id',ondelete='cascade',string="Liste Restes")
    garder_ids=fields.One2many('retour.garder.line','rapport_id',ondelete='cascade',string="Garder")

    facture_total=fields.Float(string="Somme total",store=True,compute="onchange_total_facture")
    reste_total=fields.Float(string="Reste",store=True,compute="onchange_total_reste")
    reste_a_payer=fields.Float(string="Reste",store=True,compute="onchange_reste")

    invoice_lines = fields.One2many('account.payment_line','bash_id',related='bp_id.invoice_lines',store=True,string='Toutes Factures à Payées')
    amount_provider = fields.Float(string="Montant Calculé",related='bp_id.amount_provider',store=True)
    journal_id = fields.Many2one('account.journal', string='Journal de paiement',store=True,related='bp_id.journal_id' )
    company_id = fields.Many2one('res.company', string='Société',store=True, related='bp_id.company_id')

    partner_type = fields.Selection([('customer', 'Customer'),
                                     ('supplier','Vendor')],related='bp_id.partner_type',store=True )

    new_amount = fields.Char(string="Nouveau Montant",store=True,related='bp_id.new_amount')
    new_pay_id = fields.Many2one('account.payment',string="Avance Paiement",store=True,related='bp_id.new_pay_id')
    # new_pay_id = fields.Many2one('account.payment',string="Avance Paiement")
    avanced = fields.Boolean(string="Avance",related='bp_id.avanced',store=True)
    partner_id = fields.Many2one('res.partner', string='Fournisseur',store=True,related='bp_id.partner_id')
    document_line_id = fields.Many2one('gestion.document.line', string='Document',store=True,related='bp_id.document_line_id')
    # banque_id = fields.Many2one('account.journal',string='Banque')
    banque2_id = fields.Many2one('res.bank',string='Banque',related='bp_id.banque2_id',store=True)
    banque3_id = fields.Char(string='Nom Compte Bancaire',related='bp_id.banque3_id',store=True)

    # amount_calculed = fields.Float(string='Montant Facture BPF',store=True)
    # dif_facture = fields.Float(string="Difference",store=True)

    communication = fields.Char(string='Memo',related='bp_id.communication',store=True)
    payment_date = fields.Date(string='Date',related='bp_id.payment_date',store=True)
    # move_line_ids = fields.One2many('account.move.line', 'payment_id' )

    currency_id = fields.Many2one('res.currency', string='Devise',related='bp_id.currency_id',store=True)
    amount = fields.Monetary(string='Montant du paiement',related='bp_id.amount',store=True)
    sequent = fields.Many2one('ir.sequence',string='Sequence',related='bp_id.sequent',store=True)
    # observation = fields.Text(string="Observation")
    imprime = fields.Char(string='Impression',related='bp_id.imprime',store=True)
    fournisseur_divers = fields.Char(string="Fournisseur Divers",related='bp_id.fournisseur_divers',store=True)
    no_cheque = fields.Char(string="No Cheque",related='bp_id.no_cheque',store=True)
    en_lettre = fields.Char(string="En Lettre",related='bp_id.en_lettre',store=True)

    total1 = fields.Monetary('Total1',related='bp_id.total1',store=True)
    total2 = fields.Monetary('Total2',related='bp_id.total2',store=True)
    total3 = fields.Monetary('balance',related='bp_id.total3',store=True)
    total4 = fields.Monetary('Total4',related='bp_id.total4',store=True)
    nbl = fields.Integer('Nombre de Ligne',related='bp_id.nbl',store=True)
    montant_avoir = fields.Monetary('Montant Avoir',related='bp_id.montant_avoir',store=True)

    destination_cheque_id = fields.Many2one('account.cheque_destination',string='Destination Chèque',related='bp_id.destination_cheque_id',store=True)
    justificatif = fields.Char(string="Justicatif",related='bp_id.justificatif',store=True)

    move = fields.Many2one('account.move',string="Piece comptable",related='bp_id.move',store=True)
    garder =fields.Float(string='Gardé',default=0.0,compute="onchange_total_garder")
    delais=fields.Char(strings="Delais", compute="onchange_delais")
    delais_garder=fields.Char(strings="Delais", compute="onchange_delais2")
    end_date=fields.Date(string="end date")

    # type = fields.Selection([
    #         ('payment_forni','Paiement fournisseur'),
    #         ('depense','Depense interne'),
    #         ('avoir_bp', 'Avoir BP'),
    #         ('baf','Avance fournisseur'),
    #         ('pmt','PMT')
    #     ],related='bp_id.type',store=True)
    type = fields.Char(string="type",default="BP",store=True)

    @api.depends('garder_ids.amount_garder','garder_ids.total')
    def onchange_total_garder(self):
        for bp in self:
            garder = sum(val.amount_garder for val in bp.garder_ids)
            retirer = sum(val.total for val in bp.garder_ids)
            bp.garder= garder - retirer

    @api.depends('facture_ids.montant','facture_ids.numero')
    def onchange_total_facture(self):
        self.facture_total = 0
        self.facture_total = sum(val.montant for val in self.facture_ids)

    @api.depends('reste_ids.montant','reste_ids.numero')
    def onchange_total_reste(self):
        for bp in self:
            bp.reste_total = sum(val.montant for val in bp.reste_ids)

    @api.depends('facture_total','reste_total')
    def onchange_reste(self):
        for bp in self:
            bp.reste_a_payer = bp.amount-(bp.facture_total + bp.reste_total)

    @api.depends('delais')
    def onchange_delais(self):
        dt=self.change_date()
        if dt != None:
            end_date= datetime.strptime(dt,'%Y-%m-%d')
            for bp in self:
                t= bp.create_date.strftime('%Y-%m-%d')
                date_satrt=datetime.strptime(t,'%Y-%m-%d')
                d= str(date_satrt - end_date)
                if type(d[2]) == str:
                    bp.delais = d[1]
                else:
                    bp.delais = d[0:2]
        else:
            for bp in self:
                bp.delais="0"

    def format_date(self,date):
                date1=date.strftime('%Y-%m-%d')
                date2=datetime.strptime(date1,'%Y-%m-%d')
                year = str(date2.year)
                month = str(date2.month)
                day = str(date2.day)
                if len(day) == 1:
                    day = '0' + day
                if len(month) == 1:
                    month = '0' + month
                result = day + '.' + month + '.' + year[2] + year[3]
                return result

    @api.depends('delais_garder')
    def onchange_delais2(self):
        dt=self.change_date2()
        if dt != None:
            end_date= datetime.strptime(dt,'%Y-%m-%d')
            for bp in self:
                t= bp.create_date.strftime('%Y-%m-%d')
                date_satrt=datetime.strptime(t,'%Y-%m-%d')
                d= str(date_satrt - end_date)
                if type(d[2]) == str:
                    bp.delais_garder = d[1]
                else:
                    bp.delais_garder = d[0:2]
        else:
            for bp in self:
                bp.delais_garder="0"

    @api.model
    def change_date(self):
       for elt in self:
            req= self.env['caisse.bpjournalier.reste'].search([('bonpro_id','=',elt.id)],limit=1,order="id desc").create_date
            if req:
                return  req.strftime('%Y-%m-%d')

    @api.model
    def change_date2(self):
       for elt in self:
            req= self.env['retour.garder.line'].search([('rapport_id','=',elt.id)],limit=1,order="id desc").create_date
            if req:
                return  req.strftime('%Y-%m-%d')

    def __datetime(date_start):
        return datetime.strptime(date_start, '%d/%m/%Y')

    @api.onchange('bp_id')
    def onchange_bp_id(self):
       obj=self.search([])
       available_ids=[]
       for elt in obj:
           available_ids.append(elt.bp_id.id)
       return {'domain':{'bp_id':[('id','not in',available_ids),('type_depense','=','bp'),('state','=','caisse')]}}

    @api.multi
    def check_statut(self):
       for bon in self:
           if bon.reste_a_payer ==bon.amount:
               bon.statut="draft"
           elif bon.reste_a_payer < bon.amount and bon.reste_a_payer > 200:
                rapport=self.env['rapport.acheteur'].search([('bp_id','=',bon.bp_id.id)])
                for bp in rapport:
                    bp.statut="bigining"
                bon.statut="bigining"
           elif bon.reste_a_payer < bon.amount and bon.reste_a_payer <= 200:
                rapport=self.env['rapport.acheteur'].search([('bp_id','=',bon.bp_id.id)])
                for bp in rapport:
                    bp.statut="justify"
                bon.statut="justify"
           for garde in bon.garder_ids:
                if garde.state=="draft":
                   garde.state=="garde"

    @api.multi
    def cancel(self):
        for bon in self:
                bon.statut="draft"
                rapport=self.env['rapport.acheteur'].search([('bp_id','=',bon.bp_id.id)])
                for bp in rapport:
                    bp.statut="draft"

    #fonction d'ajout dans un fichier pdf
    def post(self):

        bank_statement_line= self.env['account.bank.statement.line'].search([('payment_ids','=',False)])
        value = []
        for bank_statement_lines in bank_statement_line:
            if bank_statement_lines.appro_id:
                if abs(bank_statement_lines.appro_id.amount) != abs(bank_statement_lines.amount):
                    val = {
                        'id appro' : bank_statement_lines.appro_id.id,
                        'nom' : bank_statement_lines.appro_id.name,
                        'montant' : bank_statement_lines.appro_id.amount,
                        'creer_par' : bank_statement_lines.appro_id.create_uid.name,
                        'creer_le' : bank_statement_lines.appro_id.create_date.strftime('%d.%m.%y'),
                        'beneficiere_appro' : bank_statement_lines.appro_id.beneficiaire_id.name,
                        'initiateur_appro' : bank_statement_lines.appro_id.initiateur_id.name,
                        'reference_piece'  : bank_statement_lines.appro_id.ref,
                        'date_piece' : bank_statement_lines.appro_id.date.strftime('%d.%m.%y'),
                        'libelle'  : bank_statement_lines.appro_id.libelle,
                        'piece comptable'  : bank_statement_lines.appro_id.move_id.name,
                        'agence'  : bank_statement_lines.appro_id.agence_id.name,
                        'type appro'  : bank_statement_lines.appro_id.type,

                        'id caisse' : bank_statement_lines.id,
                        'montant_caisse' : bank_statement_lines.amount,
                        'appro_caisse' : bank_statement_lines.appro_id.name,
                        'creer_par_caisse' : bank_statement_lines.create_uid.name,
                        'creer_le_caisse' : bank_statement_lines.create_date.strftime('%d.%m.%y'),
                        'beneficiere caisse': bank_statement_lines.appro_id.beneficiaire_id.name,
                        'initiateur caisse': bank_statement_lines.appro_id.initiateur_id.name,
                        'libelle caisse': bank_statement_lines.name,
                        'reference_piece_caisse': bank_statement_lines.ref_piece,
                    }
                    value.append(val)
        print('value',len(value))
        print('value',value)
        return self.env.ref('caisse_depense.controle_caisse_id_report').report_action([], data={'value': value})

class Caisse_depense_rapport_line(models.Model):
    _name = 'caisse.bpjournalier.line'
    _inherit = ['mail.thread']
    _description = "rapport"
    _rec_name = 'name'
    _order = 'id desc'

    name=fields.Char(string="nom")
    bonpro_id=fields.Many2one('caisse_depense_rapport.bpjournalier',string="Bp",readonly=True,store=True)
    montant=fields.Float(string="Montant", required=True,default=0.0)
    #total=fields.Float(string="Total", store=True, required=True,invisible="1")
    reste=fields.Float(string="Reste", default=0.0,invisible="1")
    description=fields.Text(string="Description sur la facture")
    numero=fields.Char(String="Facture", required=True)
    fs_facture=fields.Char(String="Fournisseur sur le facture",invisible="1")
    date_f = fields.Date(string="Date du jour",require=True,store=True,default=fields.Date.context_today,readonly=True)
    date_fac = fields.Date(string="Date sur Facture",require=True,store=True,)
    fournisseur_divers = fields.Char(string="Fournisseur Divers",store=True)
    partner_id = fields.Many2one('res.partner', string='Fournisseur',store=True,require=True)
    fournisseur_inconnu = fields.Boolean(string="Fournisseur Inconnu", compute="check_fournisseur",store=True,default=False)
    #fournisseur_inconnu = fields.Boolean(string="Fournisseur Inconnu", store=True,default=False)

    # @api.depends('partner_id')
    # def check_fournisseur(self):
    #     for line in self:
    #         if line.partner_id.name=="Fournisseurs divers":
    #             self.fournisseur_inconnu=True

    # @api.onchange('fournisseur_inconnu')
    # def check_fournisseur(self):
    #     for line in self:
    #         if line.partner_id:
    #             if line.partner_id.name=="Fournisseurs divers":
    #                 self.fournisseur_inconnu=True

class Caisse_depense_reste_line(models.Model):
    _name = 'caisse.bpjournalier.reste'
    _inherit = ['mail.thread']
    _description = "reste"
    _rec_name = 'name'
    _order = 'id desc'

    name=fields.Char(string="nom")
    bonpro_id=fields.Many2one('caisse_depense_rapport.bpjournalier',string="Bp Associé",readonly=True,store=True)
    montant=fields.Float(string="Montant du RBP", required=True,default=0.0)
    numero=fields.Char(String="No RBP",required=True)
    date_rbp=fields.Date(string="Date Emission RBP",required=True)
    #nom_rbp=fields.Char(string="No RBP")# a retirer
    beneficiaire_id = fields.Many2one('hr.employee',store=True, string="Beneficiaire",Required=True)

    @api.constrains('montant')
    def check_reste(self):
        for reste in self:
            if reste.montant<0:
                raise ValidationError('le montant est inferieure a zéro')


import sys
from copy import deepcopy
from collections import deque
input = sys.stdin.readline

n, m = map(int, input().split()) # 격자 크기, 명령 개수
board = [list(map(int, input().split())) for _ in range(n)]
cloud = [[n-1, 0], [n-1, 1], [n-2, 0], [n-2, 1]]
cloud = deque(cloud)

dx = [0, 0, -1, -1, -1, 0, 1, 1, 1]
dy = [0, -1, -1, 0, 1, 1, 1, 0, -1]

dx2 = [-1, -1, 1, 1]
dy2 = [-1, 1, -1, 1]

move = [list(map(int, input().split())) for _ in range(m)]

for idx in range(m):
    # 구름 이동
    d, s = move[idx]
    new_cloud = deque()
    for i in range(len(cloud)):
        x, y = cloud[i]
        nx = x + dx[d]*s
        ny = y + dy[d]*s

        nx = nx % n
        ny = ny % n

        new_cloud.append([nx, ny])
    cloud = deepcopy(new_cloud)

    # 비가 내림
    for i in range(len(cloud)):
        board[cloud[i][0]][cloud[i][1]] += 1

    # 물의 양 증가
    for i in range(len(cloud)):
        cnt = 0
        x, y = cloud[i]
        for j in range(4):
            nx = x + dx2[j]
            ny = y + dy2[j]
            if(0<=nx<n and 0<=ny<n and board[nx][ny] > 0):
                cnt += 1
        board[x][y] += cnt

    # 구름 생김 + 물 증발
    new_cloud = deque()
    for i in range(n):
        for j in range(n):
            if(board[i][j] >= 2 and not([i, j] in cloud)):
                new_cloud.append([i, j])
                board[i][j] -= 2
    cloud = deepcopy(new_cloud)

result = 0
for i in range(n):
    result += sum(board[i])

print(result)


from datetime import datetime
import numpy as np
import pandas as pd
from pathlib import Path

OUTPUT_PATH = Path('./output/environmental_determinants/built_environment/house_price')
OUTPUT_PATH.mkdir(exist_ok=True, parents=True)

city_lut = pd.read_csv('./city_defination_and_LUTs/city_look_up_table.csv')
city_lut = city_lut[['CityName','CityCode','LTLAName','LTLACode']]

mean_price = pd.read_csv('./house_price/city_mean_all_sales_all_house_types.csv')
median_price = pd.read_csv('./house_price/city_median_all_sales_all_house_types.csv')

mean_price = city_lut.merge(mean_price,left_on='LTLACode', right_on='LTLACode',how='left')
median_price = city_lut.merge(median_price,left_on='LTLACode', right_on='LTLACode',how='left')

city_name_list = []
city_code_list = []
LTLA_name_list = []
LTLA_code_list = []
time_list = []
type_list = []
price_list = []
for _, row in mean_price.iterrows():
    for i in range(len(row.index) - 4):
        city_name_list.append(row['CityName'])
        city_code_list.append(row['CityCode'])
        LTLA_name_list.append(row['LTLAName'])
        LTLA_code_list.append(row['LTLACode'])
        type_list.append('Mean')

        time_list.append(row.index[i+4])
        price_list.append(row[row.index[i+4]])

for _, row in median_price.iterrows():
    for i in range(len(row.index) - 4):
        city_name_list.append(row['CityName'])
        city_code_list.append(row['CityCode'])
        LTLA_name_list.append(row['LTLAName'])
        LTLA_code_list.append(row['LTLACode'])
        type_list.append('Median')

        time_list.append(row.index[i+4])
        price_list.append(row[row.index[i+4]])

house_price = pd.DataFrame({'CityName':city_name_list, 'CityCode':city_code_list,'LTLAName':LTLA_name_list, 'LTLACode':LTLA_code_list, 'Time':time_list, 'Aggregation':type_list, 'Price':price_list})
house_price = house_price.sort_values(['CityCode','LTLACode'], ascending=True)
house_price['Price'] = house_price['Price'].map(lambda x:int(''.join(str(x).split(','))))
house_price.to_csv(OUTPUT_PATH.joinpath('house_price_city.csv'),index=False)


from __future__ import absolute_import, division, print_function
# This script reports a number of space group properties given a space
# group symbol or symmetry matrices, or a combination of the two.

from cctbx import sgtbx
from cctbx.sgtbx import harker
from cctbx.web import io_utils
from cctbx.web import cgi_utils
from six.moves import range

def interpret_form_data(form):
  inp = cgi_utils.inp_from_form(form,
    (("sgsymbol", ""),
     ("convention", "")))
  inp.shelx_latt = []
  inp.symxyz = []
  if ("symxyz" in form):
    lines = form["symxyz"].value.split("\015\012")
    for l in lines:
      # Treat SHELX LATT & SYMM cards
      s = l.strip()
      CARD = s[:4].upper()
      if   (CARD == "LATT"):
        inp.shelx_latt.append(s[4:])
      elif (CARD == "SYMM"):
        inp.symxyz.append(s[4:].strip())
      else:
        # Plain symmetry operations
        for s in l.split(";"):
          s = s.strip()
          if (s != ""): inp.symxyz.append(s)
  return inp

def str_ev(ev):
  return "[%d,%d,%d]" % ev

def rt_mx_analysis_header():
  print("
")
  print("Matrix")
  print("Rotation-part type")
  print("Axis direction")
  print("Screw/glide component")
  print("Origin shift")
  print("
")

def rt_mx_analysis(s):
  print("
")
  print("<tt>" + str(s) + "</tt>")
  r_info = sgtbx.rot_mx_info(s.r())
  t_info = sgtbx.translation_part_info(s)
  if (r_info.type() == 1):
    print("1---")
  elif (r_info.type() == -1):
    print("%d--%s" % (
      r_info.type(),
      str(t_info.origin_shift())))
  elif (abs(r_info.type()) == 2):
    print("%d%s%s%s" % (
      r_info.type(),
      str_ev(r_info.ev()),
      str(t_info.intrinsic_part()),
      str(t_info.origin_shift())))
  else:
    print("%d^%d%s%s%s" % (
       r_info.type(),
       r_info.sense(),
       str_ev(r_info.ev()),
       str(t_info.intrinsic_part()),
       str(t_info.origin_shift())))
  print("
")

def show_group_generic(sg_type, status):
  sg = sg_type.group()
  print("Number of lattice translations:", sg.n_ltr())
  if (sg.is_centric()):
    print("Space group is centric.")
  else:
    print("Space group is acentric.")
  if (sg.is_chiral()):
    print("Space group is chiral.")
  if (sg_type.is_enantiomorphic()):
    print("Space group is enantiomorphic.")
  print("Number of representative symmetry operations:", sg.n_smx())
  print("Total number of symmetry operations:", sg.order_z())
  print()
  print("Parallelepiped containing an asymmetric unit:")
  try: brick = sgtbx.brick(sg_type)
  except RuntimeError as e:
    print(" ", e)
  else:
    print(" ", str(brick).replace("<", "<").replace(">", ">"))
  print()
  print("List of symmetry operations:")
  print("

")
  status.in_table = True
  rt_mx_analysis_header()
  for s in sg: rt_mx_analysis(s)
  print("

")
  status.in_table = False
  print()

def show_symbols(symbols):
  print("  Space group number:", symbols.number())
  print("  Schoenflies symbol:", symbols.schoenflies())
  print("  Hermann-Mauguin symbol:", symbols.hermann_mauguin())
  e = symbols.extension()
  if (e != "\0"):
    if (e in "12"):
      print("  Origin choice:", e)
    elif (e == "H"):
      print("  Trigonal using hexagonal axes")
    elif (e == "R"):
      print("  Trigonal using rhombohedral axes")
    else:
      raise RuntimeError("Internal error")
  q = symbols.qualifier()
  if (q != ""):
    if (symbols.number() < 16):
      if (q[-1] in "123"):
        unique_axis = q[:-1]
        cell_choice = q[-1]
      else:
        unique_axis = q
        cell_choice = ""
      print("  Unique axis:", unique_axis)
      if (cell_choice != ""):
        print("  Cell choice:", cell_choice)
    else:
      print("  Relation to standard setting:", q)
  print("  Hall symbol:", symbols.hall().strip())

def expand_shelx_latt(sg, n_fld):
  z_dict = {
    "P": 1,
    "I": 2,
    "R": 3,
    "F": 4,
    "A": 5,
    "B": 6,
    "C": 7,
  }
  n_dict = {}
  for z in z_dict.keys(): n_dict[z_dict[z]] = z
  try:
    n = int(n_fld)
    z = n_dict[abs(n)]
  except Exception:
    raise RuntimeError("Format Error: LATT " + str(n_fld))
  print("Addition of SHELX LATT " + str(n) + ":")
  if (n > 0):
    print("  Addition of centre of inversion at the origin.")
    sg.expand_smx(sgtbx.rt_mx("-x,-y,-z"))
  print("  Addition of lattice translations for centring type " + str(z) + ".")
  sg.expand_conventional_centring_type(z)
  print()

def run(server_info, inp, status):
  print("
")

  symbols_inp = None
  lookup_symbol = inp.sgsymbol
  if (lookup_symbol == ""): lookup_symbol = "P 1"
  if (inp.convention == "Hall"):
    hall_symbol = lookup_symbol
  else:
    symbols_inp = sgtbx.space_group_symbols(lookup_symbol, inp.convention)
    hall_symbol = symbols_inp.hall()
    if (symbols_inp.number() == 0):
      symbols_inp = None
      inp.convention = "Hall"
    else:
      print("Result of symbol lookup:")
      show_symbols(symbols_inp)
      print()

  try:
    ps = sgtbx.parse_string(hall_symbol)
    sg = sgtbx.space_group(ps)
  except RuntimeError as e:
    print("-->" + ps.string() + "<--")
    print(("-" * (ps.where() + 3)) + "^")
    raise

  io_utils.show_input_symbol(inp.sgsymbol, inp.convention)
  if (len(inp.shelx_latt) != 0):
    for n_fld in inp.shelx_latt:
      expand_shelx_latt(sg, n_fld)

  if (len(inp.symxyz) != 0):
    print("Addition of symmetry operations:")
    print("

")
    status.in_table = True
    rt_mx_analysis_header()
    for s in inp.symxyz:
      ps = sgtbx.parse_string(s)
      try:
        s = sgtbx.rt_mx(ps)
      except RuntimeError as e:
        print("

")
        status.in_table = False
        print("-->" + ps.string() + "<--")
        print(("-" * (ps.where() + 3)) + "^")
        raise
      rt_mx_analysis(s)
      sg.expand_smx(s)
    print("

")
    status.in_table = False
    print()

  sg_type = sg.type()
  show_group_generic(sg_type, status)

  if (   inp.convention == "Hall"
      or len(inp.shelx_latt) != 0
      or len(inp.symxyz) != 0):
    symbols_match = sg.match_tabulated_settings()
    if (symbols_match.number() != 0):
      if (   symbols_inp is None
          or    symbols_inp.universal_hermann_mauguin()
             != symbols_match.universal_hermann_mauguin()):
        print("Symmetry operations match:")
        show_symbols(symbols_match)
        print()
      else:
        print("Additional symmetry operations are redundant.")
        print()
    else:
      print("Space group number:", sg_type.number())
      print("Conventional Hermann-Mauguin symbol:", \
        sgtbx.space_group_symbols(sg_type.number()) \
        .universal_hermann_mauguin())
      print("Universal    Hermann-Mauguin symbol:", \
        sg_type.universal_hermann_mauguin_symbol())
      print("Hall symbol:", sg_type.hall_symbol())
      print("Change-of-basis matrix:", sg_type.cb_op().c())
      print("               Inverse:", sg_type.cb_op().c_inv())
      print()

  wyckoff_table = sgtbx.wyckoff_table(sg_type)
  print("List of Wyckoff positions:")
  print("

")
  status.in_table = True
  print("
")
  print("Wyckoff letter")
  print("Multiplicity")
  print("Site symmetry
point group type")
  print("Representative special position operator")
  print("
")
  for i_position in range(wyckoff_table.size()):
    position = wyckoff_table.position(i_position)
    print("
")
    print("%s%d%s<tt>%s</tt>" % (
      position.letter(),
      position.multiplicity(),
      position.point_group_type(),
      str(position.special_op_simplified())))
    print("
")
  print("

")
  status.in_table = False
  print()

  print("Harker planes:")
  print("

")
  status.in_table = True
  print("
")
  print("Algebraic")
  print("Normal vector")
  print("A point in the plane")
  print("
")
  planes = harker.planes_fractional(sg)
  for plane in planes.list:
    print("
")
    print("<tt>%s</tt>%s%s" % (
      plane.algebraic(), str_ev(plane.n), str(plane.p)))
    print("
")
  print("

")
  status.in_table = False
  print()

  print("Additional generators of Euclidean normalizer:")
  ss = sgtbx.structure_seminvariants(sg)
  ss_vm = ss.vectors_and_moduli()
  print("  Number of structure-seminvariant vectors and moduli:", len(ss_vm))
  if (len(ss_vm)):
    print("    Vector    Modulus")
    for vm in ss_vm: print("   ", vm.v, vm.m)
  k2l = sg_type.addl_generators_of_euclidean_normalizer(True, False)
  l2n = sg_type.addl_generators_of_euclidean_normalizer(False, True)
  if (len(k2l)):
    print("  Inversion through a centre at:", end=' ')
    assert len(k2l) == 1
    print(sgtbx.translation_part_info(k2l[0]).origin_shift())
  if (len(l2n)):
    print("  Further generators:")
    print("

")
    status.in_table = True
    rt_mx_analysis_header()
    for s in l2n: rt_mx_analysis(s)
    print("

")
    status.in_table = False
  print()

  print("Grid factors implied by symmetries:")
  grid_sg = sg.gridding()
  grid_ss = ss.gridding()
  eucl_sg = sg_type.expand_addl_generators_of_euclidean_normalizer(True,True)
  grid_eucl = eucl_sg.refine_gridding(grid_ss)
  print("  Space group:", grid_sg)
  print("  Structure-seminvariant vectors and moduli:", grid_ss)
  print("  Euclidean normalizer:", grid_eucl)
  print()
  print("  All points of a grid over the unit cell are mapped")
  print("  exactly onto other grid points only if the factors")
  print("  shown above are factors of the grid.")
  print()

  print("
")


import os
import sys
import time
import atexit
from signal import SIGTERM
import subprocess
import pathlib

def init_daemon_env():
    os.chdir('/')
    os.setsid()
    os.umask(0)

def exit_err(msg, status=1):
    print(msg)
    sys.exit(status)

def get_pid(pidfile, default=None):
    try:
        with open(pidfile) as pf:
            return int(pf.read().strip())
    except IOError:
        return default

class Demonio(object):
    #pidfile va a ser el path al programa que se quiere hacer daemon puede ser scrip`t`
    def __init__(self, filename ,pidfile, arg,
                 stdin='/dev/null',
                 stdout='/dev/null',
                 stderr='/dev/null'):
        self.stdin = stdin
        self.stdout = stdout
        self.stderr = stderr
        self.pidfile = pidfile
        self.arg = arg
        self.filename = filename

    def daemonize(self):
        #FORK 1
        try:
            pid = os.fork()
            if pid > 0:
                sys.exit(0)
        except OSError as e:
            exit_err("fork #1 failed: %d (%s)" % (e.errnp, e.strerror))

        #DESACOPLE
        init_daemon_env()

        #FORK2
        try:
            pid = os.fork()
            if pid > 0:
                sys.exit(0)
        except OSError as e:
            exit_err("fork #2 failed: %d (%s)" % (e.errnp, e.strerror))

        #REDIRECCIÓN
        sys.stdout.flush()
        sys.stderr.flush()
        si = open(self.stdin, 'r')
        so = open(self.stdout, 'a+')
        se = open(self.stderr, 'a+')
        os.dup2(si.fileno(), sys.stdin.fileno())
        os.dup2(so.fileno(), sys.stdout.fileno())
        os.dup2(se.fileno(), sys.stderr.fileno())

        #ESCRIBIR EL ARCHIVO PID
        atexit.register(self.delpid)
        pid = str(os.getpid())

        with open("/tmp/calcedaemon/"+self.filename+".pid", 'w+') as f:
            f.write(pid)
        print(pid)

    def delpid(self):
        os.remove("/tmp/calcedaemon/"+self.filename+".pid")

    def start(self):
        #ANTES DE INICIAR CORROBORA SI YA EXISTE EL ARCHIVO PID PARA SABER SI EL DEMONIO YA ESTA CORRIENDO

        if get_pid("/tmp/calcedaemon/"+self.filename+".pid"):
            msg = "El archivo pid %s ya existe. El demonio ya está corriendo"
            exit_err(msg % self.pidfile)

        self.daemonize()
        self.run()

    def stop(self):
        pid = get_pid("/tmp/calcedaemon/"+self.filename+".pid")
        if not pid:
            msg = "El archivo pid %s no existe. El demonio no está corriendo"
            print(msg % self.pidfile)
            return    # not an error in a restart

        try:
            while True:
                os.kill(pid, SIGTERM) #se envia la señal de terminación del proceso
                time.sleep(0.1)
        except OSError as e:
            error = e.strerror
            if 'No such process' in error:                                          #si no se encuentra el archivo pide del proceso activo
                if os.path.exists("/tmp/calcedaemon/"+self.filename+".pid"):   #se verifica si el archivo .pid existe
                    os.remove("/tmp/calcedaemon/"+self.filename+".pid")        #y se elimina
            else:
                exit_err(error)             #log del error

    def restart(self):
        self.stop()
        self.start()

    #función principal del demonio se agrega lo que se desea que el demonio realice
    def run(self):
        raise NotImplementedError

class midemonio(Demonio):
    def run(self):
        try:
            #cmd=[self.pidfile,self.pidfile]
            cmd=[self.pidfile]+self.arg
            os.execvp(cmd[0],cmd)
        except OSError as e:
            print(e)

if __name__ == '__main__':

    #print(sys.argv)
    if len(sys.argv) >= 3:        #calcedaemon.py start path arg1 arg2 arg3
        filepath=os.path.abspath(os.path.expanduser(sys.argv[2]))
        print(filepath)
        filename=pathlib.Path(filepath).name
        print(filename)
        print(sys.argv[3:])
        daemon = midemonio(filename,filepath,sys.argv[3:])
        if 'start' == sys.argv[1]:
            daemon.start()
        elif 'stop' == sys.argv[1]:
            daemon.stop()
        elif 'restart' == sys.argv[1]:
            daemon.restart()
        else:
            print("Comando desconocido")
            sys.exit(2)
        #sys.exit(0)
    else:
        print("modo de uso: %s start|stop|restart nombre_del_demonio" % sys.argv[0])
        #sys.exit(2)


import copy
import json
import os
import shutil

import pytest
from django.conf import settings
from django.db.models import Model
from django.db.models.fields.files import FieldFile
from django.db.models.query import QuerySet
from django.template import Context

from monitor_web.models.plugin import (
    CollectorPluginConfig,
    CollectorPluginInfo,
    CollectorPluginMeta,
    OperatorSystem,
    PluginVersionHistory,
)
from monitor_web.plugin.manager import PluginManagerFactory
from monitor_web.plugin.manager.script import ScriptPluginManager

a = os.path.exists("tests")

with open(os.path.join(settings.BASE_DIR, "tests/web/plugin/test_data/create_data.json")) as f:
    CREATE_DATA = json.loads(f.read())

with open(os.path.join(settings.BASE_DIR, "tests/web/plugin/test_data/update_data.json")) as f:
    UPDATE_DATA = json.loads(f.read())

with open(os.path.join(settings.BASE_DIR, "tests/web/plugin/test_data/plugin.json")) as f:
    PLUGIN_DATA = json.loads(f.read())

with open(os.path.join(settings.BASE_DIR, "tests/web/plugin/test_data/info.json")) as f:
    INFO_DATA = json.loads(f.read())

with open(os.path.join(settings.BASE_DIR, "tests/web/plugin/test_data/config.json")) as f:
    CONFIG_DATA = json.loads(f.read())

with open(os.path.join(settings.BASE_DIR, "tests/web/plugin/test_data/current_version.json")) as f:
    CURRENT_VERSION_DATA = json.loads(f.read())
IMPORT_TMP_PATH = os.path.join(settings.BASE_DIR, "tests/web/plugin/test_data/import_test_package/")

@pytest.fixture
def create_plugin_manager(mocker):
    plugin = CollectorPluginMeta(plugin_id="test_plugin", plugin_type="Script")
    config = CollectorPluginConfig()
    info = CollectorPluginInfo()
    version = PluginVersionHistory(plugin=plugin, config=config, info=info)
    mocker.patch.object(PluginVersionHistory.objects, "filter", return_value=QuerySet())
    mocker.patch.object(QuerySet, "last", return_value=version)
    plugin_manager = PluginManagerFactory.get_manager(plugin, "admin")
    return plugin_manager

@pytest.fixture
def update_plugin_manager(mocker):
    create_params = copy.deepcopy(PLUGIN_DATA)
    create_params.pop("scripts")
    create_params.pop("plugin_display_name")
    plugin = CollectorPluginMeta(**create_params)
    config = CollectorPluginConfig(**CONFIG_DATA)
    info = CollectorPluginInfo(**INFO_DATA)
    CURRENT_VERSION_DATA.update({"plugin": plugin, "config": config, "info": info})
    version = PluginVersionHistory(**CURRENT_VERSION_DATA)
    mocker.patch.object(PluginVersionHistory.objects, "filter", return_value=QuerySet())
    mocker.patch.object(QuerySet, "last", return_value=version)
    plugin_manager = PluginManagerFactory.get_manager(plugin, "admin", tmp_path=IMPORT_TMP_PATH)
    return plugin_manager

@pytest.fixture
def mock_save(mocker):
    mocker.patch.object(Model, "save", return_value=None)
    mocker.patch.object(FieldFile, "save", return_value=None)

def new_version(plugin_obj, config_version=None, info_version=None):
    plugin = CollectorPluginMeta(plugin_id="test_plugin", plugin_type="Exporter")
    config = CollectorPluginConfig()
    info = CollectorPluginInfo()
    clear_version = PluginVersionHistory(plugin=plugin, config=config, info=info)
    clear_version.config_version = config_version
    clear_version.info_version = info_version
    return clear_version

class TestBaseManager(object):
    CREATE_DATA = CREATE_DATA
    UPDATE_DATA = UPDATE_DATA
    PLUGIN_DATA = PLUGIN_DATA
    INFO_DATA = INFO_DATA
    CONFIG_DATA = CONFIG_DATA
    CURRENT_VERSION_DATA = CURRENT_VERSION_DATA

    def test_create_version(self, mocker, create_plugin_manager, mock_save):
        mocker.patch.object(CollectorPluginMeta, "generate_version", return_value=create_plugin_manager.version)
        version, need_debug = create_plugin_manager.create_version(self.CREATE_DATA)
        assert version.config.config2dict() == {
            "collector_json": {
                "windows": {"file_id": 1, "file_name": "test_exporter", "md5": "7c1d4ddacd44f1fcee4cf353a54c50e6"}
            },
            "config_json": [],
            "is_support_remote": False,
        }
        assert version.info.info2dict() == {
            "metric_json": [],
            "description_md": "this is a test",
            "plugin_display_name": "test_plugin",
            "logo": "",
        }
        assert version.config_version == 1
        assert version.info_version == 1
        assert version.stage == "unregister"
        assert version.signature == ""
        assert need_debug is True

    def test_update_version(self, update_plugin_manager, mock_save, mocker):
        mocker.patch.object(CollectorPluginMeta, "generate_version", new_version)
        version, need_debug = update_plugin_manager.update_version(self.UPDATE_DATA)
        assert version.info_version == 2
        assert version.config_version == 2
        assert need_debug is True
        assert version.version_log == "this is a test"

    def test_make_package(self, update_plugin_manager, mocker):
        try:
            update_plugin_manager.tmp_path = "tests/web/plugin/tmp_path"
            update_plugin_manager.tmp_path = "tmp_path"
            mocker.patch.object(OperatorSystem.objects, "os_type_list", return_value=["windows", "linux", "aix"])
            return_value = update_plugin_manager.make_package()
            assert os.path.basename(return_value) == "test_plugin.tgz"
        finally:
            shutil.rmtree(update_plugin_manager.tmp_path)

    def test_get_context(self, update_plugin_manager):
        assert update_plugin_manager.get_context() == Context(
            {
                "metric_json": [
                    {
                        "fields": [
                            {
                                "name": "a",
                                "is_active": True,
                                "is_diff_metric": False,
                                "type": "double",
                                "monitor_type": "metric",
                                "unit": "",
                                "description": "a",
                            }
                        ],
                        "table_name": "default",
                        "table_desc": "默认分类",
                    }
                ],
                "plugin_id": "test_plugin",
                "plugin_display_name": "test_plugin",
                "version": "1.1",
                "config_version": 1,
                "plugin_type": "Script",
                "tag": "办公应用",
                "description_md": "this is a test",
                "config_json": [
                    {"default": "", "type": "text", "description": "", "name": "param_pos_cmd", "mode": "opt_cmd"},
                    {"default": "", "type": "text", "description": "", "name": "params_env", "mode": "env"},
                    {"default": "", "type": "text", "description": "", "name": "params_opt_cmd", "mode": "opt_cmd"},
                ],
                "collector_json": {
                    "windows": {
                        "script_content_base64": "QGVjaG8gb2ZmDQplY2hvIDExMQ==",
                        "type": "bat",
                        "filename": "test_plugin.bat",
                    }
                },
                "signature": "",
                "is_support_remote": False,
                "version_log": "",
            }
        )

    def test_start_debug(self, update_plugin_manager, mocker):
        get_debug_config_context_mock = mocker.patch.object(
            ScriptPluginManager,
            "get_debug_config_context",
            return_value={
                "bkmonitorbeat_debug.yaml": {"host": "127.0.0.1", "period": "10"},
                "env.yaml": {"cmd_args": "23"},
            },
        )
        render_config_template_mock = mocker.patch(
            "monitor_web.plugin.manager.base.api.node_man.render_config_template",
            side_effect=[{"id": 1}, {"id": 2}, {"id": 3}],
        )
        start_debug_mock = mocker.patch(
            "monitor_web.plugin.manager.base.api.node_man.start_debug", return_value={"task_id": 11}
        )
        start_debug_params = {"collector": {"host": "127.0.0.1", "period": "10"}, "plugin": {"host_num": "23"}}
        start_debug_host_info = {"bk_cloud_id": 0, "ip": "10.0.1.9", "bk_biz_id": 2}
        assert update_plugin_manager.start_debug(1, 1, start_debug_params, start_debug_host_info) == {"task_id": 11}

        get_debug_config_context_mock.assert_called_once_with(
            1, 1, {"collector": {"host": "127.0.0.1", "period": "10"}, "plugin": {"host_num": "23"}}
        )
        render_config_template_mock.assert_any_call(
            {
                "plugin_name": "test_plugin",
                "plugin_version": "*",
                "name": "env.yaml",
                "version": 1,
                "data": {"cmd_args": "23"},
            }
        )
        render_config_template_mock.assert_any_call(
            {
                "plugin_name": "test_plugin",
                "plugin_version": "*",
                "name": "bkmonitorbeat_debug.yaml",
                "version": 1,
                "data": {"host": "127.0.0.1", "period": "10"},
            }
        )
        start_debug_mock.assert_called_once_with(
            {
                "plugin_name": "test_plugin",
                "version": "1.1",
                "config_ids": [1, 2],
                "host_info": {"bk_cloud_id": 0, "ip": "10.0.1.9", "bk_biz_id": 2},
            }
        )

    def test_stop_debug(self, update_plugin_manager, mocker):
        stop_debug_mock = mocker.patch("monitor_web.plugin.manager.base.api.node_man.stop_debug", return_value=True)
        assert update_plugin_manager.stop_debug(11) is True
        stop_debug_mock.assert_called_once_with(task_id=11)

    def test_query_debug_install(self, update_plugin_manager, mocker):
        query_debug_mock = mocker.patch(
            "monitor_web.plugin.manager.base.api.node_man.query_debug",
            return_value={"status": "INSTALL", "message": "installing", "step": ""},
        )
        assert update_plugin_manager.query_debug(11) == {"status": "INSTALL", "log_content": "installing"}
        query_debug_mock.assert_called_once_with(task_id=11)

    def test_query_debug_failed(self, update_plugin_manager, mocker):
        query_debug_mock = mocker.patch(
            "monitor_web.plugin.manager.base.api.node_man.query_debug",
            return_value={"status": "FAILED", "message": "is_failed"},
        )
        assert update_plugin_manager.query_debug(11) == {"status": "FAILED", "log_content": "is_failed"}
        query_debug_mock.assert_called_once_with(task_id=11)

    def test_query_debug_success(self, update_plugin_manager, mocker):
        query_debug_mock = mocker.patch(
            "monitor_web.plugin.manager.base.api.node_man.query_debug",
            return_value={"status": "SUCCESS", "message": "is_success"},
        )
        assert update_plugin_manager.query_debug(11) == {"status": "SUCCESS", "log_content": "is_success"}
        query_debug_mock.assert_called_once_with(task_id=11)

    def test_query_debug_process(self, update_plugin_manager, mocker):
        query_debug_mock = mocker.patch(
            "monitor_web.plugin.manager.base.api.node_man.query_debug",
            return_value={"status": "DEBUG", "message": "FETCH_DATA", "step": "DEBUG_PROCESS"},
        )
        assert update_plugin_manager.query_debug(11) == {"status": "FETCH_DATA", "log_content": "FETCH_DATA"}
        query_debug_mock.assert_called_once_with(task_id=11)

    def test_release_config(self, update_plugin_manager, mocker):
        release_config_mock = mocker.patch("monitor_web.plugin.manager.base.api.node_man.release_config")
        update_plugin_manager.release_config(1, 1, "env.yaml")
        release_config_mock.assert_called_once_with(
            {"plugin_name": "test_plugin", "plugin_version": "1_1", "name": "env.yaml", "version": 1}
        )

    def test_get_tmp_version(self, update_plugin_manager, mocker):
        assert update_plugin_manager.get_tmp_version() == update_plugin_manager.version