commit 70951cc4e25de39f5ad373d6f495a0b3aac4ceb0 Author: JingweiCui Date: Fri Feb 14 11:11:41 2025 +0800 init comit 首次提交 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9b896e8 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +__pycache__ +dist +build +.idea diff --git a/Brisonus_Params_2.0.4.exe.spec b/Brisonus_Params_2.0.4.exe.spec new file mode 100644 index 0000000..8726067 --- /dev/null +++ b/Brisonus_Params_2.0.4.exe.spec @@ -0,0 +1,37 @@ +# -*- mode: python ; coding: utf-8 -*- + + +a = Analysis( + ['main.py'], + pathex=['.\\venv\\Lib\\site-packages\\'], + binaries=[], + datas=[], + hiddenimports=[], + hookspath=[], + hooksconfig={}, + runtime_hooks=[], + excludes=[], + noarchive=False, +) +pyz = PYZ(a.pure) + +exe = EXE( + pyz, + a.scripts, + a.binaries, + a.datas, + [], + name='Brisonus_Params_2.0.4.exe', + debug=False, + bootloader_ignore_signals=False, + strip=False, + upx=True, + upx_exclude=[], + runtime_tmpdir=None, + console=False, + disable_windowed_traceback=False, + argv_emulation=False, + target_arch=None, + codesign_identity=None, + entitlements_file=None, +) diff --git a/HuaYan_Params_2.0.3.exe.spec b/HuaYan_Params_2.0.3.exe.spec new file mode 100644 index 0000000..5369358 --- /dev/null +++ b/HuaYan_Params_2.0.3.exe.spec @@ -0,0 +1,37 @@ +# -*- mode: python ; coding: utf-8 -*- + + +a = Analysis( + ['main.py'], + pathex=['.\\venv\\Lib\\site-packages\\'], + binaries=[], + datas=[], + hiddenimports=[], + hookspath=[], + hooksconfig={}, + runtime_hooks=[], + excludes=[], + noarchive=False, +) +pyz = PYZ(a.pure) + +exe = EXE( + pyz, + a.scripts, + a.binaries, + a.datas, + [], + name='HuaYan_Params_2.0.3.exe', + debug=False, + bootloader_ignore_signals=False, + strip=False, + upx=True, + upx_exclude=[], + runtime_tmpdir=None, + console=False, + disable_windowed_traceback=False, + argv_emulation=False, + target_arch=None, + codesign_identity=None, + entitlements_file=None, +) diff --git a/HuaYan_Params_2.0.4.exe.spec b/HuaYan_Params_2.0.4.exe.spec new file mode 100644 index 0000000..6126e50 --- /dev/null +++ b/HuaYan_Params_2.0.4.exe.spec @@ -0,0 +1,37 @@ +# -*- mode: python ; coding: utf-8 -*- + + +a = Analysis( + ['main.py'], + pathex=['.\\venv\\Lib\\site-packages\\'], + binaries=[], + datas=[], + hiddenimports=[], + hookspath=[], + hooksconfig={}, + runtime_hooks=[], + excludes=[], + noarchive=False, +) +pyz = PYZ(a.pure) + +exe = EXE( + pyz, + a.scripts, + a.binaries, + a.datas, + [], + name='HuaYan_Params_2.0.4.exe', + debug=False, + bootloader_ignore_signals=False, + strip=False, + upx=True, + upx_exclude=[], + runtime_tmpdir=None, + console=False, + disable_windowed_traceback=False, + argv_emulation=False, + target_arch=None, + codesign_identity=None, + entitlements_file=None, +) diff --git a/HuaYan_Params_2.0.exe.spec b/HuaYan_Params_2.0.exe.spec new file mode 100644 index 0000000..939a531 --- /dev/null +++ b/HuaYan_Params_2.0.exe.spec @@ -0,0 +1,37 @@ +# -*- mode: python ; coding: utf-8 -*- + + +a = Analysis( + ['main.py'], + pathex=['.\\venv\\Lib\\site-packages\\'], + binaries=[], + datas=[], + hiddenimports=[], + hookspath=[], + hooksconfig={}, + runtime_hooks=[], + excludes=[], + noarchive=False, +) +pyz = PYZ(a.pure) + +exe = EXE( + pyz, + a.scripts, + a.binaries, + a.datas, + [], + name='HuaYan_Params_2.0.exe', + debug=False, + bootloader_ignore_signals=False, + strip=False, + upx=True, + upx_exclude=[], + runtime_tmpdir=None, + console=False, + disable_windowed_traceback=False, + argv_emulation=False, + target_arch=None, + codesign_identity=None, + entitlements_file=None, +) diff --git a/ParamsDict.yml b/ParamsDict.yml new file mode 100644 index 0000000..39bc5a1 --- /dev/null +++ b/ParamsDict.yml @@ -0,0 +1,193 @@ +- params: + - id: 0 + addr: 0 + label: alpha + name: alpha + type: VAR + details: 参数1的作用是用于调节xxx功能的灵敏度。 + - id: 1 + addr: 1 + label: gamma + name: gamma + type: VAR + details: + - id: 2 + addr: 2 + label: eta + name: eta + type: VAR + details: + - id: 3 + addr: 3 + label: delta + name: delta + type: VAR + details: + - id: 4 + addr: 4 + label: leaky_gain1 + name: leaky_gain1 + type: VAR + details: + - id: 5 + addr: 5 + label: step_gain1 + name: step_gain1 + type: VAR + details: + - id: 6 + addr: 6 + label: leaky_gain2 + name: leaky_gain2 + type: VAR + details: + - id: 7 + addr: 7 + label: step_gain2 + name: step_gain2 + type: VAR + details: + - id: 8 + addr: 8 + label: leaky_gain3 + name: leaky_gain3 + type: VAR + details: + - id: 9 + addr: 9 + label: step_gain3 + name: step_gain3 + type: VAR + details: + - id: 10 + addr: 10 + label: speaker_check_value + name: speaker_check_value + type: VAR + details: + - id: 11 + addr: 11 + label: tran_func_flag + name: tran_func_flag + type: VAR + details: + - id: 12 + addr: 12 + label: input_poi + name: input_poi + type: ARRAY + len: 20 + details: + - id: 13 + addr: 32 + label: output_poi + name: output_poi + type: ARRAY + len: 8 + details: + - id: 14 + addr: 40 + label: output_check + name: output_check + type: ARRAY + len: 3072 + details: + - id: 15 + addr: 3112 + label: ref_check + name: ref_check + type: ARRAY + len: 4068 + details: + - id: 16 + addr: 7220 + label: err_check + name: err_check + type: ARRAY + len: 2048 + details: + - id: 17 + addr: 9768 + label: rnc_off + name: rnc_off + type: VAR + details: + - id: 18 + addr: 9769 + label: refer_num + name: refer_num + type: VAR + details: + - id: 19 + addr: 9770 + label: err_num + name: err_num + type: VAR + details: + - id: 20 + addr: 9771 + label: spk_num + name: spk_num + type: VAR + details: + - id: 21 + addr: 9772 + label: Input_Amplitude + name: Input_Amplitude + type: ARRAY + len: 10 + details: + - id: 22 + addr: 9782 + label: store_mod + name: store_mod + type: VAR + details: + - id: 23 + addr: 9783 + label: Output_threshold + name: Output_threshold + type: VAR + details: + - id: 24 + addr: 9784 + label: Output_amplitude + name: Output_amplitude + type: VAR + details: + - id: 25 + addr: 9785 + label: running_time + name: running_time + type: VAR + details: + - id: 26 + addr: 9786 + label: alpha_10 + name: alpha_10 + type: VAR + details: + - id: 27 + addr: 9787 + label: start_fre_num + name: start_fre_num + type: VAR + details: + - id: 28 + addr: 9788 + label: first_fre_num + name: first_fre_num + type: VAR + details: + - id: 29 + addr: 9789 + label: second_fre_num + name: second_fre_num + type: VAR + details: + - id: 30 + addr: 9790 + label: check_mod + name: check_mod + type: VAR + details: \ No newline at end of file diff --git a/ParamsDict_01.yml b/ParamsDict_01.yml new file mode 100644 index 0000000..7f9eaab --- /dev/null +++ b/ParamsDict_01.yml @@ -0,0 +1,163 @@ +- params: + - id: 0 + addr: 0 + label: alpha + name: alpha + type: VAR + details: 参数1的作用是用于调节xxx功能的灵敏度。 + - id: 1 + addr: 1 + label: gamma + name: gamma + type: VAR + details: + - id: 2 + addr: 2 + label: eta + name: eta + type: VAR + details: + - id: 3 + addr: 3 + label: delta + name: delta + type: VAR + details: + - id: 4 + addr: 4 + label: leaky_gain1 + name: leaky_gain1 + type: VAR + details: + - id: 5 + addr: 5 + label: step_gain1 + name: step_gain1 + type: VAR + details: + - id: 6 + addr: 6 + label: leaky_gain2 + name: leaky_gain2 + type: VAR + details: + - id: 7 + addr: 7 + label: step_gain2 + name: step_gain2 + type: VAR + details: + - id: 8 + addr: 8 + label: leaky_gain3 + name: leaky_gain3 + type: VAR + details: + - id: 9 + addr: 9 + label: step_gain3 + name: step_gain3 + type: VAR + details: + - id: 10 + addr: 10 + label: speaker_check_value + name: speaker_check_value + type: VAR + details: + - id: 11 + addr: 11 + label: tran_func_flag + name: tran_func_flag + type: VAR + details: + - id: 12 + addr: 12 + label: input_poi + name: input_poi + type: ARRAY + len: 20 + details: + - id: 13 + addr: 32 + label: output_poi + name: output_poi + type: ARRAY + len: 8 + details: + - id: 14 + addr: 40 + label: output_check + name: output_check + type: ARRAY + len: 3072 + details: + - id: 15 + addr: 3112 + label: ref_check + name: ref_check + type: ARRAY + len: 4068 + details: + - id: 16 + addr: 7220 + label: err_check + name: err_check + type: ARRAY + len: 2048 + details: + - id: 17 + addr: 9768 + label: rnc_off + name: rnc_off + type: VAR + details: + - id: 18 + addr: 9769 + label: refer_num + name: refer_num + type: VAR + details: + - id: 18 + addr: 9769 + label: refer_num + name: refer_num + type: VAR + details: + - id: 19 + addr: 9770 + label: err_num + name: err_num + type: VAR + details: + - id: 20 + addr: 9771 + label: spk_num + name: spk_num + type: VAR + details: + - id: 21 + addr: 9772 + label: spk_num + name: spk_num + type: ARRAY + len: 10 + details: + - id: 22 + addr: 9782 + label: store_mod + name: store_mod + type: VAR + details: + - id: 23 + addr: 9783 + label: threshold + name: threshold + type: VAR + details: + - id: 24 + addr: 9784 + label: amplitude + name: amplitude + type: VAR + details: \ No newline at end of file diff --git a/br_com_manager.py b/br_com_manager.py new file mode 100644 index 0000000..139597f --- /dev/null +++ b/br_com_manager.py @@ -0,0 +1,2 @@ + + diff --git a/br_com_message.py b/br_com_message.py new file mode 100644 index 0000000..ad1f5e2 --- /dev/null +++ b/br_com_message.py @@ -0,0 +1,59 @@ +import struct + + +class BrComMessage: + SOH = 0x0A + OP_READ = 0 + OP_WRITE = 1 + RES_READ = 100 + RES_WRITE = 101 + + def __init__(self, operation, addr: int, val: float = 0.0): + self.operation = operation + self.addr = addr + self.val = val + + def gen_message(self): + # 消息内容的组成: + # [SOH, operation_code, addr, val, checksum] + msg_pre = [self.SOH, self.operation] + \ + list(struct.pack('H', self.addr)) + \ + list(struct.pack('f', self.val)) + \ + [self.compute_checksum()] + return msg_pre + + def compute_checksum(self): + _sum = self.SOH + _sum += self.operation + + for a_byte in struct.pack(' dict: + try: + with open(filepath, encoding='UTF-8') as f: + modules_data = yaml.load(f, yaml.FullLoader) + except Exception as e: + print(e) + + return modules_data[0]['params'] + + +if __name__ == "__main__": + param_list = load_table()[0]['params'] + + print(param_list[0]) + diff --git a/br_serial_port.py b/br_serial_port.py new file mode 100644 index 0000000..c71b06f --- /dev/null +++ b/br_serial_port.py @@ -0,0 +1,24 @@ +from PySide6.QtSerialPort import QSerialPort +from PySide6.QtCore import QByteArray, Signal, SignalInstance + + +class BrSerialPort(QSerialPort): + signal_data_received: SignalInstance = Signal(str) + signal_data_sent: SignalInstance = Signal() + + def __init__(self, port_name, baud): + super().__init__() + + self.setPortName(port_name) + self.setBaudRate(baud) + + self.open(QSerialPort.OpenModeFlag.ReadWrite) + + def write_data(self, send_data): + self.write(send_data) + self.signal_data_sent.emit() + + def read_data(self): + m_read_data: QByteArray = self.readAll() + m_read_data_str = m_read_data.toStdString() + self.signal_data_received.emit(m_read_data_str) diff --git a/br_widget_arr_details.py b/br_widget_arr_details.py new file mode 100644 index 0000000..7a2151c --- /dev/null +++ b/br_widget_arr_details.py @@ -0,0 +1,96 @@ +from ui_arr_details import Ui_Widget +from PySide6.QtWidgets import QWidget, QTableWidgetItem +from PySide6.QtCore import Slot, Signal, SignalInstance +from param_data import ParamDataArr +from br_com_message import BrComMessage +from br_widget_basic_plot import BrWidgetBasicPlot + +class BrWidgetArrDetails(QWidget, Ui_Widget): + signal_read: SignalInstance = Signal(list) + def __init__(self, parent=None): + super().__init__(parent) + self.setupUi(self) + self.param_data: ParamDataArr = None + # self.tableWidget_val.setRowCount(10) + self.tableWidget_val.setColumnCount(2) + self.tableWidget_val.setHorizontalHeaderLabels(['Addr', 'Value']) + + # self.tableWidget_setval.setRowCount(10) + self.tableWidget_setval.setColumnCount(2) + self.tableWidget_setval.setHorizontalHeaderLabels(['Addr', 'Value']) + + def update_param_info(self, p_data: ParamDataArr): + self.param_data = p_data + print(self.param_data.getval_list) + self.label_addr.setText(str(p_data.addr)) + self.label_name.setText(str(p_data.name)) + self.label_length.setText(str(p_data.size)) + self.label_details.setText(str(p_data.details)) + self.update_table() + + def update_table(self): + self.tableWidget_val.setRowCount(self.param_data.size) + for row in range(0, self.param_data.size): + self.tableWidget_val.setItem( + row, 0, QTableWidgetItem( + str(self.param_data.addr + row) + ) + ) + self.tableWidget_val.setItem( + row, 1, QTableWidgetItem( + str(self.param_data.getval_list[row])) + ) + + + + def update_val_list(self): + + for i in range(0, self.param_data.size): + self.tableWidget_val.setItem(0, i, QTableWidgetItem(str(self.param_data.getval_list[i]))) + + def update_setval_list(self): + for i in range(0, len(self.param_data.setval_list)): + self.tableWidget_setval.setItem(0, i, QTableWidgetItem(str(self.param_data.setval_list[i]))) + + @Slot() + def on_pushButton_write_clicked(self): + print('[write] button clicked!') + + @Slot() + def on_pushButton_read_clicked(self): + print('[read] button clicked!') + # 生成一组读取命令 + _cmd_list = [] + for i in range(0, self.param_data.size): + _cmd_list.append( + BrComMessage( + BrComMessage.OP_READ, + self.param_data.addr + i + ) + ) + self.signal_read.emit(_cmd_list) + + @Slot() + def on_pushButton_valplot_clicked(self): + print('[valpolt] button clicked!') + self.dialog = BrWidgetBasicPlot() + self.dialog.set_chart_data(self.param_data.getval_list, self.param_data.name) + self.dialog.show() + + + @Slot() + def on_pushButton_setvalplot_clicked(self): + print('[setvalplot] button clicked!') + + +if __name__ == "__main__": + from PySide6.QtWidgets import QApplication + import sys + app = QApplication() + widget = BrWidgetArrDetails() + param_data = ParamDataArr(10, 'name', 'NULL', 0, 10) + widget.update_param_info(param_data) + widget.update_val_list() + widget.update_setval_list() + widget.show() + sys.exit(app.exec()) diff --git a/br_widget_basic_plot.py b/br_widget_basic_plot.py new file mode 100644 index 0000000..8bef524 --- /dev/null +++ b/br_widget_basic_plot.py @@ -0,0 +1,99 @@ +from ui_basic_plot import Ui_Dialog +from PySide6.QtWidgets import QDialog, QToolButton, QMenu, QFileDialog +from PySide6.QtGui import QAction + + +class BrWidgetBasicPlot(QDialog, Ui_Dialog): + line_color_list = [(0, 0, 255), (255, 0, 0), (0, 255, 0), (128, 128, 0), (128, 0, 0), (128, 128, 128)] + + def __init__(self): + super().__init__() + self.plot = None + self.chart_data = [] + self.action_delete = None + self.action_saveas = None + self.action_save = None + self.action_load = None + self.action1 = None + self.menu = None + self.line_color_index = 0 + self.setupUi(self) + self.init_ui() + self.init_plot() + + def init_ui(self): + self.toolButton_operation.setPopupMode(QToolButton.ToolButtonPopupMode.InstantPopup) + menu = QMenu(self) + self.action_load = QAction('加载', self) + self.action_load.triggered.connect(self.on_action_load) + self.action_save = QAction('保存', self) + self.action_save.triggered.connect(self.on_action_save) + self.action_saveas = QAction('另存', self) + self.action_saveas.triggered.connect(self.on_action_saveas) + self.action_delete = QAction('删除', self) + self.action_delete.triggered.connect(self.on_action_delete) + menu.addAction(self.action_load) + menu.addAction(self.action_save) + menu.addAction(self.action_saveas) + menu.addAction(self.action_delete) + self.menu = menu + self.toolButton_operation.setMenu(menu) + + def init_plot(self): + self.plot = self.graphicsView.addPlot(title="Chart") + self.plot.showGrid(x=True, y=True) + + self.graphicsView.setBackground('w') + + def on_action_load(self): + print('action1 triggered') + # 实现文件加载 + filename, filetype = QFileDialog.getOpenFileName(self, + "选取文件", + "./", + "Data Files (*.brdata)") # 设置文件扩展名过滤,注意用双分号间隔 + if filename != '': + # 加载文件中的数据 + try: + with open(filename, 'r') as f: + _data = f.read() + data_list = eval(_data) + self.line_color_index += 1 + + except Exception as e: + print(e) + self.plot.plot(data_list, pen=self.line_color_list[self.line_color_index], name=filename) + + def set_chart_data(self, chart_data, param_name): + self.chart_data = chart_data + print(param_name) + self.plot.plot(chart_data, pen=self.line_color_list[self.line_color_index], name=param_name) + + def on_action_save(self): + print('action2 triggered') + # 文件保存功能 + print(self.chart_data) + fileName2, ok2 = QFileDialog.getSaveFileName(self, + "文件保存", + "./", + "Data Files (*.brdata)") + # 用户在文件保存对话框中选择了取消 + if fileName2 != '': + with open(fileName2, 'w') as f: + f.write(str(self.chart_data)) + + def on_action_saveas(self): + print('action3 triggered') + + def on_action_delete(self): + print('action delete triggered') + + +if __name__ == "__main__": + from PySide6.QtWidgets import QApplication + import sys + + app = QApplication() + widget = BrWidgetBasicPlot() + widget.show() + sys.exit(app.exec()) diff --git a/br_widget_var_details.py b/br_widget_var_details.py new file mode 100644 index 0000000..08c6e1d --- /dev/null +++ b/br_widget_var_details.py @@ -0,0 +1,56 @@ +from PySide6.QtWidgets import QWidget +from PySide6.QtCore import Slot, Signal, SignalInstance +from ui_var_details import Ui_Widget +from param_data import ParamDataVar +from br_com_message import BrComMessage + + +class BrWidgetVarDetails(QWidget, Ui_Widget): + signal_read: SignalInstance = Signal(BrComMessage) + signal_write: SignalInstance = Signal(BrComMessage) + + def __init__(self, parent=None): + super().__init__(parent) + self.setupUi(self) + self.param_data: ParamDataVar = None + + def update_param_info(self, p_data: ParamDataVar): + self.param_data = p_data + self.label_addr.setText(str(p_data.addr)) + self.label_name.setText(str(p_data.name)) + self.label_details.setText(str(p_data.details)) + self.lineEdit_var.setText(str(p_data.val())) + + @Slot() + def on_pushButton_read_clicked(self): + print('[read] button clicked!') + + # 生成读取命令,然后触发读取事件 + m_msg = BrComMessage( + BrComMessage.OP_READ, + self.param_data.addr) + + self.signal_read.emit(m_msg) + + @Slot() + def on_pushButton_write_clicked(self): + print('[write] button clicked!') + # 获取数值 + _write_val = float(self.lineEdit_var.text()) + m_msg = BrComMessage( + BrComMessage.OP_WRITE, + self.param_data.addr, + _write_val + ) + self.signal_write.emit(m_msg) + + +if __name__ == "__main__": + from PySide6.QtWidgets import QApplication + import sys + app = QApplication() + widget = BrWidgetVarDetails() + param_data = ParamDataVar(10, 'name', 'NULL', 0) + widget.update_param_info(param_data) + widget.show() + sys.exit(app.exec()) diff --git a/cmd_server.py b/cmd_server.py new file mode 100644 index 0000000..438a19d --- /dev/null +++ b/cmd_server.py @@ -0,0 +1,58 @@ +import time + +from PySide6.QtCore import QThread, QMutex, QWaitCondition, Signal, SignalInstance +from queue import Queue +from br_com_message import BrComMessage + + +class CmdServer(QThread): + signal_write: SignalInstance = Signal(bytes) + # POLL_INTERVAL_TIME = 0.05 + POLL_INTERVAL_TIME = 0.05 + + def __init__(self): + super().__init__() + + self.isPause = True + self.isCancel = False + self.cmd_queue = Queue() + self.con = QWaitCondition() + self.mutex = QMutex() + self.mutex_rw = QMutex() + + def pause(self): + self.isPause = True + + def resume(self): + self.isCancel = False + self.isPause = False + self.con.wakeAll() + print('cmd server thread resume') + + def cancel(self): + self.resume() + self.isCancel = True + + def write(self, p_data: bytes): + self.signal_write.emit(p_data) + + def run(self): + while not self.isCancel: + self.mutex.lock() + if self.isPause: + self.con.wait(self.mutex) + if self.isCancel: + break + self.mutex.unlock() + + if not self.cmd_queue.empty(): + m_msg: BrComMessage = self.cmd_queue.get() + msg_bytes = bytes(m_msg.gen_message()) + self.signal_write.emit(msg_bytes) + + time.sleep(self.POLL_INTERVAL_TIME) + + +if __name__ == "__main__": + server = CmdServer() + server.cmd_queue.put() diff --git a/main.py b/main.py new file mode 100644 index 0000000..23aa76e --- /dev/null +++ b/main.py @@ -0,0 +1,314 @@ +# 这是一个示例 Python 脚本。 +import sys +from PySide6.QtWidgets import QMainWindow, QApplication, QFileDialog, QAbstractItemView, QMessageBox, QWidget +from PySide6.QtGui import QStandardItemModel, QStandardItem +from PySide6.QtCore import Slot, QModelIndex, QTimer +from rnc_tunning import Ui_MainWindow +from br_load_table import load_table +import serial.tools.list_ports +from br_widget_arr_details import BrWidgetArrDetails +from br_widget_var_details import BrWidgetVarDetails +from param_data import VarParamData, ParamData, ParamDataArr, ParamDataVar +from PySide6.QtSerialPort import QSerialPort +from cmd_server import CmdServer +from br_com_message import BrComMessage + +from datetime import datetime +from br_data_manager import BrDataManager + + +TIMER_TIMEOUT = 10 + + +params_filepath = 'ParamsDict.yml' + +default_config = { + 'baud_rate': 115200, + 'polling_interval': 100 +} + + +class PortInfo: + def __init__(self, num: str = '', baud_rate=115200, polling_interval=100): + self.num = num + self.baud_rate = baud_rate + self.polling_interval = polling_interval + + +# load_params_from_file('ParamsDict.yml') + + +class MainWindow(QMainWindow, Ui_MainWindow): + def __init__(self): + super().__init__() + self.widget = None + self.model = None + self.param_list = None + + self.serial_port = None + + self.setupUi(self) + + self.param_data_list = [] + self.data_manager = BrDataManager() + + self.selected_row = 0 + + self.init_tableview() + # self.tableview_load_data() + self.setWindowTitle('Brisonus RNC Tunning Tool 2.0.4') + + self.com = QSerialPort() + + # com read定时器 + self.read_timer: QTimer = QTimer() + self.read_timer.setSingleShot(True) + self.read_timer.timeout.connect(self.read_timer_stop) + + # 消息管理服务器 + self.cmd_server = CmdServer() + self.cmd_server.start() + self.cmd_server.resume() + self.cmd_server.signal_write.connect(self.com_write) + + self.portlist = [] + self.port_info = PortInfo() + self.init_comports() + + self.widget_page_arr = BrWidgetArrDetails(self.widget) + self.widget_page_var = BrWidgetVarDetails(self.widget) + + self.widget_page_var.signal_read.connect(self.on_var_read) + self.widget_page_var.signal_write.connect(self.on_var_write) + + # 定义widget_page_arr的slot + self.widget_page_arr.signal_read.connect(self.on_arr_read) + + # var arr 两个页面都处于隐藏状态 + self.widget_page_arr.hide() + self.widget_page_var.hide() + + # 默认加载可执行路径下 + try: + self.tableview_load_data('ParamsDict.yml') + self.lineEdit_filename.setText('./ParamsDict.yml') + except Exception as e: + print(e) + + def on_var_read(self, p): + if not self.com.isOpen(): + # 弹出对话框提示用户serial port未处于open状态 + self.show_msgbox('系统提示', '未打开端口!') + return + self.cmd_server.cmd_queue.put(p) + print('var widget read signal/callback on_read has been called!') + + def on_var_write(self, p): + print('var widget write signal/callback on_read has been called!') + if not self.com.isOpen(): + # 弹出对话框提示用户serial port未处于open状态 + self.show_msgbox('系统提示', '未打开端口!') + return + self.cmd_server.cmd_queue.put(p) + + def on_arr_read(self, p_cmd_list): + if not self.com.isOpen(): + # 弹出对话框提示用户serial port未处于open状态 + self.show_msgbox('系统提示', '未打开端口!') + return + for _cmd_item in p_cmd_list: + self.cmd_server.cmd_queue.put(_cmd_item) + print('arr widget signal/callback on_read has been called!') + def init_comports(self): + self.lineEdit_baudrate.setText(str(default_config['baud_rate'])) + self.lineEdit_pollingInterval.setText(str(default_config['polling_interval'])) + self.portlist = list(serial.tools.list_ports.comports()) + for port_info in self.portlist: + self.comboBox_comports.addItem(str(port_info)) + + def init_tableview(self): + self.model = QStandardItemModel(0, 3) + self.model.setHorizontalHeaderLabels(['ID', 'Name', 'Value']) + self.tableView.horizontalHeader().setStretchLastSection(True) + self.tableView.setModel(self.model) + self.tableView.setSelectionMode(QAbstractItemView.SelectionMode.SingleSelection) + self.tableView.setSelectionBehavior(QAbstractItemView.SelectionBehavior.SelectRows) + # 设置不能编辑 + self.tableView.setEditTriggers(QAbstractItemView.EditTrigger.NoEditTriggers) + + self.tableView.clicked.connect(self.on_tableview_clicked) + + def tableview_load_data(self, filepath): + param_list = load_table(filepath) + self.data_manager.param_list = [] + # 将param_list转换为param_data_list + for param_item in param_list: + if param_item['type'] == 'VAR': + self.data_manager.param_list.append(ParamDataVar( + param_item['id'], + param_item['addr'], + param_item['name'], + param_item['details'], + 0 + )) + if param_item['type'] == 'ARRAY': + self.data_manager.param_list.append(ParamDataArr( + param_item['id'], + param_item['addr'], + param_item['name'], + param_item['details'], + 1, + param_item['len'] + )) + + for i in range(0, len(self.data_manager.param_list)): + _param = self.data_manager.param_list[i] + print(_param) + self.model.setItem(i, 0, QStandardItem(str(_param.addr))) + self.model.setItem(i, 1, QStandardItem(str(_param.name))) + if _param.type == ParamData.VAR_TYPE_VAR: + _param.item = QStandardItem(str(_param.val())) + self.model.setItem(i, 2, _param.item) + if _param.type == ParamData.VAR_TYPE_ARR: + _param.item = QStandardItem(str('/')) + self.model.setItem(i, 2, _param.item) + + def switch_page(self, page_name): + if page_name == 'var': + self.widget_page_arr.hide() + self.widget_page_var.show() + if page_name == 'arr': + self.widget_page_var.hide() + self.widget_page_arr.show() + + def on_tableview_clicked(self, index: QModelIndex): + print('tableview clicked!', index.row()) + self.selected_row = index.row() + param_index = index.row() + self.update_details_page(param_index) + + def update_details_page(self, param_index): + # 将param的详细信息更新到右侧的详情Widget中进行显示 + m_param_data = self.data_manager.param_list[param_index] + + # 如果点击的是普通变量,则加载普通变量的控件 + if m_param_data.type == VarParamData.VAR_TYPE_VAR: + print(self.widget) + self.update_var_details_ui(m_param_data) + self.switch_page('var') + + # 如果点击的是数组型变量,则加载数据型变量的控件 + if m_param_data.type == VarParamData.VAR_TYPE_ARR: + self.widget_page_arr.update_param_info(m_param_data) + self.switch_page('arr') + + def update_var_details_ui(self, param_data: ParamDataVar): + print('update_var_details_ui') + self.widget_page_var.update_param_info(param_data) + + @Slot() + def on_pushButton_set_clicked(self): + print('[设定] button clicked!') + # 获取所选择的端口号 + _port_index = self.comboBox_comports.currentIndex() + self.port_info.num = self.portlist[_port_index][0] + # 获取所输入的波特率 + self.port_info.baud_rate = int(self.lineEdit_baudrate.text()) + # 设置QSerialPort参数 + self.com.setPortName(self.port_info.num) + self.com.setBaudRate(self.port_info.baud_rate) + self.com.readyRead.connect(self.com_read) + self.com.open(QSerialPort.OpenModeFlag.ReadWrite) + self.show_msgbox('系统提示', ''' +已打开端口: +Port number: %s +Baud rate: %d bps +Polling interval: 100ms + ''' % (self.port_info.num, self.port_info.baud_rate)) + + def show_msgbox(self, title, content): + msg_box = QMessageBox() + msg_box.setWindowTitle(title) + msg_box.setText(content) + msg_box.exec() + + def com_write(self, write_data: bytes): + # 判断serial port是否处于open状态 + if not self.com.isOpen(): + # 弹出对话框提示用户serial port未处于open状态 + self.show_msgbox('系统提示', '未打开端口!') + return + self.com.write(write_data) + # 获取当前系统日期时间 + current_datetime = datetime.now() + formatted_datetime = current_datetime.strftime("[%Y-%m-%d %H:%M:%S]") + write_str = "%s TX:" % formatted_datetime + self.textEdit.append(str(write_str) + write_data.hex(' ')) + self.statusbar.showMessage('读取中...') + # 延时 + + def com_read(self): + # 启动读取定时器 + self.read_timer.start(10) + + def read_timer_stop(self): + recv_data = self.com.readAll().data() + if len(recv_data) < 9: + print('ccc', recv_data) + return + # 对收到的消息进行解析 + res_msg = BrComMessage.resolve_message(list(recv_data)) + if res_msg[0]: + # 更新参数的数值 + _msg = res_msg[1] + if _msg.operation == BrComMessage.RES_READ: + self.data_manager.update_param_val_by_addr( + _msg.addr, + _msg.val + ) + # 更新var page的显示值 + self.statusbar.showMessage('地址[%d]读取完成!' % _msg.addr) + self.update_details_page(self.selected_row) + if _msg.operation == BrComMessage.RES_WRITE: + self.statusbar.showMessage('地址[%d]写入完成!' % _msg.addr) + + current_datetime = datetime.now() + formatted_datetime = current_datetime.strftime("[%Y-%m-%d %H:%M:%S]") + write_str = "%s RX:" % formatted_datetime + self.textEdit.append(str(write_str) + recv_data.hex(' ')) + + @Slot() + def on_pushButton_loadfile_clicked(self): + print('[加载文件] button clicked!') + + dialog = QFileDialog() + if dialog.exec(): + filepath = dialog.selectedFiles()[0] + self.lineEdit_filename.setText(filepath) + self.tableview_load_data(filepath) + + @Slot() + def on_pushButton_update_clicked(self): + print("[更新] button clicked!") + + @Slot() + def on_pushButton_copy_clicked(self): + print("[复制信息] button clicked!") + + def closeEvent(self, event): + reply = QMessageBox.question(self, '系统提示', '系统将退出,是否确认?', + QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No, + QMessageBox.StandardButton.No) + if reply == QMessageBox.StandardButton.Yes: + self.cmd_server.cancel() + self.cmd_server.quit() + self.cmd_server.wait() + else: + event.ignore() + +# 按装订区域中的绿色按钮以运行脚本。 +if __name__ == '__main__': + app = QApplication() + win = MainWindow() + win.show() + sys.exit(app.exec()) diff --git a/main.spec b/main.spec new file mode 100644 index 0000000..2e9c4dd --- /dev/null +++ b/main.spec @@ -0,0 +1,37 @@ +# -*- mode: python ; coding: utf-8 -*- + + +a = Analysis( + ['main.py'], + pathex=['.\\venv\\Lib\\site-packages\\'], + binaries=[], + datas=[], + hiddenimports=[], + hookspath=[], + hooksconfig={}, + runtime_hooks=[], + excludes=[], + noarchive=False, +) +pyz = PYZ(a.pure) + +exe = EXE( + pyz, + a.scripts, + a.binaries, + a.datas, + [], + name='main', + debug=False, + bootloader_ignore_signals=False, + strip=False, + upx=True, + upx_exclude=[], + runtime_tmpdir=None, + console=False, + disable_windowed_traceback=False, + argv_emulation=False, + target_arch=None, + codesign_identity=None, + entitlements_file=None, +) diff --git a/param_data.py b/param_data.py new file mode 100644 index 0000000..7472688 --- /dev/null +++ b/param_data.py @@ -0,0 +1,66 @@ + + +class ParamData: + VAR_TYPE_VAR = 0 + VAR_TYPE_ARR = 1 + + def __init__(self, p_id, addr, name, details, var_type): + self.id = p_id + self.addr = addr + self.name = name + self.details = details + self.type = var_type + + self.item = None + + +class ParamDataVar(ParamData): + def __init__(self, p_id=0, addr=0, name='', details='', var_type=0): + super().__init__(p_id, addr, name, details, var_type) + self._getval = 0 + self._setval = 0 + + def val(self): + return self._getval + + def update_val(self, val): + self._getval = val + self.item.setText(str(self.val())) + + def setval(self): + return self._setval + + def update_setval(self, val): + self._setval = val + + +class ParamDataArr(ParamData): + def __init__(self, p_id=0, addr=0, name='', details='', var_type=0, length=1): + super().__init__(p_id, addr, name, details, var_type) + self.size = length + self.getval_list = [0] * length + self.setval_list = [0] * length + + +class VarParamData: + VAR_TYPE_VAR = 0 + VAR_TYPE_ARR = 1 + + def __init__(self, addr, name, details, var_type): + self.addr = addr + self.name = name + self.details = details + self.type = self.VAR_TYPE_VAR if var_type == 'VAR' else self.VAR_TYPE_ARR + self._current_val = 0 + self._set_val = 0 + + def current_val(self): + return self._current_val + + def set_val(self, set_val): + self._set_val = set_val + + +if __name__ == "__main__": + test_list = [0] * 10 + print(test_list) diff --git a/pyqtgraph_test.py b/pyqtgraph_test.py new file mode 100644 index 0000000..fd67662 --- /dev/null +++ b/pyqtgraph_test.py @@ -0,0 +1,10 @@ +import pyqtgraph as pg + +import pyqtgraph.examples +pyqtgraph.examples.run() + +# win = pg.GraphicsLayoutWidget(show=True) +# +# p2 = win.addPlot(title="test") +# +# pg.exec() \ No newline at end of file diff --git a/rnc_tunning.py b/rnc_tunning.py new file mode 100644 index 0000000..cff7c81 --- /dev/null +++ b/rnc_tunning.py @@ -0,0 +1,189 @@ +# -*- coding: utf-8 -*- + +################################################################################ +## Form generated from reading UI file 'form.ui' +## +## Created by: Qt User Interface Compiler version 6.6.1 +## +## WARNING! All changes made in this file will be lost when recompiling UI file! +################################################################################ + +from PySide6.QtCore import (QCoreApplication, QMetaObject, QRect,) +from PySide6.QtWidgets import (QComboBox, QFrame, QGridLayout, + QHBoxLayout, QLabel, QLineEdit, + QMenuBar, QPushButton, QSizePolicy, + QSpacerItem, QStatusBar, QTableView, QTextEdit, + QVBoxLayout, QWidget) + +class Ui_MainWindow(object): + def setupUi(self, MainWindow): + if not MainWindow.objectName(): + MainWindow.setObjectName(u"MainWindow") + MainWindow.resize(743, 524) + self.centralwidget = QWidget(MainWindow) + self.centralwidget.setObjectName(u"centralwidget") + self.gridLayout = QGridLayout(self.centralwidget) + self.gridLayout.setObjectName(u"gridLayout") + self.verticalLayout_3 = QVBoxLayout() + self.verticalLayout_3.setObjectName(u"verticalLayout_3") + self.horizontalLayout_5 = QHBoxLayout() + self.horizontalLayout_5.setObjectName(u"horizontalLayout_5") + self.label_2 = QLabel(self.centralwidget) + self.label_2.setObjectName(u"label_2") + + self.horizontalLayout_5.addWidget(self.label_2) + + self.line = QFrame(self.centralwidget) + self.line.setObjectName(u"line") + self.line.setFrameShape(QFrame.VLine) + self.line.setFrameShadow(QFrame.Sunken) + + self.horizontalLayout_5.addWidget(self.line) + + self.label_3 = QLabel(self.centralwidget) + self.label_3.setObjectName(u"label_3") + + self.horizontalLayout_5.addWidget(self.label_3) + + self.comboBox_comports = QComboBox(self.centralwidget) + self.comboBox_comports.setObjectName(u"comboBox_comports") + + self.horizontalLayout_5.addWidget(self.comboBox_comports) + + self.label_4 = QLabel(self.centralwidget) + self.label_4.setObjectName(u"label_4") + + self.horizontalLayout_5.addWidget(self.label_4) + + self.lineEdit_baudrate = QLineEdit(self.centralwidget) + self.lineEdit_baudrate.setObjectName(u"lineEdit_baudrate") + + self.horizontalLayout_5.addWidget(self.lineEdit_baudrate) + + self.label_5 = QLabel(self.centralwidget) + self.label_5.setObjectName(u"label_5") + + self.horizontalLayout_5.addWidget(self.label_5) + + self.lineEdit_pollingInterval = QLineEdit(self.centralwidget) + self.lineEdit_pollingInterval.setObjectName(u"lineEdit_pollingInterval") + + self.horizontalLayout_5.addWidget(self.lineEdit_pollingInterval) + + self.pushButton_set = QPushButton(self.centralwidget) + self.pushButton_set.setObjectName(u"pushButton_set") + + self.horizontalLayout_5.addWidget(self.pushButton_set) + + self.horizontalSpacer_2 = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) + + self.horizontalLayout_5.addItem(self.horizontalSpacer_2) + + self.horizontalLayout_5.setStretch(9, 1) + + self.verticalLayout_3.addLayout(self.horizontalLayout_5) + + self.horizontalLayout = QHBoxLayout() + self.horizontalLayout.setObjectName(u"horizontalLayout") + self.verticalLayout = QVBoxLayout() + self.verticalLayout.setObjectName(u"verticalLayout") + self.horizontalLayout_2 = QHBoxLayout() + self.horizontalLayout_2.setObjectName(u"horizontalLayout_2") + self.label = QLabel(self.centralwidget) + self.label.setObjectName(u"label") + + self.horizontalLayout_2.addWidget(self.label) + + self.lineEdit_filename = QLineEdit(self.centralwidget) + self.lineEdit_filename.setObjectName(u"lineEdit_filename") + + self.horizontalLayout_2.addWidget(self.lineEdit_filename) + + self.pushButton_loadfile = QPushButton(self.centralwidget) + self.pushButton_loadfile.setObjectName(u"pushButton_loadfile") + + self.horizontalLayout_2.addWidget(self.pushButton_loadfile) + + + self.verticalLayout.addLayout(self.horizontalLayout_2) + + self.tableView = QTableView(self.centralwidget) + self.tableView.setObjectName(u"tableView") + + self.verticalLayout.addWidget(self.tableView) + + + self.horizontalLayout.addLayout(self.verticalLayout) + + self.verticalLayout_2 = QVBoxLayout() + self.verticalLayout_2.setObjectName(u"verticalLayout_2") + self.horizontalLayout_4 = QHBoxLayout() + self.horizontalLayout_4.setObjectName(u"horizontalLayout_4") + self.pushButton_update = QPushButton(self.centralwidget) + self.pushButton_update.setObjectName(u"pushButton_update") + + self.horizontalLayout_4.addWidget(self.pushButton_update) + + self.pushButton_copy = QPushButton(self.centralwidget) + self.pushButton_copy.setObjectName(u"pushButton_copy") + + self.horizontalLayout_4.addWidget(self.pushButton_copy) + + self.horizontalSpacer = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) + + self.horizontalLayout_4.addItem(self.horizontalSpacer) + + self.horizontalLayout_4.setStretch(2, 1) + + self.verticalLayout_2.addLayout(self.horizontalLayout_4) + + self.widget = QWidget(self.centralwidget) + self.widget.setObjectName(u"widget") + + self.verticalLayout_2.addWidget(self.widget) + + self.textEdit = QTextEdit(self.centralwidget) + self.textEdit.setObjectName(u"textEdit") + + self.verticalLayout_2.addWidget(self.textEdit) + + self.verticalLayout_2.setStretch(1, 4) + self.verticalLayout_2.setStretch(2, 1) + + self.horizontalLayout.addLayout(self.verticalLayout_2) + + self.horizontalLayout.setStretch(0, 1) + self.horizontalLayout.setStretch(1, 3) + + self.verticalLayout_3.addLayout(self.horizontalLayout) + + + self.gridLayout.addLayout(self.verticalLayout_3, 0, 0, 1, 1) + + MainWindow.setCentralWidget(self.centralwidget) + self.menubar = QMenuBar(MainWindow) + self.menubar.setObjectName(u"menubar") + self.menubar.setGeometry(QRect(0, 0, 743, 21)) + MainWindow.setMenuBar(self.menubar) + self.statusbar = QStatusBar(MainWindow) + self.statusbar.setObjectName(u"statusbar") + MainWindow.setStatusBar(self.statusbar) + + self.retranslateUi(MainWindow) + + QMetaObject.connectSlotsByName(MainWindow) + # setupUi + + def retranslateUi(self, MainWindow): + MainWindow.setWindowTitle(QCoreApplication.translate("MainWindow", u"MainWindow", None)) + self.label_2.setText(QCoreApplication.translate("MainWindow", u"\u4e32\u53e3\u8bbe\u7f6e", None)) + self.label_3.setText(QCoreApplication.translate("MainWindow", u"\u7aef\u53e3", None)) + self.label_4.setText(QCoreApplication.translate("MainWindow", u"\u6ce2\u7279\u7387[bps]", None)) + self.label_5.setText(QCoreApplication.translate("MainWindow", u"\u8f6e\u8be2\u95f4\u9694[ms]", None)) + self.pushButton_set.setText(QCoreApplication.translate("MainWindow", u"\u8bbe\u5b9a", None)) + self.label.setText(QCoreApplication.translate("MainWindow", u"\u53c2\u6570\u914d\u7f6e\u6587\u4ef6", None)) + self.pushButton_loadfile.setText(QCoreApplication.translate("MainWindow", u"\u52a0\u8f7d\u6587\u4ef6", None)) + self.pushButton_update.setText(QCoreApplication.translate("MainWindow", u"\u5237\u65b0", None)) + self.pushButton_copy.setText(QCoreApplication.translate("MainWindow", u"\u590d\u5236\u4fe1\u606f", None)) + # retranslateUi + diff --git a/test.brdata b/test.brdata new file mode 100644 index 0000000..febf2ad --- /dev/null +++ b/test.brdata @@ -0,0 +1 @@ +[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] \ No newline at end of file diff --git a/test.data b/test.data new file mode 100644 index 0000000..febf2ad --- /dev/null +++ b/test.data @@ -0,0 +1 @@ +[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] \ No newline at end of file diff --git a/test2.brdata b/test2.brdata new file mode 100644 index 0000000..1828321 --- /dev/null +++ b/test2.brdata @@ -0,0 +1 @@ +[370.0, 649.0, 485.0, 259.0, 952.0, 400.0, 726.0, 403.0, 136.0, 198.0, 823.0, 47.0, 232.0, 199.0, 448.0, 308.0, 213.0, 378.0, 520.0, 333.0, 139.0, 322.0, 870.0, 312.0, 689.0, 878.0, 783.0, 309.0, 431.0, 639.0, 585.0, 958.0, 496.0, 938.0, 665.0, 620.0, 607.0, 20.0, 198.0, 185.0, 903.0, 736.0, 253.0, 742.0, 97.0, 845.0, 5.0, 853.0, 601.0, 39.0, 344.0, 38.0, 431.0, 245.0, 832.0, 998.0, 446.0, 6.0, 281.0, 415.0, 593.0, 317.0, 65.0, 680.0, 819.0, 461.0, 585.0, 794.0, 595.0, 534.0, 285.0, 968.0, 235.0, 514.0, 86.0, 43.0, 161.0, 539.0, 566.0, 120.0, 328.0, 318.0, 22.0, 220.0, 711.0, 748.0, 131.0, 479.0, 854.0, 116.0, 832.0, 582.0, 226.0, 567.0, 144.0, 510.0, 194.0, 400.0, 601.0, 770.0, 114.0, 709.0, 868.0, 984.0, 427.0, 269.0, 869.0, 112.0, 11.0, 360.0, 784.0, 712.0, 238.0, 487.0, 136.0, 498.0, 371.0, 590.0, 96.0, 117.0, 965.0, 680.0, 575.0, 337.0, 477.0, 200.0, 730.0, 769.0, 190.0, 655.0, 947.0, 360.0, 192.0, 747.0, 946.0, 114.0, 770.0, 232.0, 663.0, 80.0, 871.0, 324.0, 5.0, 178.0, 838.0, 448.0, 90.0, 648.0, 3.0, 125.0, 915.0, 834.0, 248.0, 182.0, 990.0, 805.0, 45.0, 173.0, 700.0, 955.0, 48.0, 75.0, 775.0, 597.0, 937.0, 858.0, 824.0, 698.0, 348.0, 405.0, 947.0, 477.0, 834.0, 460.0, 86.0, 780.0, 574.0, 283.0, 708.0, 993.0, 827.0, 133.0, 12.0, 541.0, 546.0, 85.0, 378.0, 731.0, 94.0, 671.0, 36.0, 437.0, 685.0, 698.0, 98.0, 912.0, 848.0, 121.0, 970.0, 632.0, 681.0, 650.0, 336.0, 4.0, 789.0, 212.0, 766.0, 707.0, 117.0, 548.0, 150.0, 174.0, 820.0, 46.0, 839.0, 434.0, 45.0, 489.0, 454.0, 648.0, 56.0, 534.0, 705.0, 543.0, 831.0, 875.0, 262.0, 337.0, 284.0, 828.0, 743.0, 730.0, 445.0, 119.0, 406.0, 112.0, 82.0, 368.0, 560.0, 888.0, 700.0, 295.0, 841.0, 191.0, 201.0, 148.0, 584.0, 165.0, 259.0, 360.0, 198.0, 373.0, 789.0, 364.0, 174.0, 50.0, 885.0, 533.0, 10.0, 323.0, 891.0, 927.0, 640.0, 193.0, 192.0, 53.0, 939.0, 183.0, 44.0, 83.0, 345.0, 927.0, 964.0, 646.0, 282.0, 396.0, 17.0, 745.0, 692.0, 531.0, 921.0, 411.0, 295.0, 620.0, 581.0, 167.0, 52.0, 448.0, 901.0, 997.0, 742.0, 941.0, 106.0, 108.0, 965.0, 706.0, 52.0, 837.0, 831.0, 23.0, 692.0, 420.0, 687.0, 75.0, 350.0, 733.0, 524.0, 529.0, 201.0, 200.0, 66.0, 632.0, 641.0, 265.0, 920.0, 180.0, 809.0, 938.0, 974.0, 239.0, 328.0, 411.0, 627.0, 486.0, 31.0, 610.0, 827.0, 240.0, 411.0, 474.0, 513.0, 563.0, 778.0, 234.0, 469.0, 20.0, 580.0, 334.0, 614.0, 317.0, 140.0, 868.0, 399.0, 296.0, 822.0, 657.0, 210.0, 623.0, 16.0, 598.0, 749.0, 398.0, 578.0, 18.0, 951.0, 591.0, 954.0, 599.0, 742.0, 25.0, 352.0, 60.0, 974.0, 267.0, 282.0, 105.0, 333.0, 905.0, 408.0, 444.0, 891.0, 499.0, 75.0, 371.0, 611.0, 111.0, 236.0, 559.0, 149.0, 617.0, 547.0, 925.0, 98.0, 670.0, 101.0, 790.0, 185.0, 341.0, 211.0, 610.0, 271.0, 919.0, 977.0, 398.0, 112.0, 631.0, 457.0, 140.0, 483.0, 928.0, 270.0, 624.0, 169.0, 747.0, 148.0, 862.0, 647.0, 204.0, 570.0, 416.0, 389.0, 905.0, 122.0, 455.0, 897.0, 611.0, 47.0, 713.0, 935.0, 766.0, 177.0, 538.0, 377.0, 409.0, 124.0, 339.0, 399.0, 178.0, 157.0, 998.0, 715.0, 400.0, 961.0, 676.0, 192.0, 868.0, 201.0, 29.0, 807.0, 842.0, 400.0, 155.0, 479.0, 515.0, 13.0, 313.0, 112.0, 240.0, 184.0, 123.0, 863.0, 888.0, 822.0, 73.0, 956.0, 803.0, 456.0, 453.0, 342.0, 277.0, 679.0, 285.0, 597.0, 648.0, 637.0, 342.0, 20.0, 376.0, 438.0, 95.0, 343.0, 564.0, 776.0, 203.0, 415.0, 353.0, 855.0, 682.0, 50.0, 536.0, 614.0, 790.0, 923.0, 51.0, 766.0, 34.0, 326.0, 618.0, 752.0, 634.0, 76.0, 478.0, 250.0, 240.0, 113.0, 613.0, 223.0, 29.0, 8.0, 998.0, 565.0, 662.0, 126.0, 742.0, 674.0, 161.0, 824.0, 735.0, 662.0, 476.0, 554.0, 99.0, 38.0, 659.0, 385.0, 847.0, 488.0, 52.0, 18.0, 285.0, 431.0, 2.0, 238.0, 75.0, 618.0, 872.0, 938.0, 484.0, 370.0, 92.0, 865.0, 728.0, 799.0, 32.0, 777.0, 845.0, 85.0, 982.0, 755.0, 365.0, 599.0, 760.0, 403.0, 964.0, 582.0, 540.0, 269.0, 141.0, 11.0, 406.0, 553.0, 868.0, 412.0, 129.0, 16.0, 190.0, 784.0, 762.0, 567.0, 977.0, 159.0, 685.0, 263.0, 397.0, 475.0, 739.0, 730.0, 640.0, 574.0, 858.0, 991.0, 837.0, 941.0, 836.0, 315.0, 891.0, 351.0, 364.0, 919.0, 767.0, 323.0, 472.0, 937.0, 808.0, 737.0, 170.0, 7.0, 766.0, 930.0, 185.0, 557.0, 291.0, 999.0, 253.0, 521.0, 379.0, 139.0, 396.0, 217.0, 671.0, 184.0, 612.0, 578.0, 657.0, 543.0, 407.0, 850.0, 474.0, 193.0, 995.0, 146.0, 679.0, 75.0, 974.0, 271.0, 456.0, 507.0, 592.0, 652.0, 212.0, 910.0, 872.0, 436.0, 828.0, 713.0, 10.0, 922.0, 851.0, 147.0, 237.0, 762.0, 919.0, 442.0, 632.0, 557.0, 138.0, 980.0, 583.0, 483.0, 630.0, 993.0, 318.0, 252.0, 623.0, 376.0, 72.0, 484.0, 984.0, 384.0, 459.0, 787.0, 311.0, 779.0, 298.0, 228.0, 461.0, 70.0, 624.0, 255.0, 976.0, 218.0, 148.0, 100.0, 40.0, 991.0, 951.0, 926.0, 206.0, 77.0, 158.0, 495.0, 511.0, 537.0, 450.0, 425.0, 1.0, 785.0, 748.0, 586.0, 391.0, 170.0, 930.0, 79.0, 399.0, 288.0, 192.0, 999.0, 343.0, 185.0, 818.0, 685.0, 87.0, 803.0, 762.0, 832.0, 424.0, 775.0, 102.0, 3.0, 349.0, 99.0, 208.0, 197.0, 476.0, 190.0, 229.0, 683.0, 810.0, 337.0, 393.0, 770.0, 416.0, 722.0, 758.0, 347.0, 341.0, 323.0, 102.0, 935.0, 480.0, 676.0, 830.0, 194.0, 629.0, 40.0, 198.0, 61.0, 619.0, 491.0, 642.0, 784.0, 820.0, 944.0, 74.0, 469.0, 966.0, 174.0, 213.0, 305.0, 104.0, 996.0, 114.0, 418.0, 994.0, 461.0, 23.0, 524.0, 109.0, 835.0, 236.0, 377.0, 583.0, 240.0, 773.0, 982.0, 320.0, 464.0, 236.0, 19.0, 566.0, 119.0, 398.0, 891.0, 142.0, 756.0, 292.0, 783.0, 414.0, 572.0, 322.0, 657.0, 936.0, 174.0, 241.0, 157.0, 11.0, 908.0, 302.0, 835.0, 253.0, 874.0, 285.0, 608.0, 978.0, 806.0, 551.0, 77.0, 77.0, 612.0, 439.0, 805.0, 170.0, 329.0, 847.0, 77.0, 760.0, 694.0, 37.0, 854.0, 220.0, 432.0, 559.0, 507.0, 248.0, 503.0, 292.0, 114.0, 406.0, 71.0, 235.0, 572.0, 385.0, 542.0, 582.0, 814.0, 912.0, 362.0, 827.0, 246.0, 16.0, 169.0, 963.0, 306.0, 372.0, 924.0, 881.0, 60.0, 195.0, 266.0, 554.0, 248.0, 316.0, 635.0, 136.0, 940.0, 801.0, 971.0, 333.0, 536.0, 561.0, 104.0, 638.0, 848.0, 474.0, 655.0, 677.0, 493.0, 182.0, 606.0, 668.0, 948.0, 805.0, 545.0, 641.0, 715.0, 813.0, 389.0, 325.0, 444.0, 754.0, 189.0, 460.0, 739.0, 675.0, 339.0, 212.0, 784.0, 888.0, 169.0, 832.0, 680.0, 222.0, 430.0, 723.0, 47.0, 403.0, 507.0, 652.0, 722.0, 880.0, 135.0, 363.0, 852.0, 297.0, 181.0, 114.0, 346.0, 625.0, 508.0, 699.0, 516.0, 7.0, 955.0, 185.0, 589.0, 168.0, 153.0, 336.0, 829.0, 969.0, 789.0, 153.0, 328.0, 814.0, 810.0, 153.0, 197.0, 485.0, 676.0, 117.0, 327.0, 750.0, 454.0, 562.0, 940.0, 763.0, 565.0, 55.0, 34.0, 319.0, 413.0, 91.0, 750.0, 431.0, 819.0, 519.0, 393.0, 536.0, 417.0, 74.0, 989.0, 550.0, 974.0, 893.0, 444.0, 998.0, 856.0, 349.0, 680.0, 56.0, 603.0, 946.0, 226.0, 40.0, 411.0, 871.0, 564.0, 258.0, 905.0, 53.0, 458.0, 424.0, 5.0, 700.0, 334.0, 245.0, 157.0, 117.0, 559.0, 289.0, 51.0, 884.0, 890.0, 350.0, 837.0, 590.0, 520.0, 331.0, 401.0, 721.0, 124.0, 486.0, 295.0, 918.0, 361.0, 647.0, 130.0, 773.0, 478.0, 543.0, 874.0, 779.0, 575.0, 752.0, 802.0, 302.0, 803.0, 226.0, 644.0, 702.0, 447.0, 453.0, 828.0, 853.0, 490.0, 553.0, 420.0, 970.0, 339.0, 700.0, 970.0, 988.0, 339.0, 41.0, 777.0, 911.0, 34.0, 921.0, 720.0, 760.0, 169.0, 894.0, 353.0, 118.0, 219.0, 273.0, 353.0, 436.0, 406.0, 89.0, 147.0, 280.0, 408.0, 124.0, 863.0, 976.0, 790.0, 81.0, 607.0, 352.0, 346.0, 204.0, 607.0, 97.0, 803.0, 389.0, 404.0, 338.0, 930.0, 190.0, 707.0, 753.0, 987.0, 256.0, 968.0, 187.0, 692.0, 369.0, 900.0, 488.0, 996.0, 280.0, 89.0, 95.0, 499.0, 134.0, 66.0, 233.0, 128.0, 79.0, 918.0, 482.0, 738.0, 518.0, 976.0, 822.0, 805.0, 174.0, 600.0, 666.0, 911.0, 423.0, 339.0, 794.0, 14.0, 453.0, 204.0, 271.0, 208.0, 86.0, 658.0, 175.0, 911.0, 918.0, 623.0, 148.0, 496.0, 185.0, 626.0, 803.0, 649.0, 181.0, 589.0, 320.0, 421.0, 140.0, 920.0, 420.0, 600.0, 100.0, 511.0, 4.0, 121.0, 765.0, 986.0, 451.0, 145.0, 155.0, 798.0, 69.0, 464.0, 293.0, 272.0, 126.0, 868.0, 217.0, 894.0, 114.0, 557.0, 738.0, 521.0, 676.0, 55.0, 819.0, 955.0, 404.0, 211.0, 982.0, 709.0, 451.0, 269.0, 765.0, 844.0, 366.0, 413.0, 747.0, 784.0, 65.0, 950.0, 990.0, 195.0, 755.0, 885.0, 187.0, 51.0, 455.0, 986.0, 289.0, 541.0, 506.0, 993.0, 73.0, 777.0, 96.0, 354.0, 997.0, 206.0, 822.0, 602.0, 429.0, 2.0, 732.0, 177.0, 437.0, 58.0, 675.0, 815.0, 696.0, 495.0, 905.0, 700.0, 953.0, 748.0, 182.0, 394.0, 524.0, 376.0, 272.0, 530.0, 906.0, 443.0, 348.0, 611.0, 622.0, 408.0, 798.0, 99.0, 891.0, 817.0, 268.0, 770.0, 753.0, 490.0, 906.0, 813.0, 834.0, 188.0, 459.0, 288.0, 34.0, 217.0, 891.0, 132.0, 107.0, 239.0, 967.0, 910.0, 412.0, 647.0, 631.0, 71.0, 842.0, 595.0, 441.0, 636.0, 718.0, 499.0, 526.0, 840.0, 140.0, 137.0, 983.0, 439.0, 345.0, 155.0, 702.0, 176.0, 920.0, 527.0, 261.0, 929.0, 255.0, 964.0, 871.0, 38.0, 177.0, 384.0, 155.0, 67.0, 959.0, 926.0, 699.0, 61.0, 355.0, 332.0, 57.0, 172.0, 38.0, 494.0, 276.0, 363.0, 376.0, 902.0, 40.0, 835.0, 985.0, 768.0, 24.0, 427.0, 964.0, 180.0, 914.0, 694.0, 131.0, 674.0, 578.0, 713.0, 854.0, 538.0, 833.0, 435.0, 715.0, 409.0, 672.0, 9.0, 354.0, 486.0, 797.0, 900.0, 415.0, 104.0, 470.0, 558.0, 931.0, 982.0, 943.0, 129.0, 704.0, 750.0, 108.0, 868.0, 248.0, 243.0, 938.0, 225.0, 855.0, 757.0, 833.0, 302.0, 653.0, 129.0, 112.0, 653.0, 519.0, 927.0, 162.0, 632.0, 583.0, 113.0, 422.0, 627.0, 438.0, 699.0, 166.0, 329.0, 158.0, 351.0, 259.0, 14.0, 886.0, 779.0, 805.0, 334.0, 297.0, 635.0, 811.0, 405.0, 363.0, 977.0, 782.0, 704.0, 142.0, 839.0, 283.0, 478.0, 97.0, 921.0, 207.0, 180.0, 527.0, 876.0, 810.0, 289.0, 206.0, 229.0, 74.0, 705.0, 782.0, 681.0, 221.0, 461.0, 716.0, 305.0, 169.0, 320.0, 904.0, 419.0, 693.0, 407.0, 933.0, 495.0, 785.0, 355.0, 157.0, 640.0, 424.0, 883.0, 197.0, 355.0, 131.0, 169.0, 355.0, 672.0, 79.0, 414.0, 500.0, 785.0, 538.0, 859.0, 847.0, 918.0, 729.0, 67.0, 514.0, 116.0, 23.0, 135.0, 735.0, 17.0, 561.0, 975.0, 801.0, 963.0, 268.0, 249.0, 406.0, 61.0, 466.0, 236.0, 308.0, 434.0, 524.0, 813.0, 255.0, 636.0, 362.0, 176.0, 396.0, 857.0, 396.0, 358.0, 373.0, 411.0, 600.0, 122.0, 730.0, 888.0, 299.0, 459.0, 203.0, 796.0, 4.0, 805.0, 257.0, 990.0, 989.0, 570.0, 20.0, 372.0, 53.0, 577.0, 944.0, 152.0, 205.0, 13.0, 553.0, 940.0, 157.0, 155.0, 129.0, 767.0, 255.0, 628.0, 224.0, 563.0, 989.0, 522.0, 156.0, 822.0, 914.0, 972.0, 860.0, 928.0, 264.0, 588.0, 373.0, 193.0, 147.0, 99.0, 989.0, 827.0, 630.0, 153.0, 430.0, 599.0, 590.0, 611.0, 163.0, 934.0, 143.0, 672.0, 332.0, 596.0, 546.0, 147.0, 502.0, 896.0, 229.0, 310.0, 8.0, 787.0, 766.0, 810.0, 833.0, 943.0, 433.0, 649.0, 445.0, 525.0, 883.0, 516.0, 199.0, 604.0, 694.0, 62.0, 422.0, 929.0, 193.0, 507.0, 972.0, 581.0, 242.0, 85.0, 432.0, 236.0, 641.0, 422.0, 799.0, 30.0, 68.0, 309.0, 70.0, 795.0, 703.0, 100.0, 726.0, 384.0, 296.0, 484.0, 115.0, 520.0, 339.0, 863.0, 278.0, 606.0, 741.0, 23.0, 660.0, 235.0, 538.0, 50.0, 390.0, 17.0, 358.0, 289.0, 718.0, 765.0, 72.0, 757.0, 339.0, 922.0, 546.0, 181.0, 831.0, 331.0, 213.0, 386.0, 167.0, 763.0, 514.0, 112.0, 260.0, 19.0, 350.0, 381.0, 236.0, 837.0, 895.0, 936.0, 928.0, 543.0, 383.0, 996.0, 443.0, 598.0, 874.0, 668.0, 91.0, 364.0, 560.0, 770.0, 696.0, 966.0, 21.0, 517.0, 176.0, 721.0, 198.0, 708.0, 898.0, 783.0, 222.0, 233.0, 290.0, 722.0, 694.0, 93.0, 757.0, 842.0, 636.0, 227.0, 890.0, 654.0, 910.0, 662.0, 138.0, 819.0, 332.0, 988.0, 193.0, 64.0, 427.0, 203.0, 222.0, 656.0, 688.0, 653.0, 300.0, 675.0, 104.0, 656.0, 391.0, 51.0, 333.0, 536.0, 543.0, 328.0, 432.0, 872.0, 151.0, 164.0, 327.0, 361.0, 645.0, 717.0, 955.0, 475.0, 864.0, 345.0, 647.0, 148.0, 918.0, 197.0, 219.0, 3.0, 475.0, 279.0, 633.0, 1.0, 637.0, 446.0, 761.0, 275.0, 279.0, 300.0, 971.0, 823.0, 654.0, 926.0, 363.0, 105.0, 666.0, 49.0, 515.0, 406.0, 365.0, 201.0, 465.0, 176.0, 229.0, 111.0, 684.0, 718.0, 529.0, 21.0, 282.0, 453.0, 812.0, 394.0, 24.0, 775.0, 347.0, 408.0, 284.0, 85.0, 65.0, 51.0, 930.0, 745.0, 818.0, 845.0, 3.0, 891.0, 959.0, 224.0, 158.0, 643.0, 657.0, 710.0, 893.0, 312.0, 875.0, 88.0, 753.0, 128.0, 966.0, 953.0, 924.0, 354.0, 748.0, 209.0, 906.0, 696.0, 248.0, 530.0, 831.0, 768.0, 333.0, 842.0, 322.0, 967.0, 883.0, 526.0, 336.0, 213.0, 147.0, 132.0, 750.0, 950.0, 296.0, 806.0, 791.0, 165.0, 718.0, 648.0, 217.0, 527.0, 958.0, 980.0, 209.0, 54.0, 933.0, 168.0, 883.0, 645.0, 454.0, 760.0, 986.0, 909.0, 375.0, 984.0, 144.0, 406.0, 127.0, 922.0, 212.0, 168.0, 888.0, 539.0, 389.0, 768.0, 251.0, 99.0, 788.0, 952.0, 93.0, 574.0, 417.0, 283.0, 649.0, 241.0, 931.0, 336.0, 26.0, 825.0, 6.0, 249.0, 52.0, 108.0, 682.0, 712.0, 482.0, 419.0, 22.0, 182.0, 775.0, 775.0, 566.0, 475.0, 744.0, 111.0, 846.0, 39.0, 811.0, 83.0, 29.0, 384.0, 134.0, 415.0, 822.0, 750.0, 470.0, 385.0, 206.0, 410.0, 967.0, 491.0, 458.0, 684.0, 642.0, 770.0, 731.0, 75.0, 938.0, 641.0, 157.0, 57.0, 958.0, 593.0, 933.0, 176.0, 637.0, 548.0, 243.0, 333.0, 237.0, 507.0, 579.0, 923.0, 440.0, 219.0, 580.0, 383.0, 136.0, 937.0, 848.0, 331.0, 730.0, 698.0, 152.0, 834.0, 987.0, 187.0, 916.0, 550.0, 204.0, 954.0, 109.0, 567.0, 589.0, 376.0, 538.0, 112.0, 108.0, 905.0, 582.0, 410.0, 492.0, 360.0, 250.0, 656.0, 498.0, 446.0, 436.0, 138.0, 9.0, 688.0, 314.0, 810.0, 119.0, 690.0, 185.0, 646.0, 190.0, 516.0, 636.0, 976.0, 298.0, 759.0, 959.0, 512.0, 761.0, 222.0, 383.0, 809.0, 912.0, 135.0, 514.0, 46.0, 842.0, 821.0, 119.0, 983.0, 862.0, 303.0, 951.0, 504.0, 532.0, 632.0, 328.0, 498.0, 60.0, 316.0, 534.0, 500.0, 909.0, 616.0, 449.0, 401.0, 523.0, 489.0, 798.0, 333.0, 389.0, 525.0, 74.0, 607.0, 396.0, 256.0, 815.0, 471.0, 785.0, 562.0, 734.0, 968.0, 696.0, 456.0, 816.0, 924.0, 350.0, 862.0, 991.0, 844.0, 244.0, 518.0, 667.0, 826.0, 170.0, 598.0, 23.0, 676.0, 920.0, 23.0, 718.0, 1.0, 304.0, 589.0, 851.0, 30.0, 592.0, 795.0, 882.0, 780.0, 131.0, 73.0, 411.0, 895.0, 984.0, 820.0, 228.0, 721.0, 813.0, 543.0, 7.0, 327.0, 601.0, 264.0, 680.0, 471.0, 170.0, 329.0, 60.0, 839.0, 100.0, 549.0, 921.0, 443.0, 53.0, 213.0, 803.0, 317.0, 494.0, 643.0, 60.0, 815.0, 618.0, 764.0, 303.0, 455.0, 364.0, 86.0, 474.0, 345.0, 521.0, 996.0, 962.0, 377.0, 221.0, 226.0, 194.0, 194.0, 357.0, 158.0, 514.0, 901.0, 605.0, 112.0, 676.0, 855.0, 752.0, 742.0, 22.0, 537.0, 211.0, 253.0, 549.0, 418.0, 306.0, 124.0, 182.0, 879.0, 91.0, 463.0, 913.0, 483.0, 880.0, 885.0, 594.0, 883.0, 933.0, 953.0, 287.0, 337.0, 665.0, 227.0, 194.0, 376.0, 701.0, 239.0, 459.0, 348.0, 594.0, 330.0, 407.0, 735.0, 778.0, 172.0, 601.0, 929.0, 837.0, 897.0, 465.0, 883.0, 303.0, 952.0, 342.0, 354.0, 685.0] \ No newline at end of file diff --git a/ui_arr_details.py b/ui_arr_details.py new file mode 100644 index 0000000..a891733 --- /dev/null +++ b/ui_arr_details.py @@ -0,0 +1,171 @@ +# -*- coding: utf-8 -*- + +################################################################################ +## Form generated from reading UI file 'form.ui' +## +## Created by: Qt User Interface Compiler version 6.6.1 +## +## WARNING! All changes made in this file will be lost when recompiling UI file! +################################################################################ + +from PySide6.QtCore import (QCoreApplication, QMetaObject) +from PySide6.QtWidgets import (QFormLayout, QGridLayout, QHBoxLayout, QLabel, QPushButton, QSizePolicy, + QSpacerItem, QTableWidget, QVBoxLayout,) + +class Ui_Widget(object): + def setupUi(self, Widget): + if not Widget.objectName(): + Widget.setObjectName(u"Widget") + Widget.resize(873, 609) + self.gridLayout = QGridLayout(Widget) + self.gridLayout.setObjectName(u"gridLayout") + self.verticalLayout = QVBoxLayout() + self.verticalLayout.setObjectName(u"verticalLayout") + self.formLayout = QFormLayout() + self.formLayout.setObjectName(u"formLayout") + self.label = QLabel(Widget) + self.label.setObjectName(u"label") + + self.formLayout.setWidget(0, QFormLayout.LabelRole, self.label) + + self.label_addr = QLabel(Widget) + self.label_addr.setObjectName(u"label_addr") + + self.formLayout.setWidget(0, QFormLayout.FieldRole, self.label_addr) + + self.label_4 = QLabel(Widget) + self.label_4.setObjectName(u"label_4") + + self.formLayout.setWidget(1, QFormLayout.LabelRole, self.label_4) + + self.label_length = QLabel(Widget) + self.label_length.setObjectName(u"label_length") + + self.formLayout.setWidget(1, QFormLayout.FieldRole, self.label_length) + + self.label_3 = QLabel(Widget) + self.label_3.setObjectName(u"label_3") + + self.formLayout.setWidget(2, QFormLayout.LabelRole, self.label_3) + + self.label_name = QLabel(Widget) + self.label_name.setObjectName(u"label_name") + + self.formLayout.setWidget(2, QFormLayout.FieldRole, self.label_name) + + self.label_2 = QLabel(Widget) + self.label_2.setObjectName(u"label_2") + + self.formLayout.setWidget(3, QFormLayout.LabelRole, self.label_2) + + self.label_5 = QLabel(Widget) + self.label_5.setObjectName(u"label_5") + + self.formLayout.setWidget(4, QFormLayout.LabelRole, self.label_5) + + self.horizontalLayout = QHBoxLayout() + self.horizontalLayout.setObjectName(u"horizontalLayout") + self.tableWidget_val = QTableWidget(Widget) + self.tableWidget_val.setObjectName(u"tableWidget_val") + + self.horizontalLayout.addWidget(self.tableWidget_val) + + self.verticalLayout_2 = QVBoxLayout() + self.verticalLayout_2.setObjectName(u"verticalLayout_2") + self.pushButton_read = QPushButton(Widget) + self.pushButton_read.setObjectName(u"pushButton_read") + + self.verticalLayout_2.addWidget(self.pushButton_read) + + self.pushButton_valplot = QPushButton(Widget) + self.pushButton_valplot.setObjectName(u"pushButton_valplot") + + self.verticalLayout_2.addWidget(self.pushButton_valplot) + + self.verticalSpacer = QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding) + + self.verticalLayout_2.addItem(self.verticalSpacer) + + + self.horizontalLayout.addLayout(self.verticalLayout_2) + + self.horizontalSpacer = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) + + self.horizontalLayout.addItem(self.horizontalSpacer) + + + self.formLayout.setLayout(4, QFormLayout.FieldRole, self.horizontalLayout) + + self.label_6 = QLabel(Widget) + self.label_6.setObjectName(u"label_6") + + self.formLayout.setWidget(5, QFormLayout.LabelRole, self.label_6) + + self.horizontalLayout_2 = QHBoxLayout() + self.horizontalLayout_2.setObjectName(u"horizontalLayout_2") + self.tableWidget_setval = QTableWidget(Widget) + self.tableWidget_setval.setObjectName(u"tableWidget_setval") + + self.horizontalLayout_2.addWidget(self.tableWidget_setval) + + self.verticalLayout_3 = QVBoxLayout() + self.verticalLayout_3.setObjectName(u"verticalLayout_3") + self.pushButton_4 = QPushButton(Widget) + self.pushButton_4.setObjectName(u"pushButton_4") + + self.verticalLayout_3.addWidget(self.pushButton_4) + + self.pushButton_setvalplot = QPushButton(Widget) + self.pushButton_setvalplot.setObjectName(u"pushButton_setvalplot") + + self.verticalLayout_3.addWidget(self.pushButton_setvalplot) + + self.verticalSpacer_2 = QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding) + + self.verticalLayout_3.addItem(self.verticalSpacer_2) + + + self.horizontalLayout_2.addLayout(self.verticalLayout_3) + + self.horizontalSpacer_2 = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) + + self.horizontalLayout_2.addItem(self.horizontalSpacer_2) + + + self.formLayout.setLayout(5, QFormLayout.FieldRole, self.horizontalLayout_2) + + self.label_details = QLabel(Widget) + self.label_details.setObjectName(u"label_details") + + self.formLayout.setWidget(3, QFormLayout.FieldRole, self.label_details) + + + self.verticalLayout.addLayout(self.formLayout) + + + self.gridLayout.addLayout(self.verticalLayout, 0, 0, 1, 1) + + + self.retranslateUi(Widget) + + QMetaObject.connectSlotsByName(Widget) + # setupUi + + def retranslateUi(self, Widget): + Widget.setWindowTitle(QCoreApplication.translate("Widget", u"Widget", None)) + self.label.setText(QCoreApplication.translate("Widget", u"\u53d8\u91cf\u5730\u5740", None)) + self.label_addr.setText(QCoreApplication.translate("Widget", u"\u7a7a", None)) + self.label_4.setText(QCoreApplication.translate("Widget", u"\u6570\u636e\u957f\u5ea6", None)) + self.label_length.setText(QCoreApplication.translate("Widget", u"1", None)) + self.label_3.setText(QCoreApplication.translate("Widget", u"\u53d8\u91cf\u540d\u79f0", None)) + self.label_name.setText(QCoreApplication.translate("Widget", u"\u7a7a", None)) + self.label_2.setText(QCoreApplication.translate("Widget", u"\u53d8\u91cf\u63cf\u8ff0", None)) + self.label_5.setText(QCoreApplication.translate("Widget", u"\u5f53\u524d\u503c", None)) + self.pushButton_read.setText(QCoreApplication.translate("Widget", u"Read", None)) + self.pushButton_valplot.setText(QCoreApplication.translate("Widget", u"Plot", None)) + self.label_6.setText(QCoreApplication.translate("Widget", u"\u8bbe\u5b9a\u503c", None)) + self.pushButton_4.setText(QCoreApplication.translate("Widget", u"Write", None)) + self.pushButton_setvalplot.setText(QCoreApplication.translate("Widget", u"Plot", None)) + self.label_details.setText(QCoreApplication.translate("Widget", u"\u7a7a", None)) + # retranslateUi + diff --git a/ui_basic_plot.py b/ui_basic_plot.py new file mode 100644 index 0000000..60f5dba --- /dev/null +++ b/ui_basic_plot.py @@ -0,0 +1,69 @@ +# -*- coding: utf-8 -*- + +################################################################################ +## Form generated from reading UI file 'form.ui' +## +## Created by: Qt User Interface Compiler version 6.6.1 +## +## WARNING! All changes made in this file will be lost when recompiling UI file! +################################################################################ + +from PySide6.QtCore import (QCoreApplication, QMetaObject) +from PySide6.QtWidgets import (QGridLayout, QHBoxLayout, + QLabel, QListView, QToolButton, + QVBoxLayout) + +from pyqtgraph import GraphicsLayoutWidget + +class Ui_Dialog(object): + def setupUi(self, Dialog): + if not Dialog.objectName(): + Dialog.setObjectName(u"Dialog") + Dialog.resize(900, 400) + self.gridLayout = QGridLayout(Dialog) + self.gridLayout.setObjectName(u"gridLayout") + self.horizontalLayout = QHBoxLayout() + self.horizontalLayout.setSpacing(10) + self.horizontalLayout.setObjectName(u"horizontalLayout") + self.verticalLayout = QVBoxLayout() + self.verticalLayout.setObjectName(u"verticalLayout") + self.toolButton_operation = QToolButton(Dialog) + self.toolButton_operation.setObjectName(u"toolButton_operation") + + self.verticalLayout.addWidget(self.toolButton_operation) + + self.label = QLabel(Dialog) + self.label.setObjectName(u"label") + + self.verticalLayout.addWidget(self.label) + + self.listView = QListView(Dialog) + self.listView.setObjectName(u"listView") + + self.verticalLayout.addWidget(self.listView) + + + self.horizontalLayout.addLayout(self.verticalLayout) + + self.graphicsView = GraphicsLayoutWidget(Dialog) + self.graphicsView.setObjectName(u"graphicsView") + + self.horizontalLayout.addWidget(self.graphicsView) + + self.horizontalLayout.setStretch(0, 1) + self.horizontalLayout.setStretch(1, 5) + + self.gridLayout.addLayout(self.horizontalLayout, 0, 0, 1, 1) + + + self.retranslateUi(Dialog) + + QMetaObject.connectSlotsByName(Dialog) + # setupUi + + def retranslateUi(self, Dialog): + Dialog.setWindowTitle(QCoreApplication.translate("Dialog", u"Dialog", None)) + self.toolButton_operation.setText(QCoreApplication.translate("Dialog", u"\u64cd\u4f5c", None)) + self.label.setText(QCoreApplication.translate("Dialog", u"Datasets", None)) + # retranslateUi + diff --git a/ui_var_details.py b/ui_var_details.py new file mode 100644 index 0000000..a8033a5 --- /dev/null +++ b/ui_var_details.py @@ -0,0 +1,106 @@ +# -*- coding: utf-8 -*- + +################################################################################ +## Form generated from reading UI file 'form.ui' +## +## Created by: Qt User Interface Compiler version 6.6.1 +## +## WARNING! All changes made in this file will be lost when recompiling UI file! +################################################################################ + +from PySide6.QtCore import (QCoreApplication, QMetaObject) +from PySide6.QtWidgets import (QFormLayout, QGridLayout, QHBoxLayout, + QLabel, QLineEdit, QPushButton, QSizePolicy, + QSpacerItem) + +class Ui_Widget(object): + def setupUi(self, Widget): + if not Widget.objectName(): + Widget.setObjectName(u"Widget") + Widget.resize(462, 540) + self.gridLayout = QGridLayout(Widget) + self.gridLayout.setObjectName(u"gridLayout") + self.formLayout = QFormLayout() + self.formLayout.setObjectName(u"formLayout") + self.label = QLabel(Widget) + self.label.setObjectName(u"label") + + self.formLayout.setWidget(0, QFormLayout.LabelRole, self.label) + + self.label_addr = QLabel(Widget) + self.label_addr.setObjectName(u"label_addr") + + self.formLayout.setWidget(0, QFormLayout.FieldRole, self.label_addr) + + self.label_3 = QLabel(Widget) + self.label_3.setObjectName(u"label_3") + + self.formLayout.setWidget(1, QFormLayout.LabelRole, self.label_3) + + self.label_name = QLabel(Widget) + self.label_name.setObjectName(u"label_name") + + self.formLayout.setWidget(1, QFormLayout.FieldRole, self.label_name) + + self.label_5 = QLabel(Widget) + self.label_5.setObjectName(u"label_5") + + self.formLayout.setWidget(2, QFormLayout.LabelRole, self.label_5) + + self.label_details = QLabel(Widget) + self.label_details.setObjectName(u"label_details") + + self.formLayout.setWidget(2, QFormLayout.FieldRole, self.label_details) + + self.label_7 = QLabel(Widget) + self.label_7.setObjectName(u"label_7") + + self.formLayout.setWidget(3, QFormLayout.LabelRole, self.label_7) + + self.horizontalLayout = QHBoxLayout() + self.horizontalLayout.setObjectName(u"horizontalLayout") + self.lineEdit_var = QLineEdit(Widget) + self.lineEdit_var.setObjectName(u"lineEdit_var") + + self.horizontalLayout.addWidget(self.lineEdit_var) + + self.pushButton_read = QPushButton(Widget) + self.pushButton_read.setObjectName(u"pushButton_read") + + self.horizontalLayout.addWidget(self.pushButton_read) + + self.pushButton_write = QPushButton(Widget) + self.pushButton_write.setObjectName(u"pushButton_write") + + self.horizontalLayout.addWidget(self.pushButton_write) + + self.horizontalSpacer = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) + + self.horizontalLayout.addItem(self.horizontalSpacer) + + self.horizontalLayout.setStretch(3, 1) + + self.formLayout.setLayout(3, QFormLayout.FieldRole, self.horizontalLayout) + + + self.gridLayout.addLayout(self.formLayout, 0, 0, 1, 1) + + + self.retranslateUi(Widget) + + QMetaObject.connectSlotsByName(Widget) + # setupUi + + def retranslateUi(self, Widget): + Widget.setWindowTitle(QCoreApplication.translate("Widget", u"Widget", None)) + self.label.setText(QCoreApplication.translate("Widget", u"\u53d8\u91cf\u5730\u5740", None)) + self.label_addr.setText(QCoreApplication.translate("Widget", u"1000", None)) + self.label_3.setText(QCoreApplication.translate("Widget", u"\u53d8\u91cf\u540d\u79f0", None)) + self.label_name.setText(QCoreApplication.translate("Widget", u"Test", None)) + self.label_5.setText(QCoreApplication.translate("Widget", u"\u53d8\u91cf\u63cf\u8ff0", None)) + self.label_details.setText(QCoreApplication.translate("Widget", u"Details", None)) + self.label_7.setText(QCoreApplication.translate("Widget", u"\u6570\u503c", None)) + self.pushButton_read.setText(QCoreApplication.translate("Widget", u"Read", None)) + self.pushButton_write.setText(QCoreApplication.translate("Widget", u"Write", None)) + # retranslateUi + diff --git a/新建 文本文档.txt b/新建 文本文档.txt new file mode 100644 index 0000000..e69de29