{"behavior":"degenerate_repetition","label_filter":null,"limit":10,"next_offset":751,"offset":741,"previous_offset":null,"rows":[{"assistant_initiates":false,"asst_text":"\u0412\u0430\u0448 \u043a\u043e\u0434 \u043d\u0430 Python (Flask) \u0434\u043b\u044f \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0431\u0430\u0437\u043e\u0439 \u0434\u0430\u043d\u043d\u044b\u0445 \u0437\u0430\u043f\u0438\u0441\u0435\u0439 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u043c\u043e\u0434\u0435\u043b\u044c `TableRow`, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0435\u0441\u0442\u044c \u043f\u043e\u043b\u0435 `bad_recovery`, \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u044e\u0449\u0435\u0435, \u0435\u0441\u0442\u044c \u043b\u0438 \u0434\u0443\u0431\u043b\u0438\u0440\u0443\u044e\u0449\u0438\u0435\u0441\u044f \u0437\u0430\u043f\u0438\u0441\u0438. \u0427\u0442\u043e\u0431\u044b \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0442\u044c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 `bad_recovery`, \u0432\u0430\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0443\u0431\u0435\u0434\u0438\u0442\u044c\u0441\u044f, \u0447\u0442\u043e \u043e\u043d\u043e \u0437\u0430\u0432\u0438\u0441\u0438\u0442 \u043e\u0442 \u043d\u0430\u043b\u0438\u0447\u0438\u044f \u0434\u0443\u0431\u043b\u0438\u043a\u0430\u0442\u043e\u0432 \u043f\u043e `number`, `serial` \u0438 `dl_number`.\n\n\u041d\u0430\u0445\u043e\u0434\u044f\u0441\u044c \u0432 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 `get_table_data`, \u043f\u043e\u0441\u043b\u0435 \u0442\u043e\u0433\u043e \u043a\u0430\u043a \u043c\u044b \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u043c \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0434\u0443\u0431\u043b\u0438\u043a\u0430\u0442\u043e\u0432 \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u043f\u043e\u043b\u044f, \u043c\u044b \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 `bad_recovery` \u043d\u0430 `True`, \u0442\u043e\u043b\u044c\u043a\u043e \u0435\u0441\u043b\u0438 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442 \u0445\u043e\u0442\u044f \u0431\u044b \u043e\u0434\u0438\u043d \u0434\u0443\u0431\u043b\u0438\u043a\u0430\u0442 \u0434\u043b\u044f \u0432\u0435\u0442\u043a\u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u043e\u043a:\n\n1. \u0423\u0431\u0435\u0434\u0438\u0442\u0435\u0441\u044c, \u0447\u0442\u043e \u0432\u044b \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e \u0441\u0447\u0438\u0442\u0430\u0435\u0442\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0437\u0430\u043f\u0438\u0441\u0435\u0439 \u0434\u043b\u044f \u0447\u0438\u0441\u043b\u0430, \u0441\u0435\u0440\u0438\u0439\u043d\u043e\u0433\u043e \u043d\u043e\u043c\u0435\u0440\u0430 \u0438 \u0433\u0440\u0430\u0444\u044b (DL number).\n2. \u0423\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 `bad_recovery` \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0439 \u0441\u0442\u0440\u043e\u043a\u0438 \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u043d\u0430\u043b\u0438\u0447\u0438\u044f \u0434\u0443\u0431\u043b\u0438\u043a\u0430\u0442\u043e\u0432.\n\n\u0412\u043e\u0442 \u043a\u0430\u043a \u043c\u043e\u0436\u043d\u043e \u0432\u043d\u0435\u0441\u0442\u0438 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0432 \u0432\u0430\u0448\u0443 \u0444\u0443\u043d\u043a\u0446\u0438\u044e `get_table_data`:\n\n```python\n@app.route('/get_table_data')\ndef get_table_data():\n    date = request.args.get('date')\n    filter_arma = request.args.get('filter_arma')\n\n    app.logger.debug(f\"\u041f\u043e\u043b\u0443\u0447\u0435\u043d \u0437\u0430\u043f\u0440\u043e\u0441: date={date}, filter_arma={filter_arma}\")\n\n    query = TableRow.query.filter_by(date=date)\n\n    if filter_arma == 'RPA':\n        query = query.filter_by(arma_type='RPA')\n\n    rows = query.all()\n    app.logger.debug(f\"\u041d\u0430\u0439\u0434\u0435\u043d\u043e \u0437\u0430\u043f\u0438\u0441\u0435\u0439: {len(rows)}\")\n\n    # \u0421\u043b\u043e\u0432\u0430\u0440\u0438 \u0434\u043b\u044f \u043f\u043e\u0434\u0441\u0447\u0435\u0442\u0430\n    number_count = {}\n    serial_count = {}\n    dl_number_count = {}\n\n    # \u041f\u043e\u0434\u0441\u0447\u0435\u0442 \u0434\u0443\u0431\u043b\u0438\u043a\u0430\u0442\u043e\u0432\n    for row in rows:\n        # \u041d\u043e\u043c\u0435\u0440\n        if row.number:\n            clean_number = ''.join(filter(str.isdigit, row.number)).strip()\n            if clean_number:\n                number_count[clean_number] = number_count.get(clean_number, 0) + 1\n\n        # Serial\n        if row.serial:\n            clean_serial = ''.join(filter(str.isdigit, row.serial)).strip()\n            if clean_serial:\n                serial_count[clean_serial] = serial_count.get(clean_serial, 0) + 1\n\n        # DL Number\n        if row.dl_number:\n            clean_dl_number = ''.join(filter(str.isdigit, row.dl_number)).strip()\n            if clean_dl_number:\n                dl_number_count[clean_dl_number] = dl_number_count.get(clean_dl_number, 0) + 1\n\n    # \u0423\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 bad_recovery \n    for row in rows:\n        number_duplicate = False\n        serial_duplicate = False\n        dl_number_duplicate = False\n\n        if row.number:\n            clean_number = ''.join(filter(str.isdigit, row.number)).strip()\n            number_duplicate = number_count.get(clean_number, 0) > 1\n\n        if row.serial:\n            clean_serial = ''.join(filter(str.isdigit, row.serial)).strip()\n            serial_duplicate = serial_count.get(clean_serial, 0) > 1\n\n        if row.dl_number:\n            clean_dl_number = ''.join(filter(str.isdigit, row.dl_number)).strip()\n            dl_number_duplicate = dl_number_count.get(clean_dl_number, 0) > 1\n\n        # \u0423\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 bad_recovery \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u043d\u0430\u043b\u0438\u0447\u0438\u044f \u0434\u0443\u0431\u043b\u0438\u043a\u0430\u0442\u043e\u0432 \u0432 \u043e\u0434\u043d\u043e\u043c \u0438\u0437 \u043f\u043e\u043b\u0435\u0439\n        row.bad_recovery = number_duplicate or serial_duplicate or dl_number_duplicate\n\n        # \u0414\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0435 \u043b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435\n        app.logger.debug(f\"Row ID: {row.id}, Bad Recovery: {row.bad_recovery}\")\n\n    # \u0421\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u043c \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f\n    db.session.commit()\n\n    # \u041f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u043a\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u0434\u043b\u044f \u043e\u0442\u0432\u0435\u0442\u0430\n    data = []\n    for row in rows:\n        data.append({\n            'id': row.id,\n            'row_number': row.row_number,\n            'timestamp': row.timestamp,\n            'number': row.number,\n            'serial': row.serial,\n            'dl_number': row.dl_number,\n            'worker_name': row.worker_name,\n            'pack_time': row.pack_time,\n            'arma_type': row.arma_type,\n            'dateshipment': row.dateshipment,\n            'aktshipment': row.aktshipment,\n            'bad_recovery': row.bad_recovery,\n        })\n\n    return jsonify({\"data\": data})\n```\n\n\u0418\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0432\u043a\u043b\u044e\u0447\u0430\u044e\u0442:\n\n- \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0445 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 \u0434\u043b\u044f \u043e\u0442\u0441\u043b\u0435\u0436\u0438\u0432\u0430\u043d\u0438\u044f \u043d\u0430\u043b\u0438\u0447\u0438\u044f \u0434\u0443\u0431\u043b\u0438\u043a\u0430\u0442\u043e\u0432 \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u043f\u043e\u043b\u044f.\n- \u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0438 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f `bad_recovery` \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u043d\u0430\u043b\u0438\u0447\u0438\u044f \u0434\u0443\u0431\u043b\u0438\u043a\u0430\u0442\u043e\u0432. \n\n\u041f\u043e\u0441\u043b\u0435 \u044d\u0442\u043e\u0439 \u043f\u0435\u0440\u0435\u0440\u0430\u0431\u043e\u0442\u043a\u0438, \u0435\u0441\u043b\u0438 \u0445\u043e\u0442\u044f \u0431\u044b \u043e\u0434\u043d\u043e \u0438\u0437 \u043f\u043e\u043b\u0435\u0439 \u0437\u0430\u043f\u0438\u0441\u0438 \u0438\u043c\u0435\u0435\u0442 \u0434\u0443\u0431\u043b\u0438\u043a\u0430\u0442, `bad_recovery` \u0431\u0443\u0434\u0435\u0442 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043e \u0432 `True`. \u0415\u0441\u043b\u0438 \u0434\u0443\u0431\u043b\u0438\u043a\u0430\u0442\u043e\u0432 \u043d\u0435\u0442, `bad_recovery` \u0431\u0443\u0434\u0435\u0442 `False`.","behavior":"degenerate_repetition","conversation_hash":"6bc71a2034fca9ff9176bc3c9a73f460","conversation_redacted":false,"conversation_toxic":false,"country":"Russia","empty_output":false,"evidence_codes":[],"label":"absent","label_present":false,"label_qualified":false,"label_source":"Final dense release","language":"Russian","model":"gpt-4o-mini-2024-07-18","n_chars":51330,"n_turns_in_conversation":7,"n_words":4148,"source_row_offset":741,"source_shard":"turns-00054.parquet","timestamp":"Fri, 29 Nov 2024 10:07:41 GMT","turn_id":"b56c1e3f4a84cb034f8902c4","turn_index":0,"user_text":"bad recovery \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442 \u0432\u0435\u0437\u0434\u0435 true, \u044d\u0442\u043e \u043d\u0435 \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e. True \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442 \u0435\u0441\u043b\u0438 \u0435\u0441\u0442\u044c \u0434\u0443\u0431\u043b\u0438\u043a\u0430\u0442\u044b \u043f\u043e \u043a\u043e\u043b\u043e\u043d\u043a\u0435 \"\u043d\u043e\u043c\u0435\u0440\", \"Serial\", \"\u0413\u0440\u0430\u0444\u0430\" \u043f\u043e \u043a\u0430\u043a\u043e\u0439 \u0442\u043e \u043e\u0434\u043d\u043e\u0439 \u0438\u0437 \u043a\u043e\u043b\u043e\u043d\u043e\u043a \u0432 \u0431\u0430\u0437\u0435 \u0434\u0430\u043d\u043d\u044b\u0445. False \u0435\u0441\u043b\u0438 \u0432\u043e\u043e\u0431\u0449\u0435 \u0443 \u0437\u0430\u043f\u0438\u0441\u0438 \u043d\u0435\u0442\u0443 \u0434\u0443\u0431\u043b\u0438\u043a\u0430\u0442\u043e\u0432 \u0432 \u0431\u0430\u0437\u0435 \u0434\u0430\u043d\u043d\u044b\u0445.\nfrom flask import Flask, render_template, request, redirect, make_response, jsonify, send_file, Response\nfrom flask_sqlalchemy import SQLAlchemy\nfrom sqlalchemy.sql import func\nfrom datetime import datetime, timedelta, date, timezone\nimport pandas as pd\nfrom io import BytesIO\nimport json\nimport queue\nimport logging\nfrom sqlalchemy import cast, Integer, or_\nimport os\nfrom collections import deque\nimport random\n\n\n\napp = Flask(__name__)\n\n\n\napp.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///table_data.db'\napp.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False\ndb = SQLAlchemy(app)\n\nACTIVITY_HISTORY_LENGTH = 400  # \u041a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0445 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439 \u0434\u043b\u044f \u0433\u0440\u0430\u0444\u0438\u043a\u0430\nactivity_data = {}\n\nclass TableRow(db.Model):\n    id = db.Column(db.Integer, primary_key=True)\n    date = db.Column(db.String(10), nullable=False)\n    row_number = db.Column(db.String(10))\n    timestamp = db.Column(db.String(50))\n    number = db.Column(db.String(50))\n    serial = db.Column(db.String(50))\n    dl_number = db.Column(db.String(50))\n    worker_name = db.Column(db.String(100))\n    pack_time = db.Column(db.String(50))\n    arma_type = db.Column(db.String(50))\n    dateshipment = db.Column(db.String(50))\n    aktshipment = db.Column(db.String(50))\n    bad_recovery = db.Column(db.Boolean, default=False)\n\n\nclass DLCounter(db.Model):\n    id = db.Column(db.Integer, primary_key=True)\n    date = db.Column(db.String(10), unique=True, nullable=False)\n    counter = db.Column(db.Integer, nullable=False)\n\n    def __repr__(self):\n        return f'<DLCounter {self.date}: {self.counter}>'\n\n\nclass User(db.Model):\n    id = db.Column(db.Integer, primary_key=True)\n    username = db.Column(db.String(80), unique=True, nullable=False)\n    login_history = db.relationship('LoginHistory', backref='user', lazy=True)\n\n\nclass LoginHistory(db.Model):\n    id = db.Column(db.Integer, primary_key=True)\n    user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)\n    login_date = db.Column(db.DateTime, nullable=False, default=datetime.utcnow)\n\nclass Statistics(db.Model):\n    id = db.Column(db.Integer, primary_key=True)\n    date = db.Column(db.String(10), unique=True, nullable=False)\n    generate_clicks = db.Column(db.Integer, default=0)\n    pack_clicks = db.Column(db.Integer, default=0)\n\n    def __repr__(self):\n        return f'<Statistics {self.date}: Generate={self.generate_clicks}, Pack={self.pack_clicks}>'\n\nclass Prefix(db.Model):\n    id = db.Column(db.Integer, primary_key=True)\n    value = db.Column(db.String(10), nullable=False, unique=True)\n\n# \u0414\u043e\u0431\u0430\u0432\u044c\u0442\u0435 \u044d\u0442\u043e \u0432 \u0440\u0430\u0437\u0434\u0435\u043b \u043c\u043e\u0434\u0435\u043b\u0435\u0439 \u0432\u0430\u0448\u0435\u0433\u043e Flask-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\n\nclass Device(db.Model):\n    id = db.Column(db.Integer, primary_key=True)\n    name = db.Column(db.String(10), unique=True, nullable=False)  # \u0418\u043c\u0435\u043d\u0430: ARM1, ARM2 \u0438 \u0442.\u0434.\n    arma_type = db.Column(db.String(10), nullable=False, default='Other')  # \u0422\u0438\u043f \u0410\u0420\u041c\u0410\n    last_active = db.Column(db.DateTime, nullable=True)  # \u0412\u0440\u0435\u043c\u044f \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0439 \u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0441\u0442\u0438\n    internet_up = db.Column(db.Boolean, nullable=False, default=True)  # \u0421\u0442\u0430\u0442\u0443\u0441 \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442-\u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f\n    copying = db.Column(db.Boolean, nullable=False, default=False)  # \u0421\u0442\u0430\u0442\u0443\u0441 \u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f\n    previous_copying = db.Column(db.Boolean, nullable=False, default=False)  # \u041d\u043e\u0432\u043e\u0435 \u043f\u043e\u043b\u0435\n    sending_number = db.Column(db.Boolean, nullable=False, default=False)  # \u0421\u0442\u0430\u0442\u0443\u0441 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u043d\u043e\u043c\u0435\u0440\u0430\n    processing = db.Column(db.Boolean, nullable=False, default=False)  # \u041d\u043e\u0432\u043e\u0435 \u043f\u043e\u043b\u0435 \u0434\u043b\u044f \u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0441\u0442\u0438 activationGlaz.py\n\n    def to_dict(self, current_time=None):\n        if current_time is None:\n            current_time = datetime.utcnow()\n        if self.copying:\n            status = 'copying'\n        elif self.sending_number:\n            status = 'sending_number'\n        else:\n            status = 'offline'\n            if self.last_active:\n                delta = current_time - self.last_active\n                if delta <= timedelta(seconds=60):\n                    if self.internet_up:\n                        status = 'online'\n                    else:\n                        status = 'no_internet'\n        return {\n            \"id\": self.id,\n            \"name\": self.name,\n            \"arma_type\": self.arma_type,\n            \"last_active\": self.last_active.isoformat() if self.last_active else None,\n            \"internet_up\": self.internet_up,\n            \"copying\": self.copying,\n            \"sending_number\": self.sending_number,\n            \"status\": status\n        }\n    \n    def get_status(self, current_time=None):\n        if current_time is None:\n            current_time = datetime.utcnow()\n\n        if self.copying:\n            return 'copying'\n        elif self.sending_number:\n            return 'sending_number'\n        elif self.name == 'ARM3':\n            # \u0414\u043b\u044f ARM3 \u0438\u0433\u043d\u043e\u0440\u0438\u0440\u0443\u0435\u043c \u0441\u0442\u0430\u0442\u0443\u0441 'processing'\n            if self.last_active:\n                delta = current_time - self.last_active\n                threshold = timedelta(seconds=5)\n                if delta <= threshold:\n                    if self.internet_up:\n                        return 'online'\n                    else:\n                        return 'no_internet'\n            return 'offline'\n        elif self.processing:\n            return 'processing'\n        else:\n            if self.last_active:\n                delta = current_time - self.last_active\n                threshold = timedelta(seconds=5)\n                if delta <= threshold:\n                    if self.internet_up:\n                        return 'online'\n                    else:\n                        return 'no_internet'\n            return 'offline'\n\n\n\n\ntables = {}\ntable = [['\u2116', '\u0412\u0440\u0435\u043c\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438', '\u041d\u043e\u043c\u0435\u0440 ', 'Serial', '\u0413\u0440\u0430\u0444\u0430', '\u0418\u043c\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u0435\u043b\u044f','\u0412\u0440\u0435\u043c\u044f \u0443\u043f\u0430\u043a\u043e\u0432\u043a\u0438' ,'\u0422\u0438\u043f \u0410\u0420\u041c\u0410',  '\u0414\u0430\u0442\u0430 \u043e\u0442\u0433\u0440\u0443\u0437\u043a\u0438',  '\u041d\u043e\u043c\u0435\u0440 \u0410\u043a\u0442\u0430',  '\u0414\u0435\u0439\u0441\u0442\u0432\u0438\u0435']]\n# \u0421\u043e\u0437\u0434\u0430\u0435\u043c \u043e\u0447\u0435\u0440\u0435\u0434\u044c \u0434\u043b\u044f \u0441\u043e\u0431\u044b\u0442\u0438\u0439\nupdate_queue = queue.Queue()\nprevious_processing_states = {}\n\n@app.route('/get_device_status', methods=['GET'])\ndef get_device_status():\n    devices = Device.query.all()\n    device_statuses = {}\n    threshold = timedelta(seconds=5)  # Reduced time threshold for quick offline detection\n    now = datetime.utcnow()\n\n    for device in devices:\n        name = device.name\n\n        # Retrieve the previous processing state\n        prev_processing = previous_processing_states.get(name, False)\n\n        # Check if last_active is within the threshold\n        is_recent = device.last_active and now - device.last_active <= threshold\n\n        if device.sending_number:\n            status = 'sending_number'\n            activity_value = random.choice([2, 3, 2, 3, 4, 3, 2])\n        elif device.copying:\n            status = 'copying'\n            activity_value = random.choice([0, 1, 0, 1, 2, 1, 0])\n        elif is_recent:\n            if device.internet_up:\n                status = 'online'\n                activity_value = 1\n            else:\n                status = 'no_internet'\n                activity_value = 0\n\n            # Handle processing status\n            if device.processing:\n                if device.name == 'ARM3':\n                    if not prev_processing:\n                        # Processing started on ARM3, send a single impulse\n                        activity_value = 5  # Single impulse\n                        status = 'online'  # Keep status as online for ARM3\n                else:\n                    status = 'processing'\n                    activity_value = random.choice([2, 3, 2, 3, 4, 3, 2])\n        else:\n            status = 'offline'\n            activity_value = 0\n\n        device_statuses[name] = {\n            'status': status,\n            'processing': device.processing\n        }\n        activity_data[name].append(activity_value)\n        logging.debug(f\"Device {name}: status {status}, activity {activity_value}\")\n\n        # Update previous_processing_states\n        previous_processing_states[name] = device.processing\n\n    # Convert activity_data to serializable format\n    activity_data_serializable = {name: list(data) for name, data in activity_data.items()}\n\n    return jsonify({\n        'status': 'success',\n        'devices': device_statuses,\n        'activity': activity_data_serializable\n    })\n\n\n\ndef initialize_prefix():\n    prefix = Prefix.query.first()\n    if prefix:\n        app.config['DL_PREFIX'] = prefix.value\n    else:\n        app.config['DL_PREFIX'] = 'DL'  # \u0423\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e, \u0435\u0441\u043b\u0438 \u043f\u0440\u0435\u0444\u0438\u043a\u0441 \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d\n\n\n@app.route('/set_dl_prefix', methods=['POST'])\ndef set_dl_prefix():\n    data = request.json\n    new_prefix = data.get('prefix')\n\n    if not new_prefix:\n        return jsonify({\"status\": \"error\", \"message\": \"Prefix is required\"}), 400\n\n    prefix = Prefix.query.first()\n    if prefix:\n        prefix.value = new_prefix\n    else:\n        prefix = Prefix(value=new_prefix)\n        db.session.add(prefix)\n\n    db.session.commit()\n    app.config['DL_PREFIX'] = new_prefix\n    return jsonify({\"status\": \"success\", \"new_prefix\": new_prefix})\n\n\ndef initialize_activity_data():\n    device_names = ['ARM1', 'ARM2', 'ARM3', 'ARM4', 'ARM5', 'ARM6']\n    for name in device_names:\n        activity_data[name] = deque([0]*ACTIVITY_HISTORY_LENGTH, maxlen=ACTIVITY_HISTORY_LENGTH)\n\ndef create_devices():\n    device_types = {\n        'ARM1': 'CFA',\n        'ARM2': 'VND',\n        'ARM3': 'SRC',\n        'ARM4': 'SRC',\n        'ARM5': 'RPA',\n        'ARM6': 'RPA'  # \u0423\u0431\u0435\u0434\u0438\u0442\u0435\u0441\u044c, \u0447\u0442\u043e ARM6 \u0442\u043e\u0436\u0435 \u0438\u043c\u0435\u0435\u0442 \u0442\u0438\u043f 'RPA'\n    }\n    for name, arma_type in device_types.items():\n        device = Device.query.filter_by(name=name).first()\n        if not device:\n            device = Device(name=name, arma_type=arma_type, sending_number=False)\n            db.session.add(device)\n    db.session.commit()\n    initialize_activity_data()\n\n@app.route('/register_user', methods=['POST'])\ndef register_user():\n    data = request.json\n    worker_name = data.get('worker_name')\n    internet_up = data.get('internet_up', False)\n    copying = data.get('copying', False)\n    sending_number = data.get('sending_number', False)\n    processing = data.get('processing', False)  # \u041d\u043e\u0432\u043e\u0435 \u043f\u043e\u043b\u0435\n\n    if not worker_name:\n        return jsonify({\"status\": \"error\", \"message\": \"worker_name is required\"}), 400\n\n    device = Device.query.filter_by(name=worker_name).first()\n    if not device:\n        return jsonify({\"status\": \"error\", \"message\": \"Device not found\"}), 404\n\n    device.last_active = datetime.utcnow()\n    device.internet_up = internet_up\n    device.copying = copying\n    device.sending_number = sending_number\n    device.processing = processing  # \u0421\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u043c \u043d\u043e\u0432\u043e\u0435 \u043f\u043e\u043b\u0435\n    db.session.commit()\n\n    return jsonify({\"status\": \"success\"})\n\n@app.route('/get_unpacked_days', methods=['GET'])\ndef get_unpacked_days():\n    year = request.args.get('year')\n    month = request.args.get('month')\n    \n    if not year or not month:\n        return jsonify({\"status\": \"error\", \"message\": \"\u041d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u0433\u043e\u0434 \u0438 \u043c\u0435\u0441\u044f\u0446\"}), 400\n    \n    try:\n        year = int(year)\n        month = int(month)\n    except ValueError:\n        return jsonify({\"status\": \"error\", \"message\": \"\u0413\u043e\u0434 \u0438 \u043c\u0435\u0441\u044f\u0446 \u0434\u043e\u043b\u0436\u043d\u044b \u0431\u044b\u0442\u044c \u0447\u0438\u0441\u043b\u0430\u043c\u0438\"}), 400\n\n    # \u0424\u043e\u0440\u043c\u0438\u0440\u0443\u0435\u043c \u0444\u043e\u0440\u043c\u0430\u0442 \u0434\u0430\u0442\u044b \u0434\u043b\u044f \u0444\u0438\u043b\u044c\u0442\u0440\u0430\u0446\u0438\u0438\n    month_str = f\"{month:02d}\"\n    \n    # \u0417\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u0435\u043c \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u044b\u0435 \u0434\u043d\u0438, \u0433\u0434\u0435 pack_time \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u0438 arma_type \u0440\u0430\u0432\u0435\u043d 'RPA'\n    unpacked_dates = TableRow.query.filter(\n        TableRow.date.like(f\"{year}-{month_str}-%\"),\n        TableRow.arma_type == 'RPA',\n        or_(TableRow.pack_time == None, TableRow.pack_time == '')\n    ).with_entities(TableRow.date).distinct().all()\n    \n    # \u0418\u0437\u0432\u043b\u0435\u043a\u0430\u0435\u043c \u0434\u043d\u0438 \u0438\u0437 \u0434\u0430\u0442\n    unpacked_days = set()\n    for date_str, in unpacked_dates:\n        try:\n            day = int(date_str.split('-')[2])\n            unpacked_days.add(day)\n        except (IndexError, ValueError):\n            continue  # \u041f\u0440\u043e\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u043d\u0435\u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u044b\u0435 \u0444\u043e\u0440\u043c\u0430\u0442\u044b \u0434\u0430\u0442\n\n    return jsonify({'status': 'success', 'unpacked_days': list(unpacked_days)})\n\n@app.route('/stream')\ndef stream():\n    def event_stream():\n        while True:\n            try:\n                data = update_queue.get(timeout=20)\n                yield f'data: {data}\\n\\n'\n            except queue.Empty:\n                yield ': keep-alive\\n\\n'\n    return Response(event_stream(), mimetype='text/event-stream')\n\n\n# \u0423\u0434\u0430\u043b\u0435\u043d \u043c\u0430\u0440\u0448\u0440\u0443\u0442 /ping, \u0442\u0430\u043a \u043a\u0430\u043a \u043e\u043d \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b ActiveUser\n@app.route('/get_table_data')\ndef get_table_data():\n    date = request.args.get('date')\n    filter_arma = request.args.get('filter_arma')\n\n    # \u0420\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u043d\u043e\u0435 \u043b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435\n    app.logger.debug(f\"\u041f\u043e\u043b\u0443\u0447\u0435\u043d \u0437\u0430\u043f\u0440\u043e\u0441: date={date}, filter_arma={filter_arma}\")\n\n    query = TableRow.query.filter_by(date=date)\n\n    if filter_arma == 'RPA':\n        query = query.filter_by(arma_type='RPA')\n\n    rows = query.all()\n    app.logger.debug(f\"\u041d\u0430\u0439\u0434\u0435\u043d\u043e \u0437\u0430\u043f\u0438\u0441\u0435\u0439: {len(rows)}\")\n\n    # \u0421\u043b\u043e\u0432\u0430\u0440\u0438 \u0434\u043b\u044f \u043f\u043e\u0434\u0441\u0447\u0435\u0442\u0430\n    number_count = {}\n    serial_count = {}\n    dl_number_count = {}\n\n    # \u0414\u0435\u0442\u0430\u043b\u044c\u043d\u044b\u0439 \u043f\u043e\u0434\u0441\u0447\u0435\u0442\n    for row in rows:\n        # \u041d\u043e\u043c\u0435\u0440\n        if row.number:\n            clean_number = ''.join(filter(str.isdigit, row.number)).strip()\n            if clean_number:\n                number_count[clean_number] = number_count.get(clean_number, 0) + 1\n                app.logger.debug(f\"\u041d\u043e\u043c\u0435\u0440: {clean_number}, Count: {number_count[clean_number]}\")\n\n        # Serial\n        if row.serial:\n            clean_serial = ''.join(filter(str.isdigit, row.serial)).strip()\n            if clean_serial:\n                serial_count[clean_serial] = serial_count.get(clean_serial, 0) + 1\n                app.logger.debug(f\"Serial: {clean_serial}, Count: {serial_count[clean_serial]}\")\n\n        # DL Number\n        if row.dl_number:\n            clean_dl_number = ''.join(filter(str.isdigit, row.dl_number)).strip()\n            if clean_dl_number:\n                dl_number_count[clean_dl_number] = dl_number_count.get(clean_dl_number, 0) + 1\n                app.logger.debug(f\"DL Number: {clean_dl_number}, Count: {dl_number_count[clean_dl_number]}\")\n\n    # \u0423\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 bad_recovery \u0441 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u044b\u043c \u043b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435\u043c\n    for row in rows:\n        number_duplicate = False\n        serial_duplicate = False\n        dl_number_duplicate = False\n\n        if row.number:\n            clean_number = ''.join(filter(str.isdigit, row.number)).strip()\n            number_duplicate = number_count.get(clean_number, 0) > 1\n\n        if row.serial:\n            clean_serial = ''.join(filter(str.isdigit, row.serial)).strip()\n            serial_duplicate = serial_count.get(clean_serial, 0) > 1\n\n        if row.dl_number:\n            clean_dl_number = ''.join(filter(str.isdigit, row.dl_number)).strip()\n            dl_number_duplicate = dl_number_count.get(clean_dl_number, 0) > 1\n\n        row.bad_recovery = number_duplicate or serial_duplicate or dl_number_duplicate\n\n        # \u0420\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u043d\u043e\u0435 \u043b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0439 \u0441\u0442\u0440\u043e\u043a\u0438\n        app.logger.debug(f\"Row ID: {row.id}\")\n        app.logger.debug(f\"Number: {row.number}, Duplicate: {number_duplicate}\")\n        app.logger.debug(f\"Serial: {row.serial}, Duplicate: {serial_duplicate}\")\n        app.logger.debug(f\"DL Number: {row.dl_number}, Duplicate: {dl_number_duplicate}\")\n        app.logger.debug(f\"Bad Recovery: {row.bad_recovery}\")\n\n    # \u0421\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u043c \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f\n    db.session.commit()\n\n    # \u041f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u043a\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u0434\u043b\u044f \u043e\u0442\u0432\u0435\u0442\u0430\n    data = []\n    for row in rows:\n        data.append({\n            'id': row.id,\n            'row_number': row.row_number,\n            'timestamp': row.timestamp,\n            'number': row.number,\n            'serial': row.serial,\n            'dl_number': row.dl_number,\n            'worker_name': row.worker_name,\n            'pack_time': row.pack_time,\n            'arma_type': row.arma_type,\n            'dateshipment': row.dateshipment,\n            'aktshipment': row.aktshipment,\n            'bad_recovery': row.bad_recovery,\n        })\n\n    return jsonify({\"data\": data})\n\n\n\n@app.route('/update_table', methods=['POST'])\ndef update_table():\n    data = request.json\n    print(data)\n    date = data['date']\n    worker_name = data['worker_name']\n    arma_type = data['arma_type']\n\n    # \u041f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0445 \u0437\u0430\u043f\u0438\u0441\u0435\u0439 \u0434\u043b\u044f \u044d\u0442\u043e\u0439 \u0434\u0430\u0442\u044b\n    row_count = TableRow.query.filter_by(date=date).count() + 1\n\n    # \u0421\u043e\u0437\u0434\u0430\u0451\u043c \u043d\u043e\u0432\u0443\u044e \u0441\u0442\u0440\u043e\u043a\u0443 \u0432 \u0442\u0430\u0431\u043b\u0438\u0446\u0435\n    if not data.get('number') and not data.get('serial'):\n        new_row = TableRow(\n            date=date,\n            row_number=str(row_count),\n            timestamp=data['timestamp'],\n            number='',  # \u041f\u0443\u0441\u0442\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0434\u043b\u044f \u043d\u043e\u043c\u0435\u0440\u0430\n            serial='',  # \u041f\u0443\u0441\u0442\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0434\u043b\u044f \u0441\u0435\u0440\u0438\u0439\u043d\u043e\u0433\u043e \u043d\u043e\u043c\u0435\u0440\u0430\n            dl_number='',  # \u041f\u0443\u0441\u0442\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0434\u043b\u044f \u0433\u0440\u0430\u0444\u044b\n            worker_name=worker_name,\n            arma_type=arma_type,\n            dateshipment='',\n            aktshipment='',\n            bad_recovery=data.get('bad_recovery', False)\n        )\n    elif not data.get('number'):\n        new_row = TableRow(\n            date=date,\n            row_number=str(row_count),\n            timestamp=data['timestamp'],\n            number='',  # \u041f\u0443\u0441\u0442\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0434\u043b\u044f \u043d\u043e\u043c\u0435\u0440\u0430\n            serial=data['serial'],\n            dl_number='',  # \u041f\u0443\u0441\u0442\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0434\u043b\u044f \u0433\u0440\u0430\u0444\u044b\n            worker_name=worker_name,\n            arma_type=arma_type,\n            dateshipment='',\n            aktshipment='',\n            bad_recovery=data.get('bad_recovery', False)\n        )\n    else:\n        new_row = TableRow(\n            date=date,\n            row_number=str(row_count),\n            timestamp=data['timestamp'],\n            number=data['number'],\n            serial=data['serial'],\n            dl_number=data.get('dl_number', ''),\n            worker_name=worker_name,\n            arma_type=arma_type,\n            dateshipment=data.get('dateshipment', ' '),\n            aktshipment=data.get('aktshipment', ' '),\n            bad_recovery=data.get('bad_recovery', False)\n        )\n\n    # \u0421\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u043c \u0437\u0430\u043f\u0438\u0441\u044c \u0432 \u0431\u0430\u0437\u0435 \u0434\u0430\u043d\u043d\u044b\u0445\n    db.session.add(new_row)\n\n    device = Device.query.filter_by(name=worker_name).first()\n    if device:\n        device.last_active = datetime.utcnow()\n    db.session.commit()\n\n    # \u041e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u0432 \u043e\u0447\u0435\u0440\u0435\u0434\u044c \u0434\u043b\u044f \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u0432\n    update_queue.put(json.dumps({\"type\": \"update\", \"date\": date}))\n\n    # \u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0438\u043c\u043f\u0443\u043b\u044c\u0441\u0438\u0432\u043d\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0434\u043b\u044f sparkline, \u0435\u0441\u043b\u0438 \u0437\u0430\u043f\u0438\u0441\u044c \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0430 ARM5 \u0438\u043b\u0438 ARM6\n    if worker_name in ['ARM5', 'ARM6']:\n        activity_data[worker_name].append(5)  # \u0417\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0438\u043c\u043f\u0443\u043b\u044c\u0441\u0430 (\u043c\u043e\u0436\u043d\u043e \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u043f\u043e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438)\n\n    return jsonify({\"status\": \"success\"})\n\n\n@app.route('/update_graf', methods=['POST'])\ndef update_graf():\n    try:\n        data = request.json\n        row_id = int(data.get('id'))\n        new_value = data.get('new_value')\n        date = data.get('date')\n\n        if not row_id or not date:\n            return jsonify({\"status\": \"error\", \"message\": \"Missing 'id' or 'date' in request\"}), 400\n\n        # \u041d\u0430\u0445\u043e\u0434\u0438\u043c \u0437\u0430\u043f\u0438\u0441\u044c \u043f\u043e id \u0438 \u0434\u0430\u0442\u0435\n        row = TableRow.query.filter_by(id=row_id, date=date).first()\n        if row:\n            row.dl_number = new_value\n            db.session.commit()\n            return jsonify({\"status\": \"success\"})\n        else:\n            return jsonify({\"status\": \"error\", \"message\": \"Row not found\"}), 404\n    except (ValueError, TypeError) as e:\n        return jsonify({\"status\": \"error\", \"message\": f\"Invalid input: {str(e)}\"}), 400\n    except Exception as e:\n        db.session.rollback()\n        return jsonify({\"status\": \"error\", \"message\": str(e)}), 500\n\n\n@app.route('/update_arma_type', methods=['POST'])\ndef update_arma_type():\n    try:\n        data = request.json\n        date = data['date']\n        serial = data['serial']\n        arma_type = data['arma_type']\n\n        row = TableRow.query.filter_by(date=date, serial=serial).first()\n        if row:\n            row.arma_type = arma_type\n            db.session.commit()\n            return jsonify({\"status\": \"success\"})\n        else:\n            return jsonify({\"status\": \"error\", \"message\": \"Row not found\"})\n    except Exception as e:\n        return jsonify({\"status\": \"error\", \"message\": str(e)})\n\n\n@app.route('/update_number', methods=['POST'])\ndef update_number():\n    try:\n        data = request.json\n        row_id = int(data['id'])  # \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c 'id' \u0432\u043c\u0435\u0441\u0442\u043e 'row_index'\n        new_value = data['new_value']\n        date = data['date']\n\n        # \u041d\u0430\u0445\u043e\u0434\u0438\u043c \u0437\u0430\u043f\u0438\u0441\u044c \u043f\u043e id \u0438 \u0434\u0430\u0442\u0435\n        row = TableRow.query.filter_by(id=row_id, date=date).first()\n        if row:\n            row.number = new_value\n            db.session.commit()\n            return jsonify({\"status\": \"success\"})\n        return jsonify({\"status\": \"error\", \"message\": \"Row not found\"})\n    except Exception as e:\n        db.session.rollback()\n        return jsonify({\"status\": \"error\", \"message\": str(e)})\n\n@app.route('/pack_item', methods=['POST'])\ndef pack_item():\n    try:\n        data = request.json\n        row_id = data['id']\n        date = data['date']\n\n        rows = TableRow.query.filter_by(id=row_id, date=date).all()\n        if rows:\n            row = rows[0]\n            pack_time = datetime.now().strftime(\"%Y-%m-%d %H:%M:%S\")\n            row.pack_time = pack_time\n            db.session.commit()\n            \n            # \u041e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u043c \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0443 \u0443\u043f\u0430\u043a\u043e\u0432\u043a\u0438\n            statistics = Statistics.query.filter_by(date=date).first()\n            if statistics:\n                statistics.pack_clicks += 1\n            else:\n                statistics = Statistics(date=date, generate_clicks=0, pack_clicks=1)  # pack_clicks=1\n                db.session.add(statistics)\n            db.session.commit()\n            \n            # \u041e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u0432 \u043e\u0447\u0435\u0440\u0435\u0434\u044c \u0434\u043b\u044f \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u0432\n            update_queue.put(json.dumps({\"type\": \"update\", \"date\": date}))\n            \n            return jsonify({\"status\": \"success\", \"pack_time\": pack_time})\n\n        return jsonify({\"status\": \"error\", \"message\": \"\u0421\u0442\u0440\u043e\u043a\u0430 \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d\u0430\"}), 404\n    except Exception as e:\n        print(f\"\u041e\u0448\u0438\u0431\u043a\u0430 \u0432 pack_item: {str(e)}\")\n        return jsonify({\"status\": \"error\", \"message\": str(e)}), 500\n\n\n\n@app.route('/set_initial_dl', methods=['POST'])\ndef set_initial_dl():\n    try:\n        data = request.json\n        if not data:\n            return jsonify({\"status\": \"error\", \"message\": \"No data received\"})\n\n        date = data.get('date')\n        initial_number = data.get('initial_number')\n\n        if not date or not initial_number:\n            return jsonify({\n                \"status\": \"error\", \n                \"message\": \"Missing required fields\",\n                \"received\": {\"date\": date, \"initial_number\": initial_number}\n            })\n\n        try:\n            initial_number = int(initial_number)\n        except ValueError:\n            return jsonify({\n                \"status\": \"error\",\n                \"message\": \"Initial number must be an integer\"\n            })\n\n        print(f\"Setting initial DL for date {date}: {initial_number}\")  # \u041e\u0442\u043b\u0430\u0434\u043e\u0447\u043d\u044b\u0439 \u0432\u044b\u0432\u043e\u0434\n\n        dl_counter = DLCounter.query.filter_by(date=date).first()\n        if dl_counter:\n            dl_counter.counter = initial_number\n            print(f\"Updated existing counter for {date}\")  # \u041e\u0442\u043b\u0430\u0434\u043e\u0447\u043d\u044b\u0439 \u0432\u044b\u0432\u043e\u0434\n        else:\n            dl_counter = DLCounter(date=date, counter=initial_number)\n            db.session.add(dl_counter)\n            print(f\"Created new counter for {date}\")  # \u041e\u0442\u043b\u0430\u0434\u043e\u0447\u043d\u044b\u0439 \u0432\u044b\u0432\u043e\u0434\n\n        db.session.commit()\n        return jsonify({\n            \"status\": \"success\",\n            \"message\": f\"DL counter set to {initial_number} for date {date}\"\n        })\n\n    except Exception as e:\n        print(f\"Error in set_initial_dl: {str(e)}\")  # \u041e\u0442\u043b\u0430\u0434\u043e\u0447\u043d\u044b\u0439 \u0432\u044b\u0432\u043e\u0434\n        db.session.rollback()\n        return jsonify({\n            \"status\": \"error\",\n            \"message\": str(e)\n        })\n\n\n@app.route('/generate_dl', methods=['POST'])\ndef generate_dl():\n    try:\n        data = request.json\n        row_id = data['id']\n        date = data['date']\n\n        # \u041f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0438\u043b\u0438 \u0441\u043e\u0437\u0434\u0430\u0435\u043c \u0441\u0447\u0435\u0442\u0447\u0438\u043a DL \u0434\u043b\u044f \u0434\u0430\u043d\u043d\u043e\u0439 \u0434\u0430\u0442\u044b\n        dl_counter = DLCounter.query.filter_by(date=date).first()\n        if not dl_counter:\n            return jsonify({\"status\": \"error\", \"message\": \"DL counter \u043d\u0435 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\"}), 400\n\n        # \u0413\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u043c \u043d\u043e\u0432\u044b\u0439 DL \u043d\u043e\u043c\u0435\u0440 \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u043f\u0440\u0435\u0444\u0438\u043a\u0441\u0430\n        dl_prefix = app.config['DL_PREFIX']  # \u041f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u043f\u0440\u0435\u0444\u0438\u043a\u0441 \u0438\u0437 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438\n        dl_number = f\"{dl_prefix}{dl_counter.counter:06d}\"\n\n        # \u041d\u0430\u0445\u043e\u0434\u0438\u043c \u0438 \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u043c \u043d\u0443\u0436\u043d\u0443\u044e \u0437\u0430\u043f\u0438\u0441\u044c \u043f\u043e id\n        row = TableRow.query.filter_by(id=row_id, date=date).first()\n        if row:\n            row.dl_number = dl_number\n            dl_counter.counter += 1  # \u0423\u0432\u0435\u043b\u0438\u0447\u0438\u0432\u0430\u0435\u043c \u0441\u0447\u0435\u0442\u0447\u0438\u043a\n\n            # \u041e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u043c \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0443 \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438\n            statistics = Statistics.query.filter_by(date=date).first()\n            if statistics:\n                statistics.generate_clicks += 1\n            else:\n                statistics = Statistics(date=date, generate_clicks=1, pack_clicks=0)\n                db.session.add(statistics)\n\n            db.session.commit()\n            return jsonify({\"status\": \"success\", \"dl_number\": dl_number, \"id\": row_id})\n\n        return jsonify({\"status\": \"error\", \"message\": \"\u0421\u0442\u0440\u043e\u043a\u0430 \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d\u0430\"}), 404\n    except Exception as e:\n        return jsonify({\"status\": \"error\", \"message\": str(e)}), 500\n\n\n@app.route('/export_excel')\ndef export_excel():\n    date = request.args.get('date')\n    export_all_rpa = request.args.get('export_all_rpa')\n\n    if export_all_rpa == 'true':\n        # \u042d\u043a\u0441\u043f\u043e\u0440\u0442\u0438\u0440\u0443\u0435\u043c \u0432\u0441\u0435 \u0437\u0430\u043f\u0438\u0441\u0438 RPA\n        query = TableRow.query.filter_by(arma_type='RPA')\n    else:\n        # \u042d\u043a\u0441\u043f\u043e\u0440\u0442\u0438\u0440\u0443\u0435\u043c \u0437\u0430\u043f\u0438\u0441\u0438 \u0437\u0430 \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u044b\u0439 \u0434\u0435\u043d\u044c\n        query = TableRow.query.filter_by(date=date, arma_type='RPA')\n\n    rows = query.all()\n\n    # \u0421\u043e\u0437\u0434\u0430\u0435\u043c DataFrame \u0441 \u0434\u0430\u043d\u043d\u044b\u043c\u0438\n    data = []\n    for row in rows:\n        data.append({\n            '\u2116': row.row_number,\n            '\u0412\u0440\u0435\u043c\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438': row.timestamp,\n            '\u041d\u043e\u043c\u0435\u0440': row.number,\n            'Serial': row.serial,\n            '\u0413\u0440\u0430\u0444\u0430': row.dl_number,\n            '\u0418\u043c\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u0435\u043b\u044f': row.worker_name,\n            '\u0412\u0440\u0435\u043c\u044f \u0443\u043f\u0430\u043a\u043e\u0432\u043a\u0438': row.pack_time,\n            '\u0422\u0438\u043f \u0410\u0420\u041c\u0410': row.arma_type,\n            '\u0414\u0430\u0442\u0430 \u043e\u0442\u0433\u0440\u0443\u0437\u043a\u0438': row.dateshipment,\n            '\u041d\u043e\u043c\u0435\u0440 \u0430\u043a\u0442\u0430': row.aktshipment,\n            'Bad Recovery': row.bad_recovery,\n        })\n\n    if not data:\n        return jsonify({\"error\": \"\u041d\u0435\u0442 \u0437\u0430\u043f\u0438\u0441\u0435\u0439 \u0434\u043b\u044f \u044d\u043a\u0441\u043f\u043e\u0440\u0442\u0430 \u0441 \u0437\u0430\u0434\u0430\u043d\u043d\u044b\u043c\u0438 \u043a\u0440\u0438\u0442\u0435\u0440\u0438\u044f\u043c\u0438.\"}), 400\n\n    df = pd.DataFrame(data)\n\n    # \u0421\u043e\u0437\u0434\u0430\u0435\u043c Excel \u0444\u0430\u0439\u043b\n    output = BytesIO()\n    with pd.ExcelWriter(output, engine='xlsxwriter') as writer:\n        df.to_excel(writer, index=False, sheet_name='Sheet1')\n\n        # \u041d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u043c \u0444\u043e\u0440\u043c\u0430\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435\n        workbook = writer.book\n        worksheet = writer.sheets['Sheet1']\n\n        # \u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0430\u044f \u0448\u0438\u0440\u0438\u043d\u0430 \u0441\u0442\u043e\u043b\u0431\u0446\u043e\u0432\n        for idx, col in enumerate(df.columns):\n            series = df[col]\n            max_len = max(\n                series.astype(str).map(len).max(),\n                len(str(col))\n            ) + 2\n            worksheet.set_column(idx, idx, max_len)\n\n    output.seek(0)\n\n    filename = 'RPA_export.xlsx' if export_all_rpa == 'true' else f'export_{date}.xlsx'\n    return send_file(\n        output,\n        mimetype='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',\n        as_attachment=True,\n        download_name=filename\n    )\n\n@app.route('/update_serial', methods=['POST'])\ndef update_serial():\n    try:\n        data = request.json\n        row_index = int(data['row_index'])\n        new_value = data['new_value']\n        date = data['date']\n\n        rows = TableRow.query.filter_by(date=date).all()\n        if 0 <= row_index < len(rows):\n            row = rows[row_index]\n            row.serial = new_value\n            db.session.commit()\n            return jsonify({\"status\": \"success\"})\n        return jsonify({\"status\": \"error\", \"message\": \"Invalid row index\"})\n    except Exception as e:\n        db.session.rollback()\n        return jsonify({\"status\": \"error\", \"message\": str(e)})\n\n\ndef initialize_table_for_date(date):\n    # \u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c, \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0442 \u043b\u0438 \u0443\u0436\u0435 \u0437\u0430\u043f\u0438\u0441\u0438 \u0434\u043b\u044f \u044d\u0442\u043e\u0439 \u0434\u0430\u0442\u044b\n    existing = TableRow.query.filter_by(date=date).first()\n    if not existing:\n        # \u0421\u043e\u0437\u0434\u0430\u0435\u043c \u043d\u043e\u0432\u0443\u044e \u0437\u0430\u043f\u0438\u0441\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u0432 \u0441\u043b\u0443\u0447\u0430\u0435 \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445\n        new_row = TableRow(\n            date=date,\n            row_number=str(1),\n            timestamp=datetime.now().strftime(\"%Y-%m-%d %H:%M:%S\"),\n            number='',\n            serial='',\n            dl_number='',\n            worker_name='',\n            arma_type='',\n            pack_time='',\n            dateshipment='',\n            aktshipment='',\n            bad_recovery='',\n        )\n        db.session.add(new_row)\n        \n        # \u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0435\u043c \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0443 \u0434\u043b\u044f \u043d\u043e\u0432\u043e\u0439 \u0434\u0430\u0442\u044b\n        statistics = Statistics(date=date, generate_clicks=0, pack_clicks=0)\n        db.session.add(statistics)\n        \n        db.session.commit()\n\n\n@app.route('/update_serial_arma', methods=['POST'])\ndef update_serial_arma():\n    try:\n        data = request.json\n        date = data['date']\n        serial = data['serial']\n        arma_type = data['arma_type']\n\n        # \u0421\u043e\u0437\u0434\u0430\u0435\u043c \u043d\u043e\u0432\u0443\u044e \u0437\u0430\u043f\u0438\u0441\u044c \u0432 \u0442\u0430\u0431\u043b\u0438\u0446\u0435\n        new_row = TableRow(\n            date=date,\n            serial=serial,\n            arma_type=arma_type,\n            timestamp=datetime.now().strftime(\"%Y-%m-%d %H:%M:%S\")\n        )\n\n        db.session.add(new_row)\n        db.session.commit()\n\n        return jsonify({\"status\": \"success\"})\n    except Exception as e:\n        db.session.rollback()\n        return jsonify({\"status\": \"error\", \"message\": str(e)}), 500\n\n@app.route('/get_statistics')\ndef get_statistics():\n    try:\n        date = request.args.get('date')\n        app.logger.debug(f\"\u041f\u043e\u043b\u0443\u0447\u0435\u043d \u0437\u0430\u043f\u0440\u043e\u0441 \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0438 \u0434\u043b\u044f \u0434\u0430\u0442\u044b: {date}\")\n        \n        # \u041f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0443 \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 \u0438 \u0443\u043f\u0430\u043a\u043e\u0432\u043a\u0438\n        statistics = Statistics.query.filter_by(date=date).first()\n        if not statistics:\n            generate_clicks = 0\n            pack_clicks = 0\n            app.logger.debug(f\"\u0421\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0430 \u0434\u043b\u044f \u0434\u0430\u0442\u044b {date} \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d\u0430. \u0423\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 0.\")\n        else:\n            generate_clicks = statistics.generate_clicks\n            pack_clicks = statistics.pack_clicks\n            app.logger.debug(f\"\u0421\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0430 \u0434\u043b\u044f \u0434\u0430\u0442\u044b {date}: \u0413\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0439 = {generate_clicks}, \u0423\u043f\u0430\u043a\u043e\u0432\u043e\u043a = {pack_clicks}\")\n        \n        # \u041f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0437\u0430\u043f\u0438\u0441\u0435\u0439 \u0442\u0438\u043f\u0430 \"RPA\"\n        rpa_records = TableRow.query.filter_by(date=date, arma_type='RPA').count()\n        app.logger.debug(f\"\u041a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0437\u0430\u043f\u0438\u0441\u0435\u0439 \u0442\u0438\u043f\u0430 RPA \u0434\u043b\u044f \u0434\u0430\u0442\u044b {date}: {rpa_records}\")\n        \n        # \u0421\u0447\u0438\u0442\u0430\u0435\u043c \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0437\u0430\u043f\u0438\u0441\u0435\u0439 \"RPA\" \u0431\u0435\u0437 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0432 \u043a\u043e\u043b\u043e\u043d\u043a\u0435 \"\u0413\u0440\u0430\u0444\u0430\"\n        unpacked_clicks = TableRow.query.filter(\n            TableRow.date == date,\n            TableRow.arma_type == 'RPA',\n            TableRow.dl_number == None\n        ).count()\n        \n        # \u041f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0443\u043f\u0430\u043a\u043e\u0432\u0430\u043d\u043d\u044b\u0445 \u0437\u0430\u043f\u0438\u0441\u0435\u0439 \u0437\u0430 \u0442\u0435\u043a\u0443\u0449\u0438\u0439 \u0447\u0430\u0441\n        current_hour = datetime.now().replace(minute=0, second=0, microsecond=0)\n        next_hour = current_hour + timedelta(hours=1)\n        done_per_hour = TableRow.query.filter(\n            TableRow.date == date,\n            TableRow.arma_type == 'RPA',\n            TableRow.pack_time >= current_hour,\n            TableRow.pack_time < next_hour\n        ).count()\n        \n        return jsonify({\n            \"generate_clicks\": generate_clicks,\n            \"pack_clicks\": pack_clicks,\n            \"rpa_records\": rpa_records,\n            \"unpacked_clicks\": unpacked_clicks,\n            \"done_per_hour\": done_per_hour\n        })\n    except Exception as e:\n        app.logger.error(f\"\u041e\u0448\u0438\u0431\u043a\u0430 \u0432 get_statistics: {str(e)}\")\n        return jsonify({\n            \"generate_clicks\": 0,\n            \"pack_clicks\": 0,\n            \"rpa_records\": 0,\n            \"unpacked_clicks\": 0,\n            \"done_per_hour\": 0,\n            \"error\": str(e)\n        })\n@app.route('/delete_row', methods=['POST'])\ndef delete_row():\n    try:\n        data = request.json\n        row_id = data.get('id')\n\n        if not row_id:\n            return jsonify({'status': 'error', 'message': 'ID \u0437\u0430\u043f\u0438\u0441\u0438 \u043d\u0435 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d'}), 400\n\n        row = TableRow.query.get(row_id)\n        if not row:\n            return jsonify({'status': 'error', 'message': '\u0417\u0430\u043f\u0438\u0441\u044c \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d\u0430'}), 404\n\n        date = row.date  # \u041f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0434\u0430\u0442\u0443 \u0437\u0430\u043f\u0438\u0441\u0438 \u0434\u043b\u044f \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0438\n\n        # \u041f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0437\u0430\u043f\u0438\u0441\u044c \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0438 \u0434\u043b\u044f \u044d\u0442\u043e\u0439 \u0434\u0430\u0442\u044b\n        statistics = Statistics.query.filter_by(date=date).first()\n\n        if statistics:\n            # \u0415\u0441\u043b\u0438 \u0437\u0430\u043f\u0438\u0441\u044c \u0438\u043c\u0435\u043b\u0430 \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 DL \u043d\u043e\u043c\u0435\u0440, \u0443\u043c\u0435\u043d\u044c\u0448\u0430\u0435\u043c generate_clicks\n            if row.dl_number:\n                if statistics.generate_clicks > 0:\n                    statistics.generate_clicks -= 1\n                else:\n                    app.logger.warning(f\"Attempting to decrement generate_clicks below zero for date {date}\")\n\n            # \u0415\u0441\u043b\u0438 \u0437\u0430\u043f\u0438\u0441\u044c \u0431\u044b\u043b\u0430 \u0443\u043f\u0430\u043a\u043e\u0432\u0430\u043d\u0430, \u0443\u043c\u0435\u043d\u044c\u0448\u0430\u0435\u043c pack_clicks\n            if row.pack_time:\n                if statistics.pack_clicks > 0:\n                    statistics.pack_clicks -= 1\n                else:\n                    app.logger.warning(f\"Attempting to decrement pack_clicks below zero for date {date}\")\n\n            db.session.commit()\n        else:\n            app.logger.warning(f\"No Statistics entry found for date {date} when deleting row {row_id}\")\n\n        # \u0423\u0434\u0430\u043b\u044f\u0435\u043c \u0437\u0430\u043f\u0438\u0441\u044c \u0438\u0437 \u0442\u0430\u0431\u043b\u0438\u0446\u044b\n        db.session.delete(row)\n        db.session.commit()\n\n        # \u0423\u043c\u0435\u043d\u044c\u0448\u0430\u0435\u043c \u0441\u0447\u0435\u0442\u0447\u0438\u043a DL, \u0435\u0441\u043b\u0438 \u0437\u0430\u043f\u0438\u0441\u044c \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043b\u0430 DL-\u043d\u043e\u043c\u0435\u0440\n        if row.dl_number:\n            dl_counter = DLCounter.query.filter_by(date=date).first()\n            if dl_counter and dl_counter.counter > 0:\n                dl_counter.counter -= 1\n                db.session.commit()\n\n        # \u041e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u0432 \u043e\u0447\u0435\u0440\u0435\u0434\u044c \u0434\u043b\u044f \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u0432\n        update_queue.put(json.dumps({\"type\": \"delete\", \"date\": date, \"id\": row.id}))\n\n        return jsonify({'status': 'success'})\n    except Exception as e:\n        db.session.rollback()\n        app.logger.error(f\"\u041e\u0448\u0438\u0431\u043a\u0430 \u0432 delete_row: {str(e)}\")\n        return jsonify({'status': 'error', 'message': str(e)}), 500\n\n@app.route('/', methods=['GET', 'POST'])\ndef main():\n    if request.method == 'POST':\n        worker = request.form.get('worker')\n        name = request.form.get('name')\n\n        # \u0421\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u043c \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e \u0432\u0445\u043e\u0434\u0435\n        user = User.query.filter_by(username=name).first()\n        if not user:\n            user = User(username=name)\n            db.session.add(user)\n\n        login_history = LoginHistory(user=user)\n        db.session.add(login_history)\n        db.session.commit()\n\n        resp = make_response(redirect('/welcome'))\n        resp.set_cookie('worker', worker)\n        resp.set_cookie('name', name)\n        return resp\n\n    return render_template('main.html')\n\n\n@app.route('/get_current_dl', methods=['GET'])\ndef get_current_dl():\n    date = request.args.get('date')\n    if not date:\n        return jsonify({\"status\": \"error\", \"message\": \"\u0414\u0430\u0442\u0430 \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u0430\"}), 400\n\n    dl_counter = DLCounter.query.filter_by(date=date).first()\n    if dl_counter:\n        return jsonify({\"status\": \"success\", \"current_dl\": dl_counter.counter})\n    else:\n        return jsonify({\"status\": \"error\", \"message\": \"\u0421\u0447\u0435\u0442\u0447\u0438\u043a DL \u043d\u0435 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d \u0434\u043b\u044f \u044d\u0442\u043e\u0439 \u0434\u0430\u0442\u044b\"}), 404\n\n\n@app.route('/welcome')\ndef welcome():\n    worker = request.cookies.get('worker')\n    name = request.cookies.get('name')\n\n    if not worker or not name:\n        return redirect('/')\n\n    current_time = datetime.utcnow()\n    devices = [device.to_dict(current_time=current_time) for device in Device.query.order_by(Device.name).all()]\n    current_time_str = current_time.isoformat()\n\n    # \u041f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0442\u0435\u043a\u0443\u0449\u0438\u0439 \u043f\u0440\u0435\u0444\u0438\u043a\u0441\n    prefix = Prefix.query.first()\n    dl_prefix = prefix.value if prefix else 'DL'\n\n    return render_template('welcome.html', name=name, worker=worker, table=table, devices=devices, current_time=current_time_str, dl_prefix=dl_prefix)\n\n\n@app.route('/logout')\ndef logout():\n    resp = make_response(redirect('/'))\n    resp.delete_cookie('worker')\n    resp.delete_cookie('name')\n    return resp\n\n@app.route('/get_unpacked_rpa_counts', methods=['GET'])\ndef get_unpacked_rpa_counts():\n    year = request.args.get('year')\n    month = request.args.get('month')\n    \n    if not year or not month:\n        return jsonify({\"status\": \"error\", \"message\": \"\u041d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u0433\u043e\u0434 \u0438 \u043c\u0435\u0441\u044f\u0446\"}), 400\n    \n    try:\n        year = int(year)\n        month = int(month)\n    except ValueError:\n        return jsonify({\"status\": \"error\", \"message\": \"\u0413\u043e\u0434 \u0438 \u043c\u0435\u0441\u044f\u0446 \u0434\u043e\u043b\u0436\u043d\u044b \u0431\u044b\u0442\u044c \u0447\u0438\u0441\u043b\u0430\u043c\u0438\"}), 400\n\n    # \u0424\u043e\u0440\u043c\u0438\u0440\u0443\u0435\u043c \u0444\u043e\u0440\u043c\u0430\u0442 \u0434\u0430\u0442\u044b \u0434\u043b\u044f \u0444\u0438\u043b\u044c\u0442\u0440\u0430\u0446\u0438\u0438\n    month_str = f\"{month:02d}\"\n    \n    # \u0417\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u0435\u043c \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0437\u0430\u043f\u0438\u0441\u0435\u0439 RPA \u0441 \u043f\u0443\u0441\u0442\u044b\u043c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435\u043c \u0432 \u043a\u043e\u043b\u043e\u043d\u043a\u0435 \"\u0412\u0440\u0435\u043c\u044f \u0443\u043f\u0430\u043a\u043e\u0432\u043a\u0438\" \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0434\u043d\u044f\n    unpacked_counts = TableRow.query.filter(\n        TableRow.date.like(f\"{year}-{month_str}-%\"),\n        TableRow.arma_type == 'RPA',\n        or_(TableRow.pack_time == None, TableRow.pack_time == '')\n    ).group_by(TableRow.date).with_entities(TableRow.date, func.count(TableRow.id)).all()\n    \n    # \u041f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u0443\u0435\u043c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0432 \u0441\u043b\u043e\u0432\u0430\u0440\u044c\n    unpacked_counts_dict = {date: count for date, count in unpacked_counts}\n    \n    return jsonify({'status': 'success', 'unpacked_counts': unpacked_counts_dict})\n\n@app.route('/get_last_dl_number_all_time', methods=['GET'])\ndef get_last_dl_number_all_time():\n    # \u041f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u044e\u044e \u0437\u0430\u043f\u0438\u0441\u044c \u0441 \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u044b\u043c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435\u043c DL \u0437\u0430 \u0432\u0441\u0451 \u0432\u0440\u0435\u043c\u044f\n    last_dl_row = TableRow.query.order_by(TableRow.dl_number.desc()).first()\n    if last_dl_row:\n        last_dl = last_dl_row.dl_number\n        if last_dl and last_dl.startswith('DL'):\n            last_dl_number = int(last_dl[2:])\n            next_dl_number = last_dl_number + 1\n        else:\n            next_dl_number = 1\n    else:\n        next_dl_number = 1\n\n    return jsonify({\"status\": \"success\", \"next_dl_number\": next_dl_number})\n\n\n@app.route('/import_excel', methods=['POST'])\ndef import_excel():\n    try:\n        # Check if a file is provided\n        if 'file' not in request.files:\n            return jsonify({\"status\": \"error\", \"message\": \"No file provided\"}), 400\n\n        # Get the uploaded file\n        file = request.files['file']\n\n        # Check the file extension for security reasons\n        if not file.filename.endswith('.xlsx') and not file.filename.endswith('.xls'):\n            return jsonify({\"status\": \"error\", \"message\": \"File type not allowed\"}), 400\n\n        # Read the Excel file into a DataFrame\n        df = pd.read_excel(file)\n\n        # Define the fields expected in the Excel file\n        required_columns = ['\u0412\u0440\u0435\u043c\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438', '\u041d\u043e\u043c\u0435\u0440', 'Serial', '\u0413\u0440\u0430\u0444\u0430', '\u0418\u043c\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u0435\u043b\u044f']\n\n        # Check if all required columns are in the DataFrame\n        if not all(col in df.columns for col in required_columns):\n            return jsonify({\"status\": \"error\", \"message\": f\"Missing required columns. Required columns are: {', '.join(required_columns)}\"}), 400\n\n        # Get current date\n        current_date = datetime.now().date().strftime(\"%Y-%m-%d\")\n\n        # Iterate over DataFrame rows and insert data into the database\n        for _, row in df.iterrows():\n            new_row = TableRow(\n                date=current_date,\n                timestamp=row['\u0412\u0440\u0435\u043c\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438'],\n                number=row['\u041d\u043e\u043c\u0435\u0440'],\n                serial=row['Serial'],\n                dl_number=row['\u0413\u0440\u0430\u0444\u0430'],\n                worker_name=row['\u0418\u043c\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u0435\u043b\u044f'],\n                row_number='',  # Will be calculated later\n                pack_time='0',  # Default value\n                arma_type='0',  # Default value\n                dateshipment='0', \n                aktshipment='0',   # Default value\n                bad_recovery=row.get('bad_recovery', False) ,\n            )\n            db.session.add(new_row)\n        db.session.commit()\n\n        # Update row numbers\n        rows_of_day = TableRow.query.filter_by(date=current_date).order_by(TableRow.id).all()\n        for idx, row in enumerate(rows_of_day, 1):\n            row.row_number = str(idx)\n        db.session.commit()\n\n        return jsonify({\"status\": \"success\", \"message\": \"Data imported successfully\"})\n\n    except Exception as e:\n        db.session.rollback()\n        app.logger.error(f\"Error during Excel import: {str(e)}\")  # \u041b\u043e\u0433\u0438\u0440\u0443\u0435\u043c \u043e\u0448\u0438\u0431\u043a\u0443\n        return jsonify({\"status\": \"error\", \"message\": str(e)}), 500\n    \n@app.route('/delete_imported_data', methods=['POST'])\ndef delete_imported_data():\n    try:\n        current_date = datetime.now().date().strftime(\"%Y-%m-%d\")\n        rows_deleted = TableRow.query.filter_by(date=current_date).delete()\n        db.session.commit()\n\n        return jsonify({\"status\": \"success\", \"message\": f\"{rows_deleted} rows deleted for date {current_date}\"})\n\n    except Exception as e:\n        db.session.rollback()\n        return jsonify({\"status\": \"error\", \"message\": str(e)}), 500\n    \n@app.route('/get_rpa_records', methods=['GET'])\ndef get_rpa_records():\n    try:\n        # \u0417\u0430\u043c\u0435\u043d\u0438\u0442\u0435 \u0444\u0438\u043b\u044c\u0442\u0440 \u043f\u043e \u0438\u043c\u0435\u043d\u0438 'worker_name' \u043d\u0430 \u0444\u0438\u043b\u044c\u0442\u0440 \u043f\u043e 'arma_type'\n        rows = TableRow.query.filter_by(arma_type='RPA').all()\n\n        data = []\n        for row in rows:\n            data.append({\n                'id': row.id,\n                'row_number': row.row_number,\n                'timestamp': row.timestamp,\n                'number': row.number,\n                'serial': row.serial,\n                'dl_number': row.dl_number,\n                'worker_name': row.worker_name,\n                'pack_time': row.pack_time,\n                'arma_type': row.arma_type,\n                'dateshipment': row.dateshipment,\n                'aktshipment': row.aktshipment,\n                'bad_recovery': row.bad_recovery,\n            })\n\n        return jsonify({\"status\": \"success\", \"data\": data})\n\n    except Exception as e:\n        return jsonify({\"status\": \"error\", \"message\": str(e)}), 500\n\n@app.route('/export_rpa_excel')\ndef export_rpa_excel():\n    try:\n        # \u041d\u0430\u0447\u0438\u043d\u0430\u0435\u043c \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d\u0438\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u0441 \u0444\u0438\u043b\u044c\u0442\u0440\u0430\u0446\u0438\u0438 \u043f\u043e \u0442\u0438\u043f\u0443 \u0410\u0420\u041c\u0410 \"RPA\"\n        query = TableRow.query.filter_by(arma_type='RPA')\n\n        # \u0414\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u0443\u0441\u043b\u043e\u0432\u0438\u044f \u0444\u0438\u043b\u044c\u0442\u0440\u0430\u0446\u0438\u0438: \n        # - dl_number \u043d\u0435 \u043f\u0443\u0441\u0442\u043e\u0439\n        # - pack_time \u043d\u0435 \u043f\u0443\u0441\u0442\u043e\u0439\n        query = query.filter(\n            TableRow.dl_number.isnot(None),\n            TableRow.dl_number != '',\n            TableRow.pack_time.isnot(None),\n            TableRow.pack_time != ''\n        )\n\n        rows = query.all()\n\n        # \u0421\u043e\u0437\u0434\u0430\u0435\u043c DataFrame \u0442\u043e\u043b\u044c\u043a\u043e \u0441 \u043e\u0442\u0444\u0438\u043b\u044c\u0442\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u043c\u0438 \u0434\u0430\u043d\u043d\u044b\u043c\u0438\n        data = []\n        for row in rows:\n            data.append({\n                '\u2116': row.row_number,\n                '\u0412\u0440\u0435\u043c\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438': row.timestamp,\n                '\u041d\u043e\u043c\u0435\u0440': row.number,\n                'Serial': row.serial,\n                '\u0413\u0440\u0430\u0444\u0430': row.dl_number,\n                '\u0418\u043c\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u0435\u043b\u044f': row.worker_name,\n                '\u0412\u0440\u0435\u043c\u044f \u0443\u043f\u0430\u043a\u043e\u0432\u043a\u0438': row.pack_time,\n                '\u0422\u0438\u043f \u0410\u0420\u041c\u0410': row.arma_type,\n                '\u0414\u0430\u0442\u0430 \u043e\u0442\u0433\u0440\u0443\u0437\u043a\u0438': row.dateshipment,\n                '\u041d\u043e\u043c\u0435\u0440 \u0430\u043a\u0442\u0430': row.aktshipment,\n                'bad_recovery': row.bad_recovery,\n            })\n\n        if not data:\n            return jsonify({\"error\": \"\u041d\u0435\u0442 \u0437\u0430\u043f\u0438\u0441\u0435\u0439 \u0434\u043b\u044f \u044d\u043a\u0441\u043f\u043e\u0440\u0442\u0430 \u0441 \u0437\u0430\u0434\u0430\u043d\u043d\u044b\u043c\u0438 \u043a\u0440\u0438\u0442\u0435\u0440\u0438\u044f\u043c\u0438.\"}), 400\n\n        df = pd.DataFrame(data)\n\n        # \u0421\u043e\u0437\u0434\u0430\u0435\u043c Excel \u0444\u0430\u0439\u043b\n        output = BytesIO()\n        with pd.ExcelWriter(output, engine='xlsxwriter') as writer:\n            df.to_excel(writer, index=False, sheet_name='Sheet1')\n\n            # \u041d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u043c \u0444\u043e\u0440\u043c\u0430\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435\n            workbook = writer.book\n            worksheet = writer.sheets['Sheet1']\n\n            # \u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0430\u044f \u0448\u0438\u0440\u0438\u043d\u0430 \u0441\u0442\u043e\u043b\u0431\u0446\u043e\u0432\n            for idx, col in enumerate(df.columns):\n                series = df[col]\n                max_len = max(\n                    series.astype(str).map(len).max(),\n                    len(str(col))\n                ) + 2\n                worksheet.set_column(idx, idx, max_len)\n\n                # \u0424\u043e\u0440\u043c\u0430\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0447\u0438\u0441\u043b\u043e\u0432\u044b\u0445 \u0441\u0442\u043e\u043b\u0431\u0446\u043e\u0432\n                if col in ['\u041d\u043e\u043c\u0435\u0440', '\u0413\u0440\u0430\u0444\u0430']:\n                    num_format = workbook.add_format({'num_format': '0'})\n                    worksheet.set_column(idx, idx, max_len, num_format)\n\n        output.seek(0)\n\n        return send_file(\n            output,\n            mimetype='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',\n            as_attachment=True,\n            download_name='RPA_export.xlsx'\n        )\n\n    except Exception as e:\n        print(f\"Export error: {str(e)}\")\n        return jsonify({\"error\": str(e)}), 500\n    \n\n@app.route('/get_duplicates')\ndef get_duplicates():\n    try:\n        # \u041f\u043e\u043b\u0443\u0447\u0438\u043c \u0432\u0441\u0435 \u0441\u0442\u0440\u043e\u043a\u0438 \u0438\u0437 \u0442\u0430\u0431\u043b\u0438\u0446\u044b\n        rows = TableRow.query.all()\n\n        # \u0425\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430 \u0434\u043b\u044f \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u0430 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439\n        numbers = {}\n        serials = {}\n        dl_numbers = {}\n\n        # \u0421\u043e\u0431\u0438\u0440\u0430\u0435\u043c \u0432\u0441\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0438 \u0438\u0445 \u0438\u043d\u0434\u0435\u043a\u0441\u044b\n        data = []\n        for row in rows:\n            row_data = {\n                'id': row.id,\n                'row_number': row.row_number,\n                'timestamp': row.timestamp,\n                'number': row.number,\n                'serial': row.serial,\n                'dl_number': row.dl_number,\n                'worker_name': row.worker_name,\n                'pack_time': row.pack_time,\n                'arma_type': row.arma_type,\n                'dateshipment': row.dateshipment,\n                'aktshipment': row.aktshipment,\n                'bad_recovery': row.bad_recovery,\n            }\n            data.append(row_data)\n            if row.number:\n                clean_number = ''.join(filter(str.isdigit, row.number))\n                if clean_number in numbers:\n                    numbers[clean_number].append(len(data) - 1)\n                else:\n                    numbers[clean_number] = [len(data) - 1]\n\n            if row.serial:\n                clean_serial = ''.join(filter(str.isdigit, row.serial))\n                if clean_serial in serials:\n                    serials[clean_serial].append(len(data) - 1)\n                else:\n                    serials[clean_serial] = [len(data) - 1]\n\n            if row.dl_number:\n                clean_dl_number = ''.join(filter(str.isdigit, row.dl_number))\n                if clean_dl_number in dl_numbers:\n                    dl_numbers[clean_dl_number].append(len(data) - 1)\n                else:\n                    dl_numbers[clean_dl_number] = [len(data) - 1]\n\n        # \u0424\u0438\u043b\u044c\u0442\u0440\u0443\u0435\u043c \u0442\u043e\u043b\u044c\u043a\u043e \u0440\u0435\u0430\u043b\u044c\u043d\u044b\u0435 \u0434\u0443\u0431\u043b\u0438\u043a\u0430\u0442\u044b\n        duplicate_numbers = {k: v for k, v in numbers.items() if len(v) > 1}\n        duplicate_serials = {k: v for k, v in serials.items() if len(v) > 1}\n        duplicate_dl_numbers = {k: v for k, v in dl_numbers.items() if len(v) > 1}\n\n        duplicates = {\n            \"numbers\": duplicate_numbers,\n            \"serials\": duplicate_serials,\n            \"dl_numbers\": duplicate_dl_numbers\n        }\n\n        # \u0421\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u043c \u0438\u043d\u0434\u0435\u043a\u0441\u044b \u0432\u0441\u0435\u0445 \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u044b\u0445 \u0434\u0443\u0431\u043b\u0438\u043a\u0430\u0442\u043e\u0432\n        duplicate_indices = set()\n        for indices in duplicate_numbers.values():\n            duplicate_indices.update(indices)\n        for indices in duplicate_serials.values():\n            duplicate_indices.update(indices)\n        for indices in duplicate_dl_numbers.values():\n            duplicate_indices.update(indices)\n\n        # \u041e\u0442\u0431\u0438\u0440\u0430\u0435\u043c \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u0443\u0431\u043b\u0438\u043a\u0430\u0442\u044b\n        duplicates_data = [data[idx] for idx in duplicate_indices]\n\n        return jsonify({\n            \"status\": \"success\",\n            \"data\": duplicates_data,\n            \"duplicates\": duplicates\n        })\n\n    except Exception as e:\n        return jsonify({\"status\": \"error\", \"message\": str(e)})\n\nif __name__ == '__main__':\n    with app.app_context():\n        db.create_all()\n        create_devices()\n\n\n\n    logging.disable(logging.CRITICAL)\n    os.system('title \u0421\u0415\u0420\u0412\u0415\u0420')\n    app.run(host='192.168.50.110', port=80, debug=True)  #192.168.50.99"},{"assistant_initiates":false,"asst_text":"\u0415\u0441\u043b\u0438 \u0432\u0441\u0435 \u0437\u0430\u043f\u0438\u0441\u0438 \u0432 \u043f\u043e\u043b\u0435 `bad_recovery` \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u044e\u0442 `True`, \u044d\u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u043d\u0430 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u0445 \u043f\u0440\u0438\u0447\u0438\u043d. \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0440\u0430\u0437\u0431\u0435\u0440\u0451\u043c\u0441\u044f \u043f\u043e \u0448\u0430\u0433\u0430\u043c:\n\n1. **\u041f\u043e\u0434\u0441\u0447\u0451\u0442 \u0434\u0443\u0431\u043b\u0438\u043a\u0430\u0442\u043e\u0432**: \u0423\u0431\u0435\u0434\u0438\u0442\u0435\u0441\u044c, \u0447\u0442\u043e \u0432\u0430\u0448\u0430 \u043b\u043e\u0433\u0438\u043a\u0430 \u043f\u043e\u0434\u0441\u0447\u0451\u0442\u0430 \u0434\u0443\u0431\u043b\u0438\u043a\u0430\u0442\u043e\u0432 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e. \u0412 \u0447\u0430\u0441\u0442\u043d\u043e\u0441\u0442\u0438, \u043f\u0440\u043e\u0432\u0435\u0440\u044c\u0442\u0435, \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e \u043b\u0438 \u0432\u044b \u043e\u0447\u0438\u0449\u0430\u0435\u0442\u0435 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u0432 \u043f\u043e\u043b\u044f\u0445 `number`, `serial` \u0438 `dl_number` \u0438 \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0443\u0441\u043b\u043e\u0432\u0438\u0435, \u043f\u0440\u0438 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0432\u044b \u0441\u0447\u0438\u0442\u0430\u0435\u0442\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0434\u0443\u0431\u043b\u0438\u043a\u0430\u0442\u043e\u0432 \u0442\u043e\u043b\u044c\u043a\u043e \u0435\u0441\u043b\u0438 \u0435\u0441\u0442\u044c \u0444\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f.\n\n2. **\u041f\u0440\u043e\u0433\u043e\u043d \u0434\u0430\u043d\u043d\u044b\u0445**: \u0423\u0431\u0435\u0434\u0438\u0442\u0435\u0441\u044c, \u0447\u0442\u043e \u0432 \u0431\u0430\u0437\u0435 \u0434\u0430\u043d\u043d\u044b\u0445 \u043d\u0430 \u0441\u0430\u043c\u043e\u043c \u0434\u0435\u043b\u0435 \u043d\u0435\u0442 \u0434\u0443\u0431\u043b\u0438\u043a\u0430\u0442\u043e\u0432 \u0432\u0432\u043e\u0434\u0438\u043c\u044b\u0445 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439. \u0412\u043e\u0437\u043c\u043e\u0436\u043d\u043e, \u0432\u044b \u0441\u043b\u0443\u0447\u0430\u0439\u043d\u043e \u0437\u0430\u043f\u043e\u043b\u043d\u0438\u043b\u0438 \u0442\u0430\u0431\u043b\u0438\u0446\u0443 \u0438\u0434\u0435\u043d\u0442\u0438\u0447\u043d\u044b\u043c\u0438 \u0434\u0430\u043d\u043d\u044b\u043c\u0438.\n\n3. **\u041b\u043e\u0433\u0438\u043a\u0430 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 `bad_recovery`**: \u041c\u044b \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c, \u0435\u0441\u043b\u0438 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0434\u0443\u0431\u043b\u0438\u043a\u0430\u0442\u043e\u0432 \u0434\u043b\u044f \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0432 \u043a\u0430\u0436\u0434\u043e\u043c \u0438\u0437 \u043f\u043e\u043b\u0435\u0439 \u0431\u043e\u043b\u044c\u0448\u0435 1. \u0415\u0441\u043b\u0438 \u044d\u0442\u043e \u0443\u0441\u043b\u043e\u0432\u0438\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f, \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0430\u044f `bad_recovery` \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u0432 `True`.\n\n\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0435\u0449\u0451 \u0440\u0430\u0437 \u043f\u0440\u043e\u043a\u043e\u043d\u0442\u0440\u043e\u043b\u0438\u0440\u0443\u0435\u043c \u0443\u0447\u0430\u0441\u0442\u043e\u043a \u043a\u043e\u0434\u0430, responsible for setting `bad_recovery`, \u0438 \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0435 \u043b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435:\n\n```python\n# \u0423\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 bad_recovery\nfor row in rows:\n    number_duplicate = False\n    serial_duplicate = False\n    dl_number_duplicate = False\n\n    # \u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c \u043d\u043e\u043c\u0435\u0440\n    if row.number:\n        clean_number = ''.join(filter(str.isdigit, row.number)).strip()\n        number_duplicate = number_count.get(clean_number, 0) > 1\n\n    # \u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c Serial\n    if row.serial:\n        clean_serial = ''.join(filter(str.isdigit, row.serial)).strip()\n        serial_duplicate = serial_count.get(clean_serial, 0) > 1\n\n    # \u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c DL Number\n    if row.dl_number:\n        clean_dl_number = ''.join(filter(str.isdigit, row.dl_number)).strip()\n        dl_number_duplicate = dl_number_count.get(clean_dl_number, 0) > 1\n\n    # \u0423\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 bad_recovery \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u043d\u0430\u043b\u0438\u0447\u0438\u044f \u0434\u0443\u0431\u043b\u0438\u043a\u0430\u0442\u043e\u0432\n    row.bad_recovery = number_duplicate or serial_duplicate or dl_number_duplicate\n\n    # \u041b\u043e\u0433\u0438\u0440\u0443\u0435\u043c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b\n    app.logger.debug(f\"Row ID: {row.id}, Number: {row.number}, Serial: {row.serial}, DL Number: {row.dl_number}\")\n    app.logger.debug(f\"Duplicates - Number: {number_duplicate}, Serial: {serial_duplicate}, DL Number: {dl_number_duplicate}\")\n    app.logger.debug(f\"Bad Recovery for Row ID {row.id}: {row.bad_recovery}\")\n\n# \u0421\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u043c \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f\ndb.session.commit()\n```\n\n### \u0420\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0430\u0446\u0438\u0438 \u043f\u043e \u043e\u0442\u043b\u0430\u0434\u043a\u0435:\n\n1. **\u041b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435**: \u0412\u043d\u0438\u043c\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u043f\u0440\u043e\u0441\u043c\u0430\u0442\u0440\u0438\u0432\u0430\u0439\u0442\u0435 \u043b\u043e\u0433\u0438, \u0447\u0442\u043e\u0431\u044b \u0443\u0434\u043e\u0441\u0442\u043e\u0432\u0435\u0440\u0438\u0442\u044c\u0441\u044f, \u043a\u0430\u043a\u0438\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u044e\u0442\u0441\u044f \u0434\u043b\u044f `number`, `serial` \u0438 `dl_number`, \u0438 \u043a\u0430\u043a\u043e\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0434\u0443\u0431\u043b\u0438\u043a\u0430\u0442\u043e\u0432 \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u0442\u0441\u044f.\n  \n2. **\u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u0432 \u0411\u0414**: \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442 \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 SQL, \u0447\u0442\u043e\u0431\u044b \u0432\u0440\u0443\u0447\u043d\u0443\u044e \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c, \u0435\u0441\u0442\u044c \u043b\u0438 \u0434\u0443\u0431\u043b\u0438\u043a\u0430\u0442\u044b \u0432 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f\u0445, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0434\u043e\u043b\u0436\u043d\u044b \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0442\u044c\u0441\u044f. \u0417\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u0435 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0435 SQL \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u0434\u043b\u044f \u043f\u043e\u0438\u0441\u043a\u0430 \u0434\u0443\u0431\u043b\u0438\u043a\u0430\u0442\u043e\u0432 \u043f\u043e \u0432\u0430\u0448\u0438\u043c \u043a\u0440\u0438\u0442\u0435\u0440\u0438\u044f\u043c.\n\n3. **\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u0445 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u0434\u043b\u044f \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445**: \u041f\u043e\u043f\u0440\u043e\u0431\u0443\u0439\u0442\u0435 \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043e\u0442\u043b\u0430\u0434\u043e\u0447\u043d\u0443\u044e \u043b\u043e\u0433\u0438\u043a\u0443, \u0447\u0442\u043e\u0431\u044b \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0432 \u043a\u0430\u043a\u043e\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 \u0438 \u043a\u0430\u043a\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u0432\u044b\u0445\u043e\u0434\u044f\u0442 \u0432 `bad_recovery`.\n\n\u0415\u0441\u043b\u0438 \u043f\u043e\u0441\u043b\u0435 \u0432\u0441\u0435\u0445 \u043f\u0440\u043e\u0432\u0435\u0440\u043e\u043a \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430 \u043e\u0441\u0442\u0430\u0451\u0442\u0441\u044f, \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u043f\u0440\u043e\u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0441 \u043f\u0440\u043e\u0441\u0442\u044b\u043c \u043d\u0430\u0431\u043e\u0440\u043e\u043c \u0442\u0435\u0441\u0442\u043e\u0432\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445, \u0447\u0442\u043e\u0431\u044b \u0443\u0431\u0435\u0434\u0438\u0442\u044c\u0441\u044f, \u0447\u0442\u043e \u043b\u043e\u0433\u0438\u043a\u0430 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0442\u0430\u043a, \u043a\u0430\u043a \u043e\u0436\u0438\u0434\u0430\u0435\u0442\u0441\u044f.","behavior":"degenerate_repetition","conversation_hash":"6bc71a2034fca9ff9176bc3c9a73f460","conversation_redacted":false,"conversation_toxic":false,"country":"Russia","empty_output":false,"evidence_codes":[],"label":"absent","label_present":false,"label_qualified":false,"label_source":"Final dense release","language":"Russian","model":"gpt-4o-mini-2024-07-18","n_chars":3023,"n_turns_in_conversation":7,"n_words":340,"source_row_offset":742,"source_shard":"turns-00054.parquet","timestamp":"Fri, 29 Nov 2024 10:07:41 GMT","turn_id":"511188054affb9f90cc03749","turn_index":1,"user_text":"\u043f\u043e\u0447\u0435\u043c\u0443 \u0443 \u043c\u0435\u043d\u044f \u0432\u0441\u0435 \u0437\u0430\u043f\u0438\u0441\u0438 true \u043d\u0435 \u043f\u043e\u043d\u0438\u043c\u0430\u044e"},{"assistant_initiates":false,"asst_text":"\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0440\u0430\u0437\u0431\u0435\u0440\u0435\u043c \u043a\u043b\u044e\u0447\u0435\u0432\u044b\u0435 \u043c\u043e\u043c\u0435\u043d\u0442\u044b \u043a\u043e\u0434\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432\u044b \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u0438\u043b\u0438, \u0438 \u043f\u043e\u0439\u043c\u0435\u043c, \u0447\u0442\u043e \u0438\u043c\u0435\u043d\u043d\u043e \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u043d\u0430 \u043a\u0430\u0436\u0434\u043e\u043c \u044d\u0442\u0430\u043f\u0435.\n\n### 1. \u041f\u043e\u0434\u0441\u0447\u0435\u0442 \u0434\u0443\u0431\u043b\u0438\u043a\u0430\u0442\u043e\u0432\n\n\u0421\u043d\u0430\u0447\u0430\u043b\u0430 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u043f\u043e\u0434\u0441\u0447\u0435\u0442 \u0434\u0443\u0431\u043b\u0438\u043a\u0430\u0442\u043e\u0432 \u043f\u043e \u043a\u0430\u0436\u0434\u043e\u043c\u0443 \u0438\u0437 \u043f\u043e\u043b\u0435\u0439: `number`, `serial`, \u0438 `dl_number`:\n\n```python\nfor row in rows:\n    # \u041d\u043e\u043c\u0435\u0440\n    if row.number:\n        clean_number = ''.join(filter(str.isdigit, row.number)).strip()\n        if clean_number:\n            number_count[clean_number] = number_count.get(clean_number, 0) + 1\n\n    # Serial\n    if row.serial:\n        clean_serial = ''.join(filter(str.isdigit, row.serial)).strip()\n        if clean_serial:\n            serial_count[clean_serial] = serial_count.get(clean_serial, 0) + 1\n\n    # DL Number\n    if row.dl_number:\n        clean_dl_number = ''.join(filter(str.isdigit, row.dl_number)).strip()\n        if clean_dl_number:\n            dl_number_count[clean_dl_number] = dl_number_count.get(clean_dl_number, 0) + 1\n```\n\n**\u0427\u0442\u043e \u0437\u0434\u0435\u0441\u044c \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442?**\n- \u0414\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0439 \u0441\u0442\u0440\u043e\u043a\u0438 \u0434\u0430\u043d\u043d\u044b\u0445 (\u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0430\u044f `row`) \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043d\u0430 \u043d\u0430\u043b\u0438\u0447\u0438\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439 \u0432 \u043f\u043e\u043b\u044f\u0445 `number`, `serial` \u0438 `dl_number`.\n- \u0415\u0441\u043b\u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442, \u043e\u043d\u043e \u043e\u0447\u0438\u0449\u0430\u0435\u0442\u0441\u044f \u043e\u0442 \u043d\u0435\u0446\u0438\u0444\u0440\u043e\u0432\u044b\u0445 \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u0432 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e `filter` \u0438 `str.isdigit`.\n- \u0417\u0430\u0442\u0435\u043c \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u043f\u043e\u0434\u0441\u0447\u0435\u0442 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0430 \u0432\u0445\u043e\u0436\u0434\u0435\u043d\u0438\u0439 \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0432 \u0441\u043b\u043e\u0432\u0430\u0440\u044f\u0445 `number_count`, `serial_count`, \u0438 `dl_number_count`.\n\n\n### 2. \u0423\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u0444\u043b\u0430\u0433\u0430 `bad_recovery`\n\n\u0417\u0430\u0442\u0435\u043c \u043c\u044b \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u043c \u043a \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0444\u043b\u0430\u0433\u0430 `bad_recovery` \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0439 \u0441\u0442\u0440\u043e\u043a\u0438:\n\n```python\nfor row in rows:\n    number_duplicate = False\n    serial_duplicate = False\n    dl_number_duplicate = False\n\n    if row.number:\n        clean_number = ''.join(filter(str.isdigit, row.number)).strip()\n        number_duplicate = number_count.get(clean_number, 0) > 1\n\n    if row.serial:\n        clean_serial = ''.join(filter(str.isdigit, row.serial)).strip()\n        serial_duplicate = serial_count.get(clean_serial, 0) > 1\n\n    if row.dl_number:\n        clean_dl_number = ''.join(filter(str.isdigit, row.dl_number)).strip()\n        dl_number_duplicate = dl_number_count.get(clean_dl_number, 0) > 1\n\n    # \u0423\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 bad_recovery \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u043d\u0430\u043b\u0438\u0447\u0438\u044f \u0434\u0443\u0431\u043b\u0438\u043a\u0430\u0442\u043e\u0432\n    row.bad_recovery = number_duplicate or serial_duplicate or dl_number_duplicate\n```\n\n**\u0427\u0442\u043e \u0437\u0434\u0435\u0441\u044c \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442?**\n- \u0412 \u043d\u0430\u0447\u0430\u043b\u0435 \u043a\u0430\u0436\u0434\u043e\u0439 \u0438\u0442\u0435\u0440\u0430\u0446\u0438\u0438 \u0441\u043e\u0437\u0434\u0430\u044e\u0442\u0441\u044f \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0444\u0438\u043a\u0441\u0438\u0440\u0443\u044e\u0442 \u043d\u0430\u043b\u0438\u0447\u0438\u0435 \u0434\u0443\u0431\u043b\u0438\u043a\u0430\u0442\u043e\u0432 (`number_duplicate`, `serial_duplicate`, \u0438 `dl_number_duplicate`).\n- \u0415\u0441\u043b\u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043f\u043e\u043b\u044f \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442, \u043e\u043d\u043e \u0441\u043d\u043e\u0432\u0430 \u043e\u0447\u0438\u0449\u0430\u0435\u0442\u0441\u044f \u043e\u0442 \u043d\u0435\u0446\u0438\u0444\u0440\u043e\u0432\u044b\u0445 \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u0432.\n- \u0417\u0430\u0442\u0435\u043c \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0438\u0437 \u043f\u043e\u043b\u0435\u0439 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442\u0441\u044f, \u0435\u0441\u0442\u044c \u043b\u0438 \u0435\u0433\u043e \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0432 \u0441\u043b\u043e\u0432\u0430\u0440\u0435 \u0431\u043e\u043b\u0435\u0435 1. \u0415\u0441\u043b\u0438 \u0434\u0430, \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0430\u044f \u0434\u0443\u0431\u043b\u0438\u043a\u0430\u0442\u0430 \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u0432 `True`.\n- \u041d\u0430\u043a\u043e\u043d\u0435\u0446, \u043f\u043e\u043b\u0435 `bad_recovery` \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u0432 `True`, \u0435\u0441\u043b\u0438 \u0445\u043e\u0442\u044f \u0431\u044b \u043e\u0434\u043d\u043e \u0438\u0437 \u043f\u043e\u043b\u0435\u0439 (`number`, `serial`, \u0438\u043b\u0438 `dl_number`) \u0438\u043c\u0435\u0435\u0442 \u0434\u0443\u0431\u043b\u0438\u043a\u0430\u0442\u044b.\n\n### 3. \u041f\u0440\u043e\u0431\u043b\u0435\u043c\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u043e\u0433\u0443\u0442 \u0432\u043e\u0437\u043d\u0438\u043a\u043d\u0443\u0442\u044c\n\n\u0415\u0441\u043b\u0438 \u0432\u0441\u0435 \u0437\u0430\u043f\u0438\u0441\u0438 \u0432 `bad_recovery` \u0441\u0442\u0430\u043d\u043e\u0432\u044f\u0442\u0441\u044f `True`, \u044d\u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442\u044c \u043f\u043e \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043f\u0440\u0438\u0447\u0438\u043d\u0430\u043c:\n\n1. **\u0412\u0441\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u043e\u0434\u0438\u043d\u0430\u043a\u043e\u0432\u044b\u0435**: \u0415\u0441\u043b\u0438 \u0432 \u0432\u0430\u0448\u0435\u0439 \u0431\u0430\u0437\u0435 \u0434\u0430\u043d\u043d\u044b\u0445 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043f\u0440\u0438\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u044e\u0442 \u0437\u0430\u043f\u0438\u0441\u0438 \u0441 \u043e\u0434\u0438\u043d\u0430\u043a\u043e\u0432\u044b\u043c\u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f\u043c\u0438 \u0432\u043e \u0432\u0441\u0435\u0445 \u043f\u043e\u043b\u044f\u0445, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0434\u043b\u044f `number`, `serial`, \u0438 `dl_number`, \u0442\u043e \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0431\u0443\u0434\u0435\u0442 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0442\u044c `True` \u0434\u043b\u044f \u0432\u0441\u0435\u0445 \u0437\u0430\u043f\u0438\u0441\u0435\u0439.\n\n2. **\u041e\u0448\u0438\u0431\u043a\u0430 \u0432 \u043e\u0447\u0438\u0449\u0435\u043d\u0438\u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439**: \u0415\u0441\u043b\u0438 \u043f\u043e \u043a\u0430\u043a\u043e\u0439-\u0442\u043e \u043f\u0440\u0438\u0447\u0438\u043d\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0432 \u043f\u043e\u043b\u044f\u0445 `number`, `serial`, \u0438\u043b\u0438 `dl_number` \u043e\u0447\u0438\u0449\u0430\u044e\u0442\u0441\u044f \u043d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e, \u0442\u043e \u044d\u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u043f\u0440\u0438\u0432\u0435\u0441\u0442\u0438 \u043a \u0442\u043e\u043c\u0443, \u0447\u0442\u043e \u0437\u0430\u043f\u0438\u0441\u0438 \u0431\u0443\u0434\u0443\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u0438\u0434\u0435\u043d\u0442\u0438\u0447\u043d\u043e, \u0447\u0442\u043e \u0442\u0430\u043a\u0436\u0435 \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u043d\u0430\u043b\u0438\u0447\u0438\u0435 \u0434\u0443\u0431\u043b\u0438\u043a\u0430\u0442\u043e\u0432.\n\n3. **\u041b\u043e\u0433\u0438\u043a\u0430 \u043f\u043e\u0434\u0441\u0447\u0435\u0442\u0430 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0430 \u0434\u0443\u0431\u043b\u0438\u043a\u0430\u0442\u043e\u0432**: \u0423\u0431\u0435\u0434\u0438\u0442\u0435\u0441\u044c, \u0447\u0442\u043e \u043f\u043e\u0434\u0441\u0447\u0435\u0442 \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e \u043d\u0430 \u0432\u0441\u0435\u0445 \u0437\u0430\u043f\u0438\u0441\u044f\u0445 \u0438 \u0447\u0442\u043e \u0432\u044b \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442\u0435 \u043a\u0430\u0436\u0434\u043e\u0435 \u043f\u043e\u043b\u0435 \u043d\u0430 \u043d\u0430\u043b\u0438\u0447\u0438\u0435 \u0434\u0443\u0431\u043b\u0438\u043a\u0430\u0442\u043e\u0432 \u0432 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0435 \u0432\u0441\u0435\u0439 \u0431\u0430\u0437\u044b \u0434\u0430\u043d\u043d\u044b\u0445.\n\n4. **\u0422\u0435\u0441\u0442\u043e\u0432\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435**: \u041f\u0440\u043e\u0432\u0435\u0440\u044c\u0442\u0435 \u0432\u0430\u0448\u0443 \u0431\u0430\u0437\u0443 \u0434\u0430\u043d\u043d\u044b\u0445 \u043d\u0430 \u043d\u0430\u043b\u0438\u0447\u0438\u0435 \u0442\u0435\u0441\u0442\u043e\u0432\u044b\u0445 \u043d\u0430\u0431\u043e\u0440\u043e\u0432 \u0434\u0430\u043d\u043d\u044b\u0445 \u0434\u043b\u044f \u043f\u043e\u0438\u0441\u043a\u0430 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u0445 \u0434\u0443\u0431\u043b\u0438\u043a\u0430\u0442\u043e\u0432.\n\n### \u0420\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0430\u0446\u0438\u0438 \u043f\u043e \u043e\u0442\u043b\u0430\u0434\u043a\u0435\n\n- \u041b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439: \u0414\u043e\u0431\u0430\u0432\u044c\u0442\u0435 \u0431\u043e\u043b\u044c\u0448\u0435 \u043b\u043e\u0433\u043e\u0432, \u0447\u0442\u043e\u0431\u044b \u0443\u0432\u0438\u0434\u0435\u0442\u044c, \u043a\u0430\u043a\u0438\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u043f\u0440\u043e\u0445\u043e\u0434\u044f\u0442 \u0447\u0435\u0440\u0435\u0437 \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438, \u0438 \u0444\u0438\u043a\u0441\u0438\u0440\u0443\u0439\u0442\u0435 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u043f\u043e\u0434\u0441\u0447\u0435\u0442\u0430 \u0434\u0443\u0431\u043b\u0438\u043a\u0430\u0442\u043e\u0432 \u043f\u0435\u0440\u0435\u0434 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u043e\u0439 `bad_recovery`.\n\n- \u0424\u0438\u043b\u044c\u0442\u0440\u0430\u0446\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445: \u041f\u0440\u043e\u0432\u0435\u0440\u044c\u0442\u0435, \u043d\u0435\u0442 \u043b\u0438 \u043d\u0435\u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0438\u0439 \u0432 \u0444\u0438\u043b\u044c\u0442\u0440\u0430\u0446\u0438\u0438 \u0434\u0430\u043d\u043d\u044b\u0445. \u0412\u043e\u0437\u043c\u043e\u0436\u043d\u043e, \u043f\u043e\u043b\u044f \u043d\u0435 \u043e\u0447\u0438\u0449\u0430\u044e\u0442\u0441\u044f, \u043a\u0430\u043a \u043f\u0440\u0435\u0434\u043f\u043e\u043b\u0430\u0433\u0430\u043b\u043e\u0441\u044c, \u0438\u043b\u0438 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u044e\u0442\u0441\u044f \u043d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e.\n\n\u041f\u0440\u043e\u0432\u0435\u0440\u0438\u0432 \u044d\u0442\u0438 \u043c\u043e\u043c\u0435\u043d\u0442\u044b, \u0432\u044b \u0441\u043c\u043e\u0436\u0435\u0442\u0435 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442\u044c \u043f\u0440\u0438\u0447\u0438\u043d\u0443 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b \u0438 \u0443\u0441\u0442\u0440\u0430\u043d\u0438\u0442\u044c \u0435\u0435.","behavior":"degenerate_repetition","conversation_hash":"6bc71a2034fca9ff9176bc3c9a73f460","conversation_redacted":false,"conversation_toxic":false,"country":"Russia","empty_output":false,"evidence_codes":[],"label":"absent","label_present":false,"label_qualified":false,"label_source":"Final dense release","language":"Russian","model":"gpt-4o-mini-2024-07-18","n_chars":4160,"n_turns_in_conversation":7,"n_words":477,"source_row_offset":743,"source_shard":"turns-00054.parquet","timestamp":"Fri, 29 Nov 2024 10:07:41 GMT","turn_id":"dd88c2605cf15ac17ed68c4b","turn_index":2,"user_text":"\u0447\u0442\u043e \u0437\u0434\u0435\u0441\u044c \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442?"},{"assistant_initiates":false,"asst_text":"\u041e\u0448\u0438\u0431\u043a\u0430 `UnboundLocalError: cannot access local variable 'row' where it is not associated with a value` \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442 \u043d\u0430 \u0442\u043e, \u0447\u0442\u043e \u0432 \u0432\u0430\u0448\u0435\u043c \u043a\u043e\u0434\u0435 \u0432\u044b \u043f\u044b\u0442\u0430\u0435\u0442\u0435\u0441\u044c \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f \u043a \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 `row`, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043d\u0435 \u0431\u044b\u043b\u0430 \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u0430 \u0438\u043b\u0438 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0430 \u0432 \u0442\u043e\u043c \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0435, \u0433\u0434\u0435 \u0432\u044b \u0435\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0435.\n\n### \u0420\u0430\u0437\u0431\u043e\u0440 \u043e\u0448\u0438\u0431\u043e\u043a\n\n1. **DeprecationWarning**:\n   - **\u041f\u0440\u0438\u0447\u0438\u043d\u0430**: `datetime.datetime.utcnow()` \u0441\u0447\u0438\u0442\u0430\u0435\u0442\u0441\u044f \u0443\u0441\u0442\u0430\u0440\u0435\u0432\u0448\u0438\u043c (deprecated) \u0432 \u043d\u043e\u0432\u044b\u0445 \u0432\u0435\u0440\u0441\u0438\u044f\u0445 Python. \u0412\u043c\u0435\u0441\u0442\u043e \u043d\u0435\u0435 \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u0435\u0442\u0441\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c `datetime.datetime.now(datetime.timezone.utc)`.\n   - **\u0420\u0435\u0448\u0435\u043d\u0438\u0435**:\n     \u0418\u0437\u043c\u0435\u043d\u0438\u0442\u0435 \u0432\u0441\u0435 \u0441\u043b\u0443\u0447\u0430\u0438 `datetime.utcnow()` \u043d\u0430 `datetime.now(datetime.timezone.utc)`. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440:\n     ```python\n     now = datetime.now(datetime.timezone.utc)\n     current_time = datetime.now(datetime.timezone.utc)\n     ```\n\n2. **UnboundLocalError**:\n   - **\u041f\u0440\u0438\u0447\u0438\u043d\u0430**: \u042d\u0442\u0430 \u043e\u0448\u0438\u0431\u043a\u0430 \u043c\u043e\u0436\u0435\u0442 \u0432\u043e\u0437\u043d\u0438\u043a\u043d\u0443\u0442\u044c, \u0435\u0441\u043b\u0438 \u0432\u044b \u043f\u044b\u0442\u0430\u0435\u0442\u0435\u0441\u044c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c `row` \u0432\u043d\u0435 \u0435\u0433\u043e \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0430. \u042d\u0442\u043e \u043e\u0431\u044b\u0447\u043d\u043e \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442, \u0435\u0441\u043b\u0438 \u043a\u043e\u0434 \u0432\u043d\u0443\u0442\u0440\u0438 \u0446\u0438\u043a\u043b\u0430 \u043d\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f, \u043b\u0438\u0431\u043e \u0435\u0441\u043b\u0438 \u043d\u0435\u0442 \u0434\u0430\u043d\u043d\u044b\u0445 \u0434\u043b\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438.\n   - **\u0420\u0435\u0448\u0435\u043d\u0438\u0435**: \u0423\u0431\u0435\u0434\u0438\u0442\u0435\u0441\u044c, \u0447\u0442\u043e \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0430\u044f `row` \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0430 \u0432 \u043f\u0440\u0435\u0434\u0435\u043b\u0430\u0445 \u043e\u0431\u043b\u0430\u0441\u0442\u0438 \u0432\u0438\u0434\u0438\u043c\u043e\u0441\u0442\u0438. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0435\u0441\u043b\u0438 \u0432\u044b \u043e\u0431\u0440\u0430\u0449\u0430\u0435\u0442\u0435\u0441\u044c \u043a \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 \u0432 \u0431\u043b\u043e\u043a\u0435 \u043a\u043e\u0434\u0430, \u0433\u0434\u0435 \u043e\u043d\u0430 \u043d\u0435 \u0431\u044b\u043b\u0430 \u043e\u0431\u044a\u044f\u0432\u043b\u0435\u043d\u0430, \u044d\u0442\u043e \u0432\u044b\u0437\u043e\u0432\u0435\u0442 \u044d\u0442\u0443 \u043e\u0448\u0438\u0431\u043a\u0443.\n\n### \u041a\u0430\u043a \u0438\u0441\u043f\u0440\u0430\u0432\u0438\u0442\u044c UnboundLocalError\n\n1. **\u041f\u0440\u043e\u0432\u0435\u0440\u044c\u0442\u0435, \u0447\u0442\u043e `rows` \u043d\u0435 \u043f\u0443\u0441\u0442\u043e\u0439**: \u041f\u0435\u0440\u0435\u0434 \u0442\u0435\u043c \u043a\u0430\u043a \u043f\u0440\u043e\u0445\u043e\u0434\u0438\u0442\u044c \u043f\u043e `rows`, \u0434\u043e\u0431\u0430\u0432\u044c\u0442\u0435 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0443 \u043d\u0430 \u043d\u0430\u043b\u0438\u0447\u0438\u0435 \u0437\u0430\u043f\u0438\u0441\u0435\u0439.\n\n```python\nrows = query.all()\nif not rows:\n    app.logger.debug(\"\u041d\u0435\u0442 \u0437\u0430\u043f\u0438\u0441\u0435\u0439 \u0434\u043b\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438.\")\n    return jsonify({\"data\": []})  # \u0418\u043b\u0438 \u043b\u044e\u0431\u043e\u0435 \u0434\u0440\u0443\u0433\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435, \u043f\u043e\u0434\u0445\u043e\u0434\u044f\u0449\u0435\u0435 \u0434\u043b\u044f \u0432\u0430\u0448\u0435\u0433\u043e \u043e\u0442\u0432\u0435\u0442\u0430\n```\n\n2. **\u041e\u0442\u043b\u0430\u0434\u043e\u0447\u043d\u044b\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f**: \u0414\u043e\u0431\u0430\u0432\u044c\u0442\u0435 \u043e\u0442\u043b\u0430\u0434\u043e\u0447\u043d\u044b\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u043f\u0435\u0440\u0435\u0434 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 `row`, \u0447\u0442\u043e\u0431\u044b \u0443\u0434\u043e\u0441\u0442\u043e\u0432\u0435\u0440\u0438\u0442\u044c\u0441\u044f, \u0447\u0442\u043e \u043e\u043d\u0430 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0430.\n\n3. **\u041f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u044b\u0439 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442 \u0446\u0438\u043a\u043b\u0430**: \u0423\u0431\u0435\u0434\u0438\u0442\u0435\u0441\u044c, \u0447\u0442\u043e \u0432\u0441\u0435 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438 \u0441 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 `row` \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u044f\u0442 \u0432\u043d\u0443\u0442\u0440\u0438 \u043a\u043e\u0440\u0440\u0435\u043b\u0438\u0440\u0443\u044e\u0449\u0435\u0433\u043e \u0446\u0438\u043a\u043b\u0430 (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0432\u043d\u0443\u0442\u0440\u0438 `for`).\n\n### \u041f\u043e\u043b\u043d\u044b\u0439 \u043f\u0440\u0438\u043c\u0435\u0440, \u0443\u0447\u0438\u0442\u044b\u0432\u0430\u044e\u0449\u0438\u0439 \u0438\u0441\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435\n\n\u0412\u043e\u0442 \u043a\u0430\u043a \u043c\u043e\u0436\u0435\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442 \u043a\u043e\u0434\u0430 \u0441 \u0443\u0447\u0435\u0442\u043e\u043c \u0432\u0441\u0435\u0445 \u043f\u0440\u0435\u0434\u043b\u043e\u0436\u0435\u043d\u043d\u044b\u0445 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439:\n\n```python\n@app.route('/get_table_data')\ndef get_table_data():\n    date = request.args.get('date')\n    filter_arma = request.args.get('filter_arma')\n\n    app.logger.debug(f\"\u041f\u043e\u043b\u0443\u0447\u0435\u043d \u0437\u0430\u043f\u0440\u043e\u0441: date={date}, filter_arma={filter_arma}\")\n\n    query = TableRow.query.filter_by(date=date)\n    if filter_arma == 'RPA':\n        query = query.filter_by(arma_type='RPA')\n\n    # \u041f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0432\u0441\u0435 \u0441\u0442\u0440\u043e\u043a\u0438, \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u044b\u0435 \u0441 \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u043e\u0439 \u0434\u0430\u0442\u043e\u0439\n    rows = query.all()\n    if not rows:\n        app.logger.debug(\"\u041d\u0435\u0442 \u0437\u0430\u043f\u0438\u0441\u0435\u0439 \u0434\u043b\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438.\")\n        return jsonify({\"data\": []})  # \u041c\u043e\u0436\u043d\u043e \u0432\u0435\u0440\u043d\u0443\u0442\u044c \u043f\u0443\u0441\u0442\u043e\u0439 \u043c\u0430\u0441\u0441\u0438\u0432 \u043a\u0430\u043a \u043e\u0442\u0432\u0435\u0442\n\n    app.logger.debug(f\"\u041d\u0430\u0439\u0434\u0435\u043d\u043e \u0437\u0430\u043f\u0438\u0441\u0435\u0439: {len(rows)}\")\n\n    # ... \u0432\u0430\u0448 \u043a\u043e\u0434 \u0434\u043b\u044f \u043f\u043e\u0434\u0441\u0447\u0435\u0442\u0430 \u0434\u0443\u0431\u043b\u0438\u043a\u0430\u0442\u043e\u0432 ...\n\n    # \u0423\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439 \u0434\u043b\u044f bad_recovery\n    for row in rows:\n        # \u0412\u0430\u0448 \u043a\u043e\u0434 \u0434\u043b\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0434\u0443\u0431\u043b\u0438\u043a\u0430\u0442\u043e\u0432 \u0438 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 row.bad_recovery\n        app.logger.debug(f\"Row ID: {row.id}, Number: {row.number}, Serial: {row.serial}, DL Number: {row.dl_number}\")\n\n    # \u0421\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u043c \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0438 \u043f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u0438\u043c \u0434\u0430\u043d\u043d\u044b\u0435 \u0434\u043b\u044f \u043e\u0442\u0432\u0435\u0442\u0430\n    db.session.commit()\n    data = [{'id': row.id, 'number': row.number, 'serial': row.serial, 'bad_recovery': row.bad_recovery} for row in rows]\n\n    return jsonify({\"data\": data})\n```\n\n### \u0417\u0430\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435\n\n\u041f\u043e\u0441\u043b\u0435 \u0432\u043d\u0435\u0441\u0435\u043d\u0438\u044f \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439, \u0432\u043a\u043b\u044e\u0447\u0430\u044f \u043f\u0435\u0440\u0435\u0445\u043e\u0434 \u043d\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 `datetime.now(datetime.timezone.utc)`, \u0432\u0430\u0448\u0430 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0430 \u0434\u043e\u043b\u0436\u043d\u0430 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0431\u0435\u0437 \u043f\u0440\u0435\u0434\u0443\u043f\u0440\u0435\u0436\u0434\u0435\u043d\u0438\u0439 \u0438 \u043e\u0448\u0438\u0431\u043e\u043a. \u0423\u0431\u0435\u0434\u0438\u0442\u0435\u0441\u044c \u0442\u0430\u043a\u0436\u0435, \u0447\u0442\u043e \u0434\u0430\u043d\u043d\u044b\u0435 \u0432 \u0432\u0430\u0448\u0435\u043c \u0437\u0430\u043f\u0440\u043e\u0441\u0435 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u044e\u0442\u0441\u044f \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e \u0434\u043b\u044f \u043f\u0440\u0435\u0434\u043e\u0442\u0432\u0440\u0430\u0449\u0435\u043d\u0438\u044f \u0432\u043e\u0437\u043d\u0438\u043a\u043d\u043e\u0432\u0435\u043d\u0438\u044f \u0441\u0438\u0442\u0443\u0430\u0446\u0438\u0439 \u0441 `UnboundLocalError`.","behavior":"degenerate_repetition","conversation_hash":"6bc71a2034fca9ff9176bc3c9a73f460","conversation_redacted":false,"conversation_toxic":false,"country":"Russia","empty_output":false,"evidence_codes":[],"label":"absent","label_present":false,"label_qualified":false,"label_source":"Final dense release","language":"Russian","model":"gpt-4o-mini-2024-07-18","n_chars":7298,"n_turns_in_conversation":7,"n_words":644,"source_row_offset":744,"source_shard":"turns-00054.parquet","timestamp":"Fri, 29 Nov 2024 10:07:41 GMT","turn_id":"8818bd23cd4b75509a3f0890","turn_index":3,"user_text":"C:\\Users\\Lenovo\\Desktop\\myprojectV11\\main.py:971: DeprecationWarning: datetime.datetime.utcnow() is deprecated and scheduled for removal in a future version. Use timezone-aware objects to represent datetimes in UTC: datetime.datetime.now(datetime.UTC).\n  current_time = datetime.utcnow()\nC:\\Users\\Lenovo\\Desktop\\myprojectV11\\main.py:163: DeprecationWarning: datetime.datetime.utcnow() is deprecated and scheduled for removal in a future version. Use timezone-aware objects to represent datetimes in UTC: datetime.datetime.now(datetime.UTC).\n  now = datetime.utcnow()\nTraceback (most recent call last):\n  File \"c:\\Program Files\\Python312\\Lib\\site-packages\\flask\\app.py\", line 1536, in __call__\n    return self.wsgi_app(environ, start_response)\n           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n  File \"c:\\Program Files\\Python312\\Lib\\site-packages\\flask\\app.py\", line 1514, in wsgi_app\n    response = self.handle_exception(e)\n               ^^^^^^^^^^^^^^^^^^^^^^^^\n  File \"c:\\Program Files\\Python312\\Lib\\site-packages\\flask\\app.py\", line 1511, in wsgi_app\n    response = self.full_dispatch_request()\n               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n  File \"c:\\Program Files\\Python312\\Lib\\site-packages\\flask\\app.py\", line 919, in full_dispatch_request\n    rv = self.handle_user_exception(e)\n         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n  File \"c:\\Program Files\\Python312\\Lib\\site-packages\\flask\\app.py\", line 917, in full_dispatch_request\n    rv = self.dispatch_request()\n         ^^^^^^^^^^^^^^^^^^^^^^^\n  File \"c:\\Program Files\\Python312\\Lib\\site-packages\\flask\\app.py\", line 902, in dispatch_request\n    return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args)  # type: ignore[no-any-return]\n           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n  File \"C:\\Users\\Lenovo\\Desktop\\myprojectV11\\main.py\", line 389, in get_table_data\n    app.logger.debug(f\"Row ID: {row.id}, Number: {row.number}, Serial: {row.serial}, DL Number: {row.dl_number}\")\n                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\nUnboundLocalError: cannot access local variable 'row' where it is not associated with a value\nTraceback (most recent call last):\n  File \"c:\\Program Files\\Python312\\Lib\\site-packages\\flask\\app.py\", line 1536, in __call__\n    return self.wsgi_app(environ, start_response)\n           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n  File \"c:\\Program Files\\Python312\\Lib\\site-packages\\flask\\app.py\", line 1514, in wsgi_app\n    response = self.handle_exception(e)\n               ^^^^^^^^^^^^^^^^^^^^^^^^\n  File \"c:\\Program Files\\Python312\\Lib\\site-packages\\flask\\app.py\", line 1511, in wsgi_app\n    response = self.full_dispatch_request()\n               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n  File \"c:\\Program Files\\Python312\\Lib\\site-packages\\flask\\app.py\", line 919, in full_dispatch_request\n    rv = self.handle_user_exception(e)\n         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n  File \"c:\\Program Files\\Python312\\Lib\\site-packages\\flask\\app.py\", line 917, in full_dispatch_request\n    rv = self.dispatch_request()\n         ^^^^^^^^^^^^^^^^^^^^^^^\n  File \"c:\\Program Files\\Python312\\Lib\\site-packages\\flask\\app.py\", line 902, in dispatch_request\n    return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args)  # type: ignore[no-any-return]\n           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n  File \"C:\\Users\\Lenovo\\Desktop\\myprojectV11\\main.py\", line 389, in get_table_data\n    app.logger.debug(f\"Row ID: {row.id}, Number: {row.number}, Serial: {row.serial}, DL Number: {row.dl_number}\")\n                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\nUnboundLocalError: cannot access local variable 'row' where it is not associated with a value"},{"assistant_initiates":false,"asst_text":"\u0412\u0430\u0448\u0438 \u043e\u0448\u0438\u0431\u043a\u0438 \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u044e\u0442 \u043d\u0430 \u0434\u0432\u0435 \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0435 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b \u0432 \u043a\u043e\u0434\u0435:\n\n1. **DeprecationWarning** (\u043f\u0440\u0435\u0434\u0443\u043f\u0440\u0435\u0436\u0434\u0435\u043d\u0438\u0435 \u043e \u0443\u0441\u0442\u0430\u0440\u0435\u0432\u0430\u043d\u0438\u0438): \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 `datetime.utcnow()` \u0441\u0447\u0438\u0442\u0430\u0435\u0442\u0441\u044f \u0443\u0441\u0442\u0430\u0440\u0435\u0432\u0448\u0438\u043c, \u0438, \u043a\u0430\u043a \u0443\u043f\u043e\u043c\u0438\u043d\u0430\u043b\u043e\u0441\u044c \u0440\u0430\u043d\u0435\u0435, \u0441\u043b\u0435\u0434\u0443\u0435\u0442 \u0437\u0430\u043c\u0435\u043d\u0438\u0442\u044c \u0435\u0433\u043e \u043d\u0430 `datetime.now(datetime.timezone.utc)`.\n\n2. **UnboundLocalError**: \u043e\u0448\u0438\u0431\u043a\u0430 \"cannot access local variable 'row' where it is not associated with a value\" \u0432\u043e\u0437\u043d\u0438\u043a\u0430\u0435\u0442 \u0438\u0437-\u0437\u0430 \u0442\u043e\u0433\u043e, \u0447\u0442\u043e \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0430\u044f `row` \u043f\u044b\u0442\u0430\u0435\u0442\u0441\u044f \u0431\u044b\u0442\u044c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0430 \u0432\u043d\u0435 \u043e\u0431\u043b\u0430\u0441\u0442\u0438 \u0432\u0438\u0434\u0438\u043c\u043e\u0441\u0442\u0438, \u0433\u0434\u0435 \u043e\u043d\u0430 \u0431\u044b\u043b\u0430 \u043e\u0431\u044a\u044f\u0432\u043b\u0435\u043d\u0430 \u0438\u043b\u0438 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u0430.\n\n### \u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0438\u0441\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0439\n\n#### 1. \u0418\u0437\u043c\u0435\u043d\u0438\u0442\u0435 \u0432\u0441\u0435 \u0432\u044b\u0437\u043e\u0432\u044b `datetime.utcnow()`\n\n\u0417\u0430\u043c\u0435\u043d\u0438\u0442\u0435 \u0432\u0441\u0435 \u0432\u044b\u0437\u043e\u0432\u044b `datetime.utcnow()` \u043d\u0430 `datetime.now(datetime.timezone.utc)`. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440:\n\n```python\nfrom datetime import datetime\n\n# \u041f\u0440\u0438\u043c\u0435\u0440 \u0437\u0430\u043c\u0435\u043d\u044b\nnow = datetime.now(datetime.timezone.utc)\ncurrent_time = datetime.now(datetime.timezone.utc)\n```\n\n\u0423\u0431\u0435\u0434\u0438\u0442\u0435\u0441\u044c, \u0447\u0442\u043e \u0438\u0441\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0432\u043d\u0435\u0441\u0435\u043d\u044b \u0432\u043e \u0432\u0441\u0435 \u043c\u0435\u0441\u0442\u0430 \u0432\u0430\u0448\u0435\u0433\u043e \u043a\u043e\u0434\u0430, \u0433\u0434\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f `datetime.utcnow()`.\n\n#### 2. \u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043d\u0430 \u043d\u0430\u043b\u0438\u0447\u0438\u0435 \u0437\u0430\u043f\u0438\u0441\u0435\u0439\n\n\u0427\u0442\u043e\u0431\u044b \u0438\u0437\u0431\u0435\u0436\u0430\u0442\u044c `UnboundLocalError`, \u043f\u0435\u0440\u0435\u0434 \u0442\u0435\u043c \u043a\u0430\u043a \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0443\u044e `row`, \u0443\u0431\u0435\u0434\u0438\u0442\u0435\u0441\u044c, \u0447\u0442\u043e \u0432\u044b \u0437\u0430\u0440\u0430\u043d\u0435\u0435 \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u043b\u0438, \u0447\u0442\u043e \u0443 \u0432\u0430\u0441 \u0435\u0441\u0442\u044c \u0437\u0430\u043f\u0438\u0441\u0438 \u0434\u043b\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438. \u0421\u043d\u0430\u0447\u0430\u043b\u0430 \u0443\u0431\u0435\u0434\u0438\u0442\u0435\u0441\u044c, \u0447\u0442\u043e \u0432\u044b \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442\u0435 \u0434\u0430\u043d\u043d\u044b\u0435:\n\n```python\n@app.route('/get_table_data')\ndef get_table_data():\n    date = request.args.get('date')\n    filter_arma = request.args.get('filter_arma')\n\n    app.logger.debug(f\"\u041f\u043e\u043b\u0443\u0447\u0435\u043d \u0437\u0430\u043f\u0440\u043e\u0441: date={date}, filter_arma={filter_arma}\")\n\n    query = TableRow.query.filter_by(date=date)\n    if filter_arma == 'RPA':\n        query = query.filter_by(arma_type='RPA')\n\n    # \u041f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0432\u0441\u0435 \u0441\u0442\u0440\u043e\u043a\u0438, \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u044b\u0435 \u0441 \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u043e\u0439 \u0434\u0430\u0442\u043e\u0439\n    rows = query.all()\n    if not rows:\n        app.logger.debug(\"\u041d\u0435\u0442 \u0437\u0430\u043f\u0438\u0441\u0435\u0439 \u0434\u043b\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438.\")\n        return jsonify({\"data\": []})  # \u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c \u043f\u0443\u0441\u0442\u043e\u0439 \u043c\u0430\u0441\u0441\u0438\u0432, \u0435\u0441\u043b\u0438 \u043d\u0435\u0442 \u0437\u0430\u043f\u0438\u0441\u0435\u0439\n\n    app.logger.debug(f\"\u041d\u0430\u0439\u0434\u0435\u043d\u043e \u0437\u0430\u043f\u0438\u0441\u0435\u0439: {len(rows)}\")\n\n    # \u0412\u0430\u0448 \u043a\u043e\u0434 \u0434\u043b\u044f \u043f\u043e\u0434\u0441\u0447\u0435\u0442\u0430 \u0434\u0443\u0431\u043b\u0438\u043a\u0430\u0442\u043e\u0432\n    for row in rows:\n        # \u0423\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0434\u043b\u044f bad_recovery \u0438 \u0434\u0440\u0443\u0433\u0438\u0435 \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u044f\n        app.logger.debug(f\"Row ID: {row.id}, Number: {row.number}, Serial: {row.serial}, DL Number: {row.dl_number}\")\n\n    # \u0421\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u043c \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0438 \u043f\u043e\u0434\u0433\u043e\u0442\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c \u0434\u0430\u043d\u043d\u044b\u0435 \u0434\u043b\u044f \u043e\u0442\u0432\u0435\u0442\u0430\n    db.session.commit()\n    data = [{'id': row.id, 'number': row.number, 'serial': row.serial, 'bad_recovery': row.bad_recovery} for row in rows]\n\n    return jsonify({\"data\": data})\n```\n\n### \u041e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u043d\u0430 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0435:\n\n- **\u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043d\u0430 \u043f\u0443\u0441\u0442\u043e\u0439 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442**: \u0415\u0441\u043b\u0438 `rows` \u043f\u0443\u0441\u0442, \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u044f\u0435\u043c \u043e\u0431 \u044d\u0442\u043e\u043c \u0432 \u043b\u043e\u0433\u0430\u0445 \u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c \u043f\u0443\u0441\u0442\u043e\u0439 \u043e\u0442\u0432\u0435\u0442. \u042d\u0442\u043e \u043f\u0440\u0435\u0434\u043e\u0442\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0443\u044e \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u0438 \u043e\u0431\u0440\u0430\u0449\u0435\u043d\u0438\u0435 \u043a \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 `row`, \u0435\u0441\u043b\u0438 \u0434\u0430\u043d\u043d\u044b\u0445 \u043d\u0435\u0442.\n  \n- **\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 `row` \u0432 \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e\u043c \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0435**: \u0423\u0431\u0435\u0434\u0438\u0442\u0435\u0441\u044c, \u0447\u0442\u043e \u043a\u043e\u0434, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0443\u044e `row`, \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0432\u043d\u0443\u0442\u0440\u0438 \u0446\u0438\u043a\u043b\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0435\u0435 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0435\u0442.\n\n### \u0418\u0442\u043e\u0433\n\n\u041f\u043e\u0441\u043b\u0435 \u0432\u043d\u0435\u0441\u0435\u043d\u0438\u044f \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u044b\u0445 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439 \u0432\u0430\u0448\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043d\u0435 \u0434\u043e\u043b\u0436\u043d\u043e \u0431\u043e\u043b\u044c\u0448\u0435 \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c `DeprecationWarning` \u0438 `UnboundLocalError`. \u0423\u0431\u0435\u0434\u0438\u0442\u0435\u0441\u044c, \u0447\u0442\u043e \u0432\u044b \u043f\u0440\u043e\u0432\u0435\u043b\u0438 \u043f\u043e\u043b\u043d\u044b\u0435 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u043a\u043e\u0434\u0430 \u0438 \u043f\u0440\u043e\u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043b\u0438 \u0435\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0434\u0438\u0442\u044c, \u0447\u0442\u043e \u0432\u0441\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e.","behavior":"degenerate_repetition","conversation_hash":"6bc71a2034fca9ff9176bc3c9a73f460","conversation_redacted":false,"conversation_toxic":false,"country":"Russia","empty_output":false,"evidence_codes":[],"label":"absent","label_present":false,"label_qualified":false,"label_source":"Final dense release","language":"Russian","model":"gpt-4o-mini-2024-07-18","n_chars":6836,"n_turns_in_conversation":7,"n_words":592,"source_row_offset":745,"source_shard":"turns-00054.parquet","timestamp":"Fri, 29 Nov 2024 10:07:41 GMT","turn_id":"dc7fd9d1c7156c54abcb033f","turn_index":4,"user_text":"C:\\Users\\Lenovo\\Desktop\\myprojectV11\\main.py:163: DeprecationWarning: datetime.datetime.utcnow() is deprecated and scheduled for removal in a future version. Use timezone-aware objects to represent datetimes in UTC: datetime.datetime.now(datetime.UTC).\n  now = datetime.utcnow()\nC:\\Users\\Lenovo\\Desktop\\myprojectV11\\main.py:975: DeprecationWarning: datetime.datetime.utcnow() is deprecated and scheduled for removal in a future version. Use timezone-aware objects to represent datetimes in UTC: datetime.datetime.now(datetime.UTC).\n  current_time = datetime.utcnow()\nTraceback (most recent call last):\n  File \"c:\\Program Files\\Python312\\Lib\\site-packages\\flask\\app.py\", line 1536, in __call__\n    return self.wsgi_app(environ, start_response)\n           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n  File \"c:\\Program Files\\Python312\\Lib\\site-packages\\flask\\app.py\", line 1514, in wsgi_app\n    response = self.handle_exception(e)\n               ^^^^^^^^^^^^^^^^^^^^^^^^\n  File \"c:\\Program Files\\Python312\\Lib\\site-packages\\flask\\app.py\", line 1511, in wsgi_app\n    response = self.full_dispatch_request()\n               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n  File \"c:\\Program Files\\Python312\\Lib\\site-packages\\flask\\app.py\", line 919, in full_dispatch_request\n    rv = self.handle_user_exception(e)\n         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n  File \"c:\\Program Files\\Python312\\Lib\\site-packages\\flask\\app.py\", line 917, in full_dispatch_request\n    rv = self.dispatch_request()\n         ^^^^^^^^^^^^^^^^^^^^^^^\n  File \"c:\\Program Files\\Python312\\Lib\\site-packages\\flask\\app.py\", line 902, in dispatch_request\n    return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args)  # type: ignore[no-any-return]\n           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n  File \"C:\\Users\\Lenovo\\Desktop\\myprojectV11\\main.py\", line 389, in get_table_data\n    app.logger.debug(f\"Row ID: {row.id}, Number: {row.number}, Serial: {row.serial}, DL Number: {row.dl_number}\")\n                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\nUnboundLocalError: cannot access local variable 'row' where it is not associated with a value\nTraceback (most recent call last):\n  File \"c:\\Program Files\\Python312\\Lib\\site-packages\\flask\\app.py\", line 1536, in __call__\n    return self.wsgi_app(environ, start_response)\n           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n  File \"c:\\Program Files\\Python312\\Lib\\site-packages\\flask\\app.py\", line 1514, in wsgi_app\n    response = self.handle_exception(e)\n               ^^^^^^^^^^^^^^^^^^^^^^^^\n  File \"c:\\Program Files\\Python312\\Lib\\site-packages\\flask\\app.py\", line 1511, in wsgi_app\n    response = self.full_dispatch_request()\n               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n  File \"c:\\Program Files\\Python312\\Lib\\site-packages\\flask\\app.py\", line 919, in full_dispatch_request\n    rv = self.handle_user_exception(e)\n         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n  File \"c:\\Program Files\\Python312\\Lib\\site-packages\\flask\\app.py\", line 917, in full_dispatch_request\n    rv = self.dispatch_request()\n         ^^^^^^^^^^^^^^^^^^^^^^^\n  File \"c:\\Program Files\\Python312\\Lib\\site-packages\\flask\\app.py\", line 902, in dispatch_request\n    return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args)  # type: ignore[no-any-return]\n           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n  File \"C:\\Users\\Lenovo\\Desktop\\myprojectV11\\main.py\", line 389, in get_table_data\n    app.logger.debug(f\"Row ID: {row.id}, Number: {row.number}, Serial: {row.serial}, DL Number: {row.dl_number}\")\n                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\nUnboundLocalError: cannot access local variable 'row' where it is not associated with a value"},{"assistant_initiates":false,"asst_text":"\u0415\u0441\u043b\u0438 \u0432\u0430\u0448\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442 `\u041d\u0430\u0439\u0434\u0435\u043d\u043e \u0437\u0430\u043f\u0438\u0441\u0435\u0439: 0` \u0434\u043b\u044f \u0432\u0441\u0435\u0445 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432, \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u0445 \u043f\u0440\u0438\u0447\u0438\u043d. \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c, \u043a\u0430\u043a \u0434\u0438\u0430\u0433\u043d\u043e\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0438 \u0440\u0435\u0448\u0438\u0442\u044c \u044d\u0442\u0443 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0443.\n\n### \u0412\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u0435 \u043f\u0440\u0438\u0447\u0438\u043d\u044b \u0438 \u0440\u0435\u0448\u0435\u043d\u0438\u044f\n\n1. **\u041d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u044b\u0439 \u0432\u0432\u043e\u0434 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432**:\n   - \u0423\u0431\u0435\u0434\u0438\u0442\u0435\u0441\u044c, \u0447\u0442\u043e `date` \u0438 `filter_arma` \u043f\u0435\u0440\u0435\u0434\u0430\u044e\u0442\u0441\u044f \u0432 \u0437\u0430\u043f\u0440\u043e\u0441\u0435 \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0435\u0441\u043b\u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 `date` \u043d\u0435 \u0441\u043e\u0432\u043f\u0430\u0434\u0430\u0435\u0442 \u0441 \u0444\u043e\u0440\u043c\u0430\u0442\u043e\u043c, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0432 \u0431\u0430\u0437\u0435 \u0434\u0430\u043d\u043d\u044b\u0445, \u0437\u0430\u043f\u0440\u043e\u0441 \u043d\u0435 \u0432\u0435\u0440\u043d\u0451\u0442 \u0437\u0430\u043f\u0438\u0441\u0435\u0439. \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435 \u0444\u043e\u0440\u043c\u0430\u0442 \u0434\u0430\u0442\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u0444\u043e\u0440\u043c\u0430\u0442\u0443 \u0432 \u0431\u0430\u0437\u0435, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440: `YYYY-MM-DD`.\n\n2. **\u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u0432 \u0431\u0430\u0437\u0435 \u0434\u0430\u043d\u043d\u044b\u0445**:\n   - \u0423\u0431\u0435\u0434\u0438\u0442\u0435\u0441\u044c, \u0447\u0442\u043e \u0437\u0430\u043f\u0438\u0441\u0438 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0435\u0441\u0442\u044c \u0432 \u0431\u0430\u0437\u0435 \u0434\u0430\u043d\u043d\u044b\u0445 \u0434\u043b\u044f \u0437\u0430\u0434\u0430\u043d\u043d\u043e\u0439 \u0434\u0430\u0442\u044b. \u0412\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0432\u044b\u0431\u043e\u0440\u043a\u0443 \u0432\u0441\u0435\u0445 \u0437\u0430\u043f\u0438\u0441\u0435\u0439 \u0438\u0437 \u0442\u0430\u0431\u043b\u0438\u0446\u044b `TableRow` \u0438 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c, \u0435\u0441\u0442\u044c \u043b\u0438 \u043e\u043d\u0438.\n     ```python\n     rows = TableRow.query.all()\n     for row in rows:\n         print(row)\n     ```\n\n3. **\u041f\u0440\u043e\u0431\u043b\u0435\u043c\u044b \u0441 \u0444\u0438\u043b\u044c\u0442\u0440\u0430\u0446\u0438\u0435\u0439`filter_arma`**:\n   - \u0423\u0431\u0435\u0434\u0438\u0442\u0435\u0441\u044c, \u0447\u0442\u043e \u043a\u0440\u0438\u0442\u0435\u0440\u0438\u0439 \u0444\u0438\u043b\u044c\u0442\u0440\u0430\u0446\u0438\u0438 `arma_type` \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u043c \u0437\u0430\u043f\u0438\u0441\u044f\u043c. \u042d\u0442\u043e \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0437\u0430\u043f\u0440\u043e\u0441\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0438\u0437\u0432\u043b\u0435\u043a\u0430\u0435\u0442 \u0432\u0441\u0435 \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u044b\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f `arma_type`.\n     ```python\n     unique_arma_types = db.session.query(TableRow.arma_type).distinct().all()\n     print(unique_arma_types)\n     ```\n\n4. **\u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0431\u0430\u0437\u044b \u0434\u0430\u043d\u043d\u044b\u0445**:\n   - \u0415\u0441\u043b\u0438 \u0432\u044b \u0442\u043e\u043b\u044c\u043a\u043e \u0447\u0442\u043e \u0441\u043e\u0437\u0434\u0430\u043b\u0438 \u0431\u0430\u0437\u0443 \u0434\u0430\u043d\u043d\u044b\u0445, \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e, \u0434\u0430\u043d\u043d\u044b\u0435 \u043d\u0435 \u0431\u044b\u043b\u0438 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u044b. \u0423\u0431\u0435\u0434\u0438\u0442\u0435\u0441\u044c, \u0447\u0442\u043e \u0443 \u0432\u0430\u0441 \u0435\u0441\u0442\u044c \u0437\u0430\u043f\u0438\u0441\u0438 \u0432 \u0432\u0430\u0448\u0435\u0439 \u0431\u0430\u0437\u0435.\n   - \u041f\u0440\u043e\u0432\u0435\u0440\u044c\u0442\u0435, \u0433\u0434\u0435 \u0432\u044b \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0435 \u0432\u0441\u0442\u0430\u0432\u043a\u0443 \u0434\u0430\u043d\u043d\u044b\u0445 (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0432 `update_table`, `update_serial_arma`, \u0438 \u0434\u0440\u0443\u0433\u0438\u0445 \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u0430\u0445). \u0412\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u044b \u0434\u043b\u044f \u0432\u0441\u0442\u0430\u0432\u043a\u0438 \u0442\u0435\u0441\u0442\u043e\u0432\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445 \u0432 \u0431\u0430\u0437\u0443 \u0434\u0430\u043d\u043d\u044b\u0445, \u0447\u0442\u043e\u0431\u044b \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u0441\u0432\u043e\u044e \u043b\u043e\u0433\u0438\u043a\u0443:\n\n   ```python\n   # \u041f\u0440\u0438\u043c\u0435\u0440 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0442\u0435\u0441\u0442\u043e\u0432\u043e\u0439 \u0437\u0430\u043f\u0438\u0441\u0438 (\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e, \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u043c \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u0435)\n   @app.route('/add_test_record', methods=['POST'])\n   def add_test_record():\n       new_row = TableRow(\n           date=\"2023-10-01\",   # \u0423\u0431\u0435\u0434\u0438\u0442\u0435\u0441\u044c, \u0447\u0442\u043e \u044d\u0442\u0430 \u0434\u0430\u0442\u0430 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u0432\u0430\u0448\u0435\u043c\u0443 \u0444\u043e\u0440\u043c\u0430\u0442\u0443\n           number=\"12345\",\n           serial=\"A1B2C3\",\n           dl_number=\"DL123456\",\n           worker_name=\"Test Worker\",\n           row_number=\"1\",\n           pack_time=\"2023-10-01 10:00:00\",\n           arma_type=\"RPA\",\n           dateshipment=\"2023-10-02\",\n           aktshipment=\"\u0410\u043a\u0442 1\",\n           bad_recovery=False\n       )\n       db.session.add(new_row)\n       db.session.commit()\n       return jsonify({\"status\": \"success\", \"message\": \"Test record added\"})\n   ```\n\n5. **\u041e\u0442\u043b\u0430\u0434\u043a\u0430 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432**:\n   - \u0414\u043e\u0431\u0430\u0432\u044c\u0442\u0435 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u0436\u0443\u0440\u043d\u0430\u043b\u044b (\u043b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435) \u043f\u0435\u0440\u0435\u0434 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435\u043c \u0432\u0430\u0448\u0435\u0433\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u0430, \u0447\u0442\u043e\u0431\u044b \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c, \u043a\u0430\u043a\u0438\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0431\u044b\u043b\u0438 \u043f\u0435\u0440\u0435\u0434\u0430\u043d\u044b \u0432 \u0444\u0438\u043b\u044c\u0442\u0440\u044b:\n   ```python\n   app.logger.debug(f\"\u0424\u0438\u043b\u044c\u0442\u0440\u0430\u0446\u0438\u044f \u043f\u043e \u0434\u0430\u0442\u0435: {date}, \u0444\u0438\u043b\u044c\u0442\u0440 ARMA: {filter_arma}\")\n   ```\n\n6. **\u041f\u0440\u043e\u0431\u043b\u0435\u043c\u044b \u0441 \u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u044f\u043c\u0438**:\n   - \u0415\u0441\u043b\u0438 \u0432\u0430\u0448\u0430 \u0431\u0430\u0437\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u0438 \u0438 \u0432\u044b \u043e\u0436\u0438\u0434\u0430\u0435\u0442\u0435 \u0443\u0432\u0438\u0434\u0435\u0442\u044c \u0437\u0430\u043f\u0438\u0441\u0438, \u0443\u0431\u0435\u0434\u0438\u0442\u0435\u0441\u044c, \u0447\u0442\u043e \u0432\u0441\u0435 \u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u0438 \u0431\u044b\u043b\u0438 \u0437\u0430\u0444\u0438\u043a\u0441\u0438\u0440\u043e\u0432\u0430\u043d\u044b (`committed`). \u041f\u0440\u043e\u0432\u0435\u0440\u044c\u0442\u0435, \u0447\u0442\u043e \u0443 \u0432\u0430\u0441 \u043d\u0435\u0442 \u043d\u0435\u0437\u0430\u0432\u0435\u0440\u0448\u0451\u043d\u043d\u044b\u0445 \u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u0439 \u0432 \u043a\u043e\u0434\u0435.\n\n### \u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0432\u0441\u0435\u0439 \u043b\u043e\u0433\u0438\u043a\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u0430\n\n\u041f\u0440\u0438\u043c\u0435\u0440 \u0444\u0438\u043d\u0430\u043b\u044c\u043d\u043e\u0439 \u043b\u043e\u0433\u0438\u043a\u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0432\u0441\u0435\u0445 \u0443\u043f\u043e\u043c\u044f\u043d\u0443\u0442\u044b\u0445 \u043c\u043e\u043c\u0435\u043d\u0442\u043e\u0432:\n\n```python\n@app.route('/get_table_data')\ndef get_table_data():\n    date = request.args.get('date')\n    filter_arma = request.args.get('filter_arma')\n\n    app.logger.debug(f\"\u041f\u043e\u043b\u0443\u0447\u0435\u043d \u0437\u0430\u043f\u0440\u043e\u0441: date={date}, filter_arma={filter_arma}\")\n\n    # \u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c \u043d\u0430 \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432\n    if not date:\n        return jsonify({\"status\": \"error\", \"message\": \"\u041d\u0435 \u0443\u043a\u0430\u0437\u0430\u043d\u0430 \u0434\u0430\u0442\u0430\"}), 400\n\n    query = TableRow.query.filter_by(date=date)\n    \n    if filter_arma == 'RPA':\n        query = query.filter_by(arma_type='RPA')\n\n    rows = query.all()\n    app.logger.debug(f\"\u041d\u0430\u0439\u0434\u0435\u043d\u043e \u0437\u0430\u043f\u0438\u0441\u0435\u0439: {len(rows)}\")\n\n    if not rows:\n        app.logger.debug(\"\u041d\u0435\u0442 \u0437\u0430\u043f\u0438\u0441\u0435\u0439 \u0434\u043b\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438.\")\n        return jsonify({\"data\": []})\n\n    # \u0414\u0430\u043b\u044c\u0448\u0435 \u0432\u0430\u0448\u0430 \u043b\u043e\u0433\u0438\u043a\u0430 \u043f\u043e\u0434\u0441\u0447\u0435\u0442\u0430 \u0434\u0443\u0431\u043b\u0438\u043a\u0430\u0442\u043e\u0432 \u0438 \u0442.\u0434.\n    ...\n```\n\n### \u0417\u0430\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435\n\n\u0415\u0441\u043b\u0438 \u0432\u044b \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u043b\u0438 \u0432\u0441\u0435 \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u044b\u0435 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f, \u043d\u043e \u0432\u0441\u0435 \u0435\u0449\u0435 \u0432\u0438\u0434\u0438\u0442\u0435, \u0447\u0442\u043e \u0437\u0430\u043f\u0438\u0441\u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u044e\u0442\u0441\u044f \u043a\u0430\u043a 0, \u043f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430, \u043f\u0440\u043e\u0432\u0435\u0440\u044c\u0442\u0435 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 \u0432\u0430\u0448\u0435\u0439 \u0431\u0430\u0437\u044b \u0434\u0430\u043d\u043d\u044b\u0445 \u0438 \u0445\u0440\u0430\u043d\u0438\u043c\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435. \u042d\u0442\u043e \u043f\u043e\u043c\u043e\u0436\u0435\u0442 \u0432\u0430\u043c \u0434\u0438\u0430\u0433\u043d\u043e\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0438 \u043d\u0430\u0439\u0442\u0438, \u0433\u0434\u0435 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430.","behavior":"degenerate_repetition","conversation_hash":"6bc71a2034fca9ff9176bc3c9a73f460","conversation_redacted":false,"conversation_toxic":false,"country":"Russia","empty_output":false,"evidence_codes":[],"label":"absent","label_present":false,"label_qualified":false,"label_source":"Final dense release","language":"Russian","model":"gpt-4o-mini-2024-07-18","n_chars":4002,"n_turns_in_conversation":7,"n_words":432,"source_row_offset":746,"source_shard":"turns-00054.parquet","timestamp":"Fri, 29 Nov 2024 10:07:41 GMT","turn_id":"53c0fb82301462474eee23d1","turn_index":5,"user_text":"\u041d\u0430\u0439\u0434\u0435\u043d\u043e \u0437\u0430\u043f\u0438\u0441\u0435\u0439: 0\n\u041d\u0430\u0439\u0434\u0435\u043d\u043e \u0437\u0430\u043f\u0438\u0441\u0435\u0439: 0\n\u041d\u0430\u0439\u0434\u0435\u043d\u043e \u0437\u0430\u043f\u0438\u0441\u0435\u0439: 0"},{"assistant_initiates":false,"asst_text":"\u0427\u0442\u043e\u0431\u044b \u043e\u0442\u043e\u0431\u0440\u0430\u0437\u0438\u0442\u044c \u043e\u0431\u0449\u0435\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0437\u0430\u043f\u0438\u0441\u0435\u0439 \u0442\u0438\u043f\u0430 'RPA' \u0432 \u0432\u0430\u0448\u0435\u043c HTML, \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u043a\u0430\u043a \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u044b\u0439, \u0442\u0430\u043a \u0438 \u043a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u0438\u0439 \u043a\u043e\u0434. \u0412 \u0447\u0430\u0441\u0442\u043d\u043e\u0441\u0442\u0438, \u043c\u044b \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u043d\u043e\u0432\u044b\u0439 \u043c\u0430\u0440\u0448\u0440\u0443\u0442 \u043d\u0430 \u0441\u0442\u043e\u0440\u043e\u043d\u0435 Flask, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0442\u044c \u043e\u0431\u0449\u0435\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0437\u0430\u043f\u0438\u0441\u0435\u0439 \u0442\u0438\u043f\u0430 'RPA', \u0430 \u0437\u0430\u0442\u0435\u043c \u043e\u0431\u043d\u043e\u0432\u0438\u043c JavaScript \u0434\u043b\u044f \u0432\u044b\u0437\u043e\u0432\u0430 \u044d\u0442\u043e\u0433\u043e \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u0430 \u0438 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0432 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0435\u043c \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0435 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430.\n\n### \u0428\u0430\u0433 1: \u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043c\u0430\u0440\u0448\u0440\u0443\u0442 \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0435\n\n\u0414\u043e\u0431\u0430\u0432\u0438\u043c \u043d\u043e\u0432\u044b\u0439 \u043c\u0430\u0440\u0448\u0440\u0443\u0442 \u0432 \u0432\u0430\u0448 Flask-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0442\u044c \u043e\u0431\u0449\u0435\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0437\u0430\u043f\u0438\u0441\u0435\u0439 \u0442\u0438\u043f\u0430 'RPA':\n\n```python\n@app.route('/get_total_rpa_count', methods=['GET'])\ndef get_total_rpa_count():\n    total_rpa_count = TableRow.query.filter_by(arma_type='RPA').count()\n    return jsonify({\"status\": \"success\", \"total_rpa\": total_rpa_count})\n```\n\n### \u0428\u0430\u0433 2: \u041e\u0431\u043d\u043e\u0432\u0438\u0442\u044c JavaScript\n\n\u0422\u0435\u043f\u0435\u0440\u044c \u043c\u044b \u0434\u043e\u0431\u0430\u0432\u0438\u043c JavaScript-\u043a\u043e\u0434, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u043e\u0431\u0449\u0435\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0437\u0430\u043f\u0438\u0441\u0435\u0439 \u0442\u0438\u043f\u0430 'RPA' \u043f\u043e\u0441\u043b\u0435 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b \u0438 \u043e\u0431\u043d\u043e\u0432\u0438\u0442\u044c \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0439 HTML \u044d\u043b\u0435\u043c\u0435\u043d\u0442.\n\n```javascript\nfunction loadTotalRPA() {\n    $.ajax({\n        url: '/get_total_rpa_count',\n        type: 'GET',\n        success: function(response) {\n            if (response.status === 'success') {\n                $('#total-rpa-records').text(response.total_rpa);\n                $('#rpa-total-container').show(); // \u041f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\n            } else {\n                console.error('\u041e\u0448\u0438\u0431\u043a\u0430 \u043f\u0440\u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0438 \u043e\u0431\u0449\u0435\u0433\u043e \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0430 RPA:', response.message);\n            }\n        },\n        error: function(xhr, status, error) {\n            console.error('\u041e\u0448\u0438\u0431\u043a\u0430 \u043f\u0440\u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u043e\u0431\u0449\u0435\u0433\u043e \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0430 RPA:', error);\n        }\n    });\n}\n\n// \u0412\u044b\u0437\u043e\u0432 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u043f\u0440\u0438 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0435 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b\n$(document).ready(function() {\n    loadTotalRPA();\n});\n```\n\n### \u0428\u0430\u0433 3: HTML \u0420\u0430\u0437\u043c\u0435\u0442\u043a\u0430\n\n\u0423\u0431\u0435\u0434\u0438\u0442\u0435\u0441\u044c, \u0447\u0442\u043e \u0443 \u0432\u0430\u0441 \u0435\u0441\u0442\u044c \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0430\u044f \u0441\u0435\u043a\u0446\u0438\u044f \u0432 \u0432\u0430\u0448\u0435\u043c HTML \u0434\u043b\u044f \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u043e\u0431\u0449\u0435\u0433\u043e \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0430 \u0437\u0430\u043f\u0438\u0441\u0435\u0439 RPA:\n\n```html\n<div id=\"rpa-total-container\" style=\"display: none;\">\n    <div class=\"stat-box\">\n        <span class=\"stat-label\">\u041e\u0431\u0449\u0435\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e RPA:</span>\n        <span id=\"total-rpa-records\" class=\"stat-value\">0</span>\n    </div>\n</div>\n```\n\n### \u0418\u0442\u043e\u0433\n\n\u0422\u0435\u043f\u0435\u0440\u044c, \u043a\u043e\u0433\u0434\u0430 \u0432\u044b \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u0442\u0435 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443, JavaScript \u0432\u044b\u0437\u043e\u0432\u0435\u0442 \u043d\u043e\u0432\u044b\u0439 \u043c\u0430\u0440\u0448\u0440\u0443\u0442 `/get_total_rpa_count`, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432\u0435\u0440\u043d\u0435\u0442 \u043e\u0431\u0449\u0435\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0437\u0430\u043f\u0438\u0441\u0435\u0439 \u0442\u0438\u043f\u0430 'RPA'. \u042d\u0442\u043e\u0442 \u0441\u0447\u0435\u0442 \u0431\u0443\u0434\u0435\u0442 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0442\u044c\u0441\u044f \u0432 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0435 \u043e\u0431\u0449\u0435\u0433\u043e \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0430 RPA, \u0438 \u0432\u044b \u0441\u043c\u043e\u0436\u0435\u0442\u0435 \u0432\u0438\u0434\u0435\u0442\u044c, \u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0437\u0430\u043f\u0438\u0441\u0435\u0439 \u0443 \u0432\u0430\u0441 \u0435\u0441\u0442\u044c \u0432 \u0431\u0430\u0437\u0435 \u0434\u0430\u043d\u043d\u044b\u0445.\n\n\u041f\u0440\u0438 \u044d\u0442\u043e\u043c:\n\n- **loadTotalRPA**: \u042d\u0442\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c\u0441\u044f \u043d\u0430 \u0441\u043e\u0431\u044b\u0442\u0438\u0438 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b \u0438 \u043e\u0431\u043d\u043e\u0432\u0438\u0442 \u044d\u043b\u0435\u043c\u0435\u043d\u0442 \u0441 id `total-rpa-records` \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435\u043c \u043e\u0431\u0449\u0435\u0433\u043e \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0430 RPA.\n- **\u041e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044b\u0439 \u043c\u0430\u0440\u0448\u0440\u0443\u0442**: \u0421\u043e\u0437\u0434\u0430\u0435\u0442 \u043d\u043e\u0432\u044b\u0439 \u043c\u0430\u0440\u0448\u0440\u0443\u0442 \u043d\u0430 \u0441\u0442\u043e\u0440\u043e\u043d\u0435 \u0441\u0435\u0440\u0432\u0435\u0440\u0430, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e RPA.\n\n\u0423\u0431\u0435\u0434\u0438\u0442\u0435\u0441\u044c, \u0447\u0442\u043e \u0432\u044b \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442\u0435 \u043a\u043e\u043d\u0441\u043e\u043b\u044c \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430 \u0432 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435 \u043d\u0430 \u043d\u0430\u043b\u0438\u0447\u0438\u0435 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u0445 \u043e\u0448\u0438\u0431\u043e\u043a \u0438\u043b\u0438 \u043f\u0440\u0435\u0434\u0443\u043f\u0440\u0435\u0436\u0434\u0435\u043d\u0438\u0439, \u0447\u0442\u043e\u0431\u044b \u0443\u0431\u0435\u0434\u0438\u0442\u044c\u0441\u044f, \u0447\u0442\u043e \u0432\u0441\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e.","behavior":"degenerate_repetition","conversation_hash":"6bc71a2034fca9ff9176bc3c9a73f460","conversation_redacted":false,"conversation_toxic":false,"country":"Russia","empty_output":false,"evidence_codes":[],"label":"absent","label_present":false,"label_qualified":false,"label_source":"Final dense release","language":"Russian","model":"gpt-4o-mini-2024-07-18","n_chars":110645,"n_turns_in_conversation":7,"n_words":8950,"source_row_offset":747,"source_shard":"turns-00054.parquet","timestamp":"Fri, 29 Nov 2024 10:07:41 GMT","turn_id":"4601480905e138df3d0e1583","turn_index":6,"user_text":"\u0421\u0434\u0435\u043b\u0430\u0439 \u0447\u0442\u043e\u0431\u044b \u043e\u0442\u043e\u0431\u0440\u0430\u0437\u0438\u043b\u043e\u0441\u044c \u043e\u0431\u0449\u0435\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e RPA \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435\n<div id=\"rpa-total-container\" style=\"display: none;\">\n                    <div class=\"stat-box\">\n                        <span class=\"stat-label\">\u041e\u0431\u0449\u0435\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e RPA:</span>\n                        <span id=\"total-rpa-records\" class=\"stat-value\">0</span>\n                </div>\nfrom flask import Flask, render_template, request, redirect, make_response, jsonify, send_file, Response\nfrom flask_sqlalchemy import SQLAlchemy\nfrom sqlalchemy.sql import func\nfrom datetime import datetime, timedelta, date, timezone\nimport pandas as pd\nfrom io import BytesIO\nimport json\nimport queue\nimport logging\nfrom sqlalchemy import cast, Integer, or_\nimport os\nfrom collections import deque\nimport random\n\n\n\napp = Flask(__name__)\n\n\n\napp.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///table_data.db'\napp.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False\ndb = SQLAlchemy(app)\n\nACTIVITY_HISTORY_LENGTH = 400  # \u041a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0445 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439 \u0434\u043b\u044f \u0433\u0440\u0430\u0444\u0438\u043a\u0430\nactivity_data = {}\n\nclass TableRow(db.Model):\n    id = db.Column(db.Integer, primary_key=True)\n    date = db.Column(db.String(10), nullable=False)\n    row_number = db.Column(db.String(10))\n    timestamp = db.Column(db.String(50))\n    number = db.Column(db.String(50))\n    serial = db.Column(db.String(50))\n    dl_number = db.Column(db.String(50))\n    worker_name = db.Column(db.String(100))\n    pack_time = db.Column(db.String(50))\n    arma_type = db.Column(db.String(50))\n    dateshipment = db.Column(db.String(50))\n    aktshipment = db.Column(db.String(50))\n    bad_recovery = db.Column(db.Boolean, default=False)\n\n\nclass DLCounter(db.Model):\n    id = db.Column(db.Integer, primary_key=True)\n    date = db.Column(db.String(10), unique=True, nullable=False)\n    counter = db.Column(db.Integer, nullable=False)\n\n    def __repr__(self):\n        return f'<DLCounter {self.date}: {self.counter}>'\n\n\nclass User(db.Model):\n    id = db.Column(db.Integer, primary_key=True)\n    username = db.Column(db.String(80), unique=True, nullable=False)\n    login_history = db.relationship('LoginHistory', backref='user', lazy=True)\n\n\nclass LoginHistory(db.Model):\n    id = db.Column(db.Integer, primary_key=True)\n    user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)\n    login_date = db.Column(db.DateTime, nullable=False, default=datetime.utcnow)\n\nclass Statistics(db.Model):\n    id = db.Column(db.Integer, primary_key=True)\n    date = db.Column(db.String(10), unique=True, nullable=False)\n    generate_clicks = db.Column(db.Integer, default=0)\n    pack_clicks = db.Column(db.Integer, default=0)\n\n    def __repr__(self):\n        return f'<Statistics {self.date}: Generate={self.generate_clicks}, Pack={self.pack_clicks}>'\n\nclass Prefix(db.Model):\n    id = db.Column(db.Integer, primary_key=True)\n    value = db.Column(db.String(10), nullable=False, unique=True)\n\n# \u0414\u043e\u0431\u0430\u0432\u044c\u0442\u0435 \u044d\u0442\u043e \u0432 \u0440\u0430\u0437\u0434\u0435\u043b \u043c\u043e\u0434\u0435\u043b\u0435\u0439 \u0432\u0430\u0448\u0435\u0433\u043e Flask-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\n\nclass Device(db.Model):\n    id = db.Column(db.Integer, primary_key=True)\n    name = db.Column(db.String(10), unique=True, nullable=False)  # \u0418\u043c\u0435\u043d\u0430: ARM1, ARM2 \u0438 \u0442.\u0434.\n    arma_type = db.Column(db.String(10), nullable=False, default='Other')  # \u0422\u0438\u043f \u0410\u0420\u041c\u0410\n    last_active = db.Column(db.DateTime, nullable=True)  # \u0412\u0440\u0435\u043c\u044f \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0439 \u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0441\u0442\u0438\n    internet_up = db.Column(db.Boolean, nullable=False, default=True)  # \u0421\u0442\u0430\u0442\u0443\u0441 \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442-\u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f\n    copying = db.Column(db.Boolean, nullable=False, default=False)  # \u0421\u0442\u0430\u0442\u0443\u0441 \u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f\n    previous_copying = db.Column(db.Boolean, nullable=False, default=False)  # \u041d\u043e\u0432\u043e\u0435 \u043f\u043e\u043b\u0435\n    sending_number = db.Column(db.Boolean, nullable=False, default=False)  # \u0421\u0442\u0430\u0442\u0443\u0441 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u043d\u043e\u043c\u0435\u0440\u0430\n    processing = db.Column(db.Boolean, nullable=False, default=False)  # \u041d\u043e\u0432\u043e\u0435 \u043f\u043e\u043b\u0435 \u0434\u043b\u044f \u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0441\u0442\u0438 activationGlaz.py\n\n    def to_dict(self, current_time=None):\n        if current_time is None:\n            current_time = datetime.utcnow()\n        if self.copying:\n            status = 'copying'\n        elif self.sending_number:\n            status = 'sending_number'\n        else:\n            status = 'offline'\n            if self.last_active:\n                delta = current_time - self.last_active\n                if delta <= timedelta(seconds=60):\n                    if self.internet_up:\n                        status = 'online'\n                    else:\n                        status = 'no_internet'\n        return {\n            \"id\": self.id,\n            \"name\": self.name,\n            \"arma_type\": self.arma_type,\n            \"last_active\": self.last_active.isoformat() if self.last_active else None,\n            \"internet_up\": self.internet_up,\n            \"copying\": self.copying,\n            \"sending_number\": self.sending_number,\n            \"status\": status\n        }\n    \n    def get_status(self, current_time=None):\n        if current_time is None:\n            current_time = datetime.utcnow()\n\n        if self.copying:\n            return 'copying'\n        elif self.sending_number:\n            return 'sending_number'\n        elif self.name == 'ARM3':\n            # \u0414\u043b\u044f ARM3 \u0438\u0433\u043d\u043e\u0440\u0438\u0440\u0443\u0435\u043c \u0441\u0442\u0430\u0442\u0443\u0441 'processing'\n            if self.last_active:\n                delta = current_time - self.last_active\n                threshold = timedelta(seconds=5)\n                if delta <= threshold:\n                    if self.internet_up:\n                        return 'online'\n                    else:\n                        return 'no_internet'\n            return 'offline'\n        elif self.processing:\n            return 'processing'\n        else:\n            if self.last_active:\n                delta = current_time - self.last_active\n                threshold = timedelta(seconds=5)\n                if delta <= threshold:\n                    if self.internet_up:\n                        return 'online'\n                    else:\n                        return 'no_internet'\n            return 'offline'\n\n\n\n\ntables = {}\ntable = [['\u2116', '\u0412\u0440\u0435\u043c\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438', '\u041d\u043e\u043c\u0435\u0440 ', 'Serial', '\u0413\u0440\u0430\u0444\u0430', '\u0418\u043c\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u0435\u043b\u044f','\u0412\u0440\u0435\u043c\u044f \u0443\u043f\u0430\u043a\u043e\u0432\u043a\u0438' ,'\u0422\u0438\u043f \u0410\u0420\u041c\u0410',  '\u0414\u0430\u0442\u0430 \u043e\u0442\u0433\u0440\u0443\u0437\u043a\u0438',  '\u041d\u043e\u043c\u0435\u0440 \u0410\u043a\u0442\u0430',  '\u0414\u0435\u0439\u0441\u0442\u0432\u0438\u0435']]\n# \u0421\u043e\u0437\u0434\u0430\u0435\u043c \u043e\u0447\u0435\u0440\u0435\u0434\u044c \u0434\u043b\u044f \u0441\u043e\u0431\u044b\u0442\u0438\u0439\nupdate_queue = queue.Queue()\nprevious_processing_states = {}\n\n@app.route('/get_device_status', methods=['GET'])\ndef get_device_status():\n    devices = Device.query.all()\n    device_statuses = {}\n    threshold = timedelta(seconds=5)  # Reduced time threshold for quick offline detection\n    now = datetime.utcnow()\n\n    for device in devices:\n        name = device.name\n\n        # Retrieve the previous processing state\n        prev_processing = previous_processing_states.get(name, False)\n\n        # Check if last_active is within the threshold\n        is_recent = device.last_active and now - device.last_active <= threshold\n\n        if device.sending_number:\n            status = 'sending_number'\n            activity_value = random.choice([2, 3, 2, 3, 4, 3, 2])\n        elif device.copying:\n            status = 'copying'\n            activity_value = random.choice([0, 1, 0, 1, 2, 1, 0])\n        elif is_recent:\n            if device.internet_up:\n                status = 'online'\n                activity_value = 1\n            else:\n                status = 'no_internet'\n                activity_value = 0\n\n            # Handle processing status\n            if device.processing:\n                if device.name == 'ARM3':\n                    if not prev_processing:\n                        # Processing started on ARM3, send a single impulse\n                        activity_value = 5  # Single impulse\n                        status = 'online'  # Keep status as online for ARM3\n                else:\n                    status = 'processing'\n                    activity_value = random.choice([2, 3, 2, 3, 4, 3, 2])\n        else:\n            status = 'offline'\n            activity_value = 0\n\n        device_statuses[name] = {\n            'status': status,\n            'processing': device.processing\n        }\n        activity_data[name].append(activity_value)\n        logging.debug(f\"Device {name}: status {status}, activity {activity_value}\")\n\n        # Update previous_processing_states\n        previous_processing_states[name] = device.processing\n\n    # Convert activity_data to serializable format\n    activity_data_serializable = {name: list(data) for name, data in activity_data.items()}\n\n    return jsonify({\n        'status': 'success',\n        'devices': device_statuses,\n        'activity': activity_data_serializable\n    })\n\n\n\ndef initialize_prefix():\n    prefix = Prefix.query.first()\n    if prefix:\n        app.config['DL_PREFIX'] = prefix.value\n    else:\n        app.config['DL_PREFIX'] = 'DL'  # \u0423\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e, \u0435\u0441\u043b\u0438 \u043f\u0440\u0435\u0444\u0438\u043a\u0441 \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d\n\n\n@app.route('/set_dl_prefix', methods=['POST'])\ndef set_dl_prefix():\n    data = request.json\n    new_prefix = data.get('prefix')\n\n    if not new_prefix:\n        return jsonify({\"status\": \"error\", \"message\": \"Prefix is required\"}), 400\n\n    prefix = Prefix.query.first()\n    if prefix:\n        prefix.value = new_prefix\n    else:\n        prefix = Prefix(value=new_prefix)\n        db.session.add(prefix)\n\n    db.session.commit()\n    app.config['DL_PREFIX'] = new_prefix\n    return jsonify({\"status\": \"success\", \"new_prefix\": new_prefix})\n\n\ndef initialize_activity_data():\n    device_names = ['ARM1', 'ARM2', 'ARM3', 'ARM4', 'ARM5', 'ARM6']\n    for name in device_names:\n        activity_data[name] = deque([0]*ACTIVITY_HISTORY_LENGTH, maxlen=ACTIVITY_HISTORY_LENGTH)\n\ndef create_devices():\n    device_types = {\n        'ARM1': 'CFA',\n        'ARM2': 'VND',\n        'ARM3': 'SRC',\n        'ARM4': 'SRC',\n        'ARM5': 'RPA',\n        'ARM6': 'RPA'  # \u0423\u0431\u0435\u0434\u0438\u0442\u0435\u0441\u044c, \u0447\u0442\u043e ARM6 \u0442\u043e\u0436\u0435 \u0438\u043c\u0435\u0435\u0442 \u0442\u0438\u043f 'RPA'\n    }\n    for name, arma_type in device_types.items():\n        device = Device.query.filter_by(name=name).first()\n        if not device:\n            device = Device(name=name, arma_type=arma_type, sending_number=False)\n            db.session.add(device)\n    db.session.commit()\n    initialize_activity_data()\n\n@app.route('/register_user', methods=['POST'])\ndef register_user():\n    data = request.json\n    worker_name = data.get('worker_name')\n    internet_up = data.get('internet_up', False)\n    copying = data.get('copying', False)\n    sending_number = data.get('sending_number', False)\n    processing = data.get('processing', False)  # \u041d\u043e\u0432\u043e\u0435 \u043f\u043e\u043b\u0435\n\n    if not worker_name:\n        return jsonify({\"status\": \"error\", \"message\": \"worker_name is required\"}), 400\n\n    device = Device.query.filter_by(name=worker_name).first()\n    if not device:\n        return jsonify({\"status\": \"error\", \"message\": \"Device not found\"}), 404\n\n    device.last_active = datetime.utcnow()\n    device.internet_up = internet_up\n    device.copying = copying\n    device.sending_number = sending_number\n    device.processing = processing  # \u0421\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u043c \u043d\u043e\u0432\u043e\u0435 \u043f\u043e\u043b\u0435\n    db.session.commit()\n\n    return jsonify({\"status\": \"success\"})\n\n@app.route('/get_unpacked_days', methods=['GET'])\ndef get_unpacked_days():\n    year = request.args.get('year')\n    month = request.args.get('month')\n    \n    if not year or not month:\n        return jsonify({\"status\": \"error\", \"message\": \"\u041d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u0433\u043e\u0434 \u0438 \u043c\u0435\u0441\u044f\u0446\"}), 400\n    \n    try:\n        year = int(year)\n        month = int(month)\n    except ValueError:\n        return jsonify({\"status\": \"error\", \"message\": \"\u0413\u043e\u0434 \u0438 \u043c\u0435\u0441\u044f\u0446 \u0434\u043e\u043b\u0436\u043d\u044b \u0431\u044b\u0442\u044c \u0447\u0438\u0441\u043b\u0430\u043c\u0438\"}), 400\n\n    # \u0424\u043e\u0440\u043c\u0438\u0440\u0443\u0435\u043c \u0444\u043e\u0440\u043c\u0430\u0442 \u0434\u0430\u0442\u044b \u0434\u043b\u044f \u0444\u0438\u043b\u044c\u0442\u0440\u0430\u0446\u0438\u0438\n    month_str = f\"{month:02d}\"\n    \n    # \u0417\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u0435\u043c \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u044b\u0435 \u0434\u043d\u0438, \u0433\u0434\u0435 pack_time \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u0438 arma_type \u0440\u0430\u0432\u0435\u043d 'RPA'\n    unpacked_dates = TableRow.query.filter(\n        TableRow.date.like(f\"{year}-{month_str}-%\"),\n        TableRow.arma_type == 'RPA',\n        or_(TableRow.pack_time == None, TableRow.pack_time == '')\n    ).with_entities(TableRow.date).distinct().all()\n    \n    # \u0418\u0437\u0432\u043b\u0435\u043a\u0430\u0435\u043c \u0434\u043d\u0438 \u0438\u0437 \u0434\u0430\u0442\n    unpacked_days = set()\n    for date_str, in unpacked_dates:\n        try:\n            day = int(date_str.split('-')[2])\n            unpacked_days.add(day)\n        except (IndexError, ValueError):\n            continue  # \u041f\u0440\u043e\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u043d\u0435\u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u044b\u0435 \u0444\u043e\u0440\u043c\u0430\u0442\u044b \u0434\u0430\u0442\n\n    return jsonify({'status': 'success', 'unpacked_days': list(unpacked_days)})\n\n@app.route('/stream')\ndef stream():\n    def event_stream():\n        while True:\n            try:\n                data = update_queue.get(timeout=20)\n                yield f'data: {data}\\n\\n'\n            except queue.Empty:\n                yield ': keep-alive\\n\\n'\n    return Response(event_stream(), mimetype='text/event-stream')\n\n\n@app.route('/get_table_data')\ndef get_table_data():\n    date = request.args.get('date')\n    filter_arma = request.args.get('filter_arma')\n   \n    app.logger.debug(f\"\u041f\u043e\u043b\u0443\u0447\u0435\u043d \u0437\u0430\u043f\u0440\u043e\u0441: date={date}, filter_arma={filter_arma}\")\n\n    query = TableRow.query.filter_by(date=date)\n\n    if filter_arma == 'RPA':\n        query = query.filter_by(arma_type='RPA')\n\n    rows = query.all()\n    print(f\"\u041d\u0430\u0439\u0434\u0435\u043d\u043e \u0437\u0430\u043f\u0438\u0441\u0435\u0439: {len(rows)}\")\n    \n    # \u0421\u043b\u043e\u0432\u0430\u0440\u0438 \u0434\u043b\u044f \u043f\u043e\u0434\u0441\u0447\u0435\u0442\u0430\n    number_count = {}\n    serial_count = {}\n    dl_number_count = {}\n\n    # \u041f\u043e\u0434\u0441\u0447\u0435\u0442 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0430 \u0432\u0445\u043e\u0436\u0434\u0435\u043d\u0438\u0439 \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f\n    for row in rows:\n        if row.number:\n            clean_number = ''.join(filter(str.isdigit, row.number)).strip()\n            number_count[clean_number] = number_count.get(clean_number, 0) + 1\n\n        if row.serial:\n            clean_serial = ''.join(filter(str.isdigit, row.serial)).strip()\n            serial_count[clean_serial] = serial_count.get(clean_serial, 0) + 1\n\n        if row.dl_number:\n            clean_dl_number = ''.join(filter(str.isdigit, row.dl_number)).strip()\n            dl_number_count[clean_dl_number] = dl_number_count.get(clean_dl_number, 0) + 1\n\n    # \u041b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043f\u043e\u0434\u0441\u0447\u0438\u0442\u0430\u043d\u043d\u044b\u0445 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439\n    app.logger.debug(f\"Number count: {number_count}\")\n    app.logger.debug(f\"Serial count: {serial_count}\")\n    app.logger.debug(f\"DL number count: {dl_number_count}\")\n\n    # \u0423\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 bad_recovery\n    for row in rows:\n        number_duplicate = False\n        serial_duplicate = False\n        dl_number_duplicate = False\n\n        if row.number:\n            clean_number = ''.join(filter(str.isdigit, row.number)).strip()\n            number_duplicate = number_count.get(clean_number, 1) > 1\n\n        if row.serial:\n            clean_serial = ''.join(filter(str.isdigit, row.serial)).strip()\n            serial_duplicate = serial_count.get(clean_serial, 1) > 1\n\n        if row.dl_number:\n            clean_dl_number = ''.join(filter(str.isdigit, row.dl_number)).strip()\n            dl_number_duplicate = dl_number_count.get(clean_dl_number, 1) > 1\n\n        # \u0423\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 bad_recovery \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u043d\u0430\u043b\u0438\u0447\u0438\u044f \u0434\u0443\u0431\u043b\u0438\u043a\u0430\u0442\u043e\u0432\n        row.bad_recovery = number_duplicate or serial_duplicate or dl_number_duplicate\n\n        # \u041b\u043e\u0433\u0438\u0440\u0443\u0435\u043c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b\n        app.logger.debug(f\"Row ID: {row.id}, Number: {row.number}, Serial: {row.serial}, DL Number: {row.dl_number}\")\n        app.logger.debug(f\"Duplicates - Number: {number_duplicate}, Serial: {serial_duplicate}, DL Number: {dl_number_duplicate}\")\n        app.logger.debug(f\"Bad Recovery for Row ID {row.id}: {row.bad_recovery}\")\n\n    if not rows:\n        app.logger.debug(\"\u041d\u0435\u0442 \u0437\u0430\u043f\u0438\u0441\u0435\u0439 \u0434\u043b\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438.\")\n        return jsonify({\"data\": []})  # \u0418\u043b\u0438 \u043b\u044e\u0431\u043e\u0435 \u0434\u0440\u0443\u0433\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435, \u043f\u043e\u0434\u0445\u043e\u0434\u044f\u0449\u0435\u0435 \u0434\u043b\u044f \u0432\u0430\u0448\u0435\u0433\u043e \u043e\u0442\u0432\u0435\u0442\u0430\n\n    # \u0421\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u043c \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f\n    db.session.commit()\n\n    # \u041f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u043a\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u0434\u043b\u044f \u043e\u0442\u0432\u0435\u0442\u0430\n    data = []\n    for row in rows:\n        data.append({\n            'id': row.id,\n            'row_number': row.row_number,\n            'timestamp': row.timestamp,\n            'number': row.number,\n            'serial': row.serial,\n            'dl_number': row.dl_number,\n            'worker_name': row.worker_name,\n            'pack_time': row.pack_time,\n            'arma_type': row.arma_type,\n            'dateshipment': row.dateshipment,\n            'aktshipment': row.aktshipment,\n            'bad_recovery': row.bad_recovery,\n        })\n\n    return jsonify({\"data\": data})\n\n\n\n@app.route('/update_table', methods=['POST'])\ndef update_table():\n    data = request.json\n    print(data)\n    date = data['date']\n    worker_name = data['worker_name']\n    arma_type = data['arma_type']\n\n    # \u041f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0445 \u0437\u0430\u043f\u0438\u0441\u0435\u0439 \u0434\u043b\u044f \u044d\u0442\u043e\u0439 \u0434\u0430\u0442\u044b\n    row_count = TableRow.query.filter_by(date=date).count() + 1\n\n    # \u0421\u043e\u0437\u0434\u0430\u0451\u043c \u043d\u043e\u0432\u0443\u044e \u0441\u0442\u0440\u043e\u043a\u0443 \u0432 \u0442\u0430\u0431\u043b\u0438\u0446\u0435\n    if not data.get('number') and not data.get('serial'):\n        new_row = TableRow(\n            date=date,\n            row_number=str(row_count),\n            timestamp=data['timestamp'],\n            number='',  # \u041f\u0443\u0441\u0442\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0434\u043b\u044f \u043d\u043e\u043c\u0435\u0440\u0430\n            serial='',  # \u041f\u0443\u0441\u0442\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0434\u043b\u044f \u0441\u0435\u0440\u0438\u0439\u043d\u043e\u0433\u043e \u043d\u043e\u043c\u0435\u0440\u0430\n            dl_number='',  # \u041f\u0443\u0441\u0442\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0434\u043b\u044f \u0433\u0440\u0430\u0444\u044b\n            worker_name=worker_name,\n            arma_type=arma_type,\n            dateshipment='',\n            aktshipment='',\n            bad_recovery=data.get('bad_recovery', False)\n        )\n    elif not data.get('number'):\n        new_row = TableRow(\n            date=date,\n            row_number=str(row_count),\n            timestamp=data['timestamp'],\n            number='',  # \u041f\u0443\u0441\u0442\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0434\u043b\u044f \u043d\u043e\u043c\u0435\u0440\u0430\n            serial=data['serial'],\n            dl_number='',  # \u041f\u0443\u0441\u0442\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0434\u043b\u044f \u0433\u0440\u0430\u0444\u044b\n            worker_name=worker_name,\n            arma_type=arma_type,\n            dateshipment='',\n            aktshipment='',\n            bad_recovery=data.get('bad_recovery', False)\n        )\n    else:\n        new_row = TableRow(\n            date=date,\n            row_number=str(row_count),\n            timestamp=data['timestamp'],\n            number=data['number'],\n            serial=data['serial'],\n            dl_number=data.get('dl_number', ''),\n            worker_name=worker_name,\n            arma_type=arma_type,\n            dateshipment=data.get('dateshipment', ' '),\n            aktshipment=data.get('aktshipment', ' '),\n            bad_recovery=data.get('bad_recovery', False)\n        )\n\n    # \u0421\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u043c \u0437\u0430\u043f\u0438\u0441\u044c \u0432 \u0431\u0430\u0437\u0435 \u0434\u0430\u043d\u043d\u044b\u0445\n    db.session.add(new_row)\n\n    device = Device.query.filter_by(name=worker_name).first()\n    if device:\n        device.last_active = datetime.utcnow()\n    db.session.commit()\n\n    # \u041e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u0432 \u043e\u0447\u0435\u0440\u0435\u0434\u044c \u0434\u043b\u044f \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u0432\n    update_queue.put(json.dumps({\"type\": \"update\", \"date\": date}))\n\n    # \u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0438\u043c\u043f\u0443\u043b\u044c\u0441\u0438\u0432\u043d\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0434\u043b\u044f sparkline, \u0435\u0441\u043b\u0438 \u0437\u0430\u043f\u0438\u0441\u044c \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0430 ARM5 \u0438\u043b\u0438 ARM6\n    if worker_name in ['ARM5', 'ARM6']:\n        activity_data[worker_name].append(5)  # \u0417\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0438\u043c\u043f\u0443\u043b\u044c\u0441\u0430 (\u043c\u043e\u0436\u043d\u043e \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u043f\u043e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438)\n\n    return jsonify({\"status\": \"success\"})\n\n\n@app.route('/update_graf', methods=['POST'])\ndef update_graf():\n    try:\n        data = request.json\n        row_id = int(data.get('id'))\n        new_value = data.get('new_value')\n        date = data.get('date')\n\n        if not row_id or not date:\n            return jsonify({\"status\": \"error\", \"message\": \"Missing 'id' or 'date' in request\"}), 400\n\n        # \u041d\u0430\u0445\u043e\u0434\u0438\u043c \u0437\u0430\u043f\u0438\u0441\u044c \u043f\u043e id \u0438 \u0434\u0430\u0442\u0435\n        row = TableRow.query.filter_by(id=row_id, date=date).first()\n        if row:\n            row.dl_number = new_value\n            db.session.commit()\n            return jsonify({\"status\": \"success\"})\n        else:\n            return jsonify({\"status\": \"error\", \"message\": \"Row not found\"}), 404\n    except (ValueError, TypeError) as e:\n        return jsonify({\"status\": \"error\", \"message\": f\"Invalid input: {str(e)}\"}), 400\n    except Exception as e:\n        db.session.rollback()\n        return jsonify({\"status\": \"error\", \"message\": str(e)}), 500\n\n\n@app.route('/update_arma_type', methods=['POST'])\ndef update_arma_type():\n    try:\n        data = request.json\n        date = data['date']\n        serial = data['serial']\n        arma_type = data['arma_type']\n\n        row = TableRow.query.filter_by(date=date, serial=serial).first()\n        if row:\n            row.arma_type = arma_type\n            db.session.commit()\n            return jsonify({\"status\": \"success\"})\n        else:\n            return jsonify({\"status\": \"error\", \"message\": \"Row not found\"})\n    except Exception as e:\n        return jsonify({\"status\": \"error\", \"message\": str(e)})\n\n\n@app.route('/update_number', methods=['POST'])\ndef update_number():\n    try:\n        data = request.json\n        row_id = int(data['id'])  # \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c 'id' \u0432\u043c\u0435\u0441\u0442\u043e 'row_index'\n        new_value = data['new_value']\n        date = data['date']\n\n        # \u041d\u0430\u0445\u043e\u0434\u0438\u043c \u0437\u0430\u043f\u0438\u0441\u044c \u043f\u043e id \u0438 \u0434\u0430\u0442\u0435\n        row = TableRow.query.filter_by(id=row_id, date=date).first()\n        if row:\n            row.number = new_value\n            db.session.commit()\n            return jsonify({\"status\": \"success\"})\n        return jsonify({\"status\": \"error\", \"message\": \"Row not found\"})\n    except Exception as e:\n        db.session.rollback()\n        return jsonify({\"status\": \"error\", \"message\": str(e)})\n\n@app.route('/pack_item', methods=['POST'])\ndef pack_item():\n    try:\n        data = request.json\n        row_id = data['id']\n        date = data['date']\n\n        rows = TableRow.query.filter_by(id=row_id, date=date).all()\n        if rows:\n            row = rows[0]\n            pack_time = datetime.now().strftime(\"%Y-%m-%d %H:%M:%S\")\n            row.pack_time = pack_time\n            db.session.commit()\n            \n            # \u041e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u043c \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0443 \u0443\u043f\u0430\u043a\u043e\u0432\u043a\u0438\n            statistics = Statistics.query.filter_by(date=date).first()\n            if statistics:\n                statistics.pack_clicks += 1\n            else:\n                statistics = Statistics(date=date, generate_clicks=0, pack_clicks=1)  # pack_clicks=1\n                db.session.add(statistics)\n            db.session.commit()\n            \n            # \u041e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u0432 \u043e\u0447\u0435\u0440\u0435\u0434\u044c \u0434\u043b\u044f \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u0432\n            update_queue.put(json.dumps({\"type\": \"update\", \"date\": date}))\n            \n            return jsonify({\"status\": \"success\", \"pack_time\": pack_time})\n\n        return jsonify({\"status\": \"error\", \"message\": \"\u0421\u0442\u0440\u043e\u043a\u0430 \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d\u0430\"}), 404\n    except Exception as e:\n        print(f\"\u041e\u0448\u0438\u0431\u043a\u0430 \u0432 pack_item: {str(e)}\")\n        return jsonify({\"status\": \"error\", \"message\": str(e)}), 500\n\n\n\n@app.route('/set_initial_dl', methods=['POST'])\ndef set_initial_dl():\n    try:\n        data = request.json\n        if not data:\n            return jsonify({\"status\": \"error\", \"message\": \"No data received\"})\n\n        date = data.get('date')\n        initial_number = data.get('initial_number')\n\n        if not date or not initial_number:\n            return jsonify({\n                \"status\": \"error\", \n                \"message\": \"Missing required fields\",\n                \"received\": {\"date\": date, \"initial_number\": initial_number}\n            })\n\n        try:\n            initial_number = int(initial_number)\n        except ValueError:\n            return jsonify({\n                \"status\": \"error\",\n                \"message\": \"Initial number must be an integer\"\n            })\n\n        print(f\"Setting initial DL for date {date}: {initial_number}\")  # \u041e\u0442\u043b\u0430\u0434\u043e\u0447\u043d\u044b\u0439 \u0432\u044b\u0432\u043e\u0434\n\n        dl_counter = DLCounter.query.filter_by(date=date).first()\n        if dl_counter:\n            dl_counter.counter = initial_number\n            print(f\"Updated existing counter for {date}\")  # \u041e\u0442\u043b\u0430\u0434\u043e\u0447\u043d\u044b\u0439 \u0432\u044b\u0432\u043e\u0434\n        else:\n            dl_counter = DLCounter(date=date, counter=initial_number)\n            db.session.add(dl_counter)\n            print(f\"Created new counter for {date}\")  # \u041e\u0442\u043b\u0430\u0434\u043e\u0447\u043d\u044b\u0439 \u0432\u044b\u0432\u043e\u0434\n\n        db.session.commit()\n        return jsonify({\n            \"status\": \"success\",\n            \"message\": f\"DL counter set to {initial_number} for date {date}\"\n        })\n\n    except Exception as e:\n        print(f\"Error in set_initial_dl: {str(e)}\")  # \u041e\u0442\u043b\u0430\u0434\u043e\u0447\u043d\u044b\u0439 \u0432\u044b\u0432\u043e\u0434\n        db.session.rollback()\n        return jsonify({\n            \"status\": \"error\",\n            \"message\": str(e)\n        })\n\n\n@app.route('/generate_dl', methods=['POST'])\ndef generate_dl():\n    try:\n        data = request.json\n        row_id = data['id']\n        date = data['date']\n\n        # \u041f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0438\u043b\u0438 \u0441\u043e\u0437\u0434\u0430\u0435\u043c \u0441\u0447\u0435\u0442\u0447\u0438\u043a DL \u0434\u043b\u044f \u0434\u0430\u043d\u043d\u043e\u0439 \u0434\u0430\u0442\u044b\n        dl_counter = DLCounter.query.filter_by(date=date).first()\n        if not dl_counter:\n            return jsonify({\"status\": \"error\", \"message\": \"DL counter \u043d\u0435 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\"}), 400\n\n        # \u0413\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u043c \u043d\u043e\u0432\u044b\u0439 DL \u043d\u043e\u043c\u0435\u0440 \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u043f\u0440\u0435\u0444\u0438\u043a\u0441\u0430\n        dl_prefix = app.config['DL_PREFIX']  # \u041f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u043f\u0440\u0435\u0444\u0438\u043a\u0441 \u0438\u0437 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438\n        dl_number = f\"{dl_prefix}{dl_counter.counter:06d}\"\n\n        # \u041d\u0430\u0445\u043e\u0434\u0438\u043c \u0438 \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u043c \u043d\u0443\u0436\u043d\u0443\u044e \u0437\u0430\u043f\u0438\u0441\u044c \u043f\u043e id\n        row = TableRow.query.filter_by(id=row_id, date=date).first()\n        if row:\n            row.dl_number = dl_number\n            dl_counter.counter += 1  # \u0423\u0432\u0435\u043b\u0438\u0447\u0438\u0432\u0430\u0435\u043c \u0441\u0447\u0435\u0442\u0447\u0438\u043a\n\n            # \u041e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u043c \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0443 \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438\n            statistics = Statistics.query.filter_by(date=date).first()\n            if statistics:\n                statistics.generate_clicks += 1\n            else:\n                statistics = Statistics(date=date, generate_clicks=1, pack_clicks=0)\n                db.session.add(statistics)\n\n            db.session.commit()\n            return jsonify({\"status\": \"success\", \"dl_number\": dl_number, \"id\": row_id})\n\n        return jsonify({\"status\": \"error\", \"message\": \"\u0421\u0442\u0440\u043e\u043a\u0430 \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d\u0430\"}), 404\n    except Exception as e:\n        return jsonify({\"status\": \"error\", \"message\": str(e)}), 500\n\n\n@app.route('/export_excel')\ndef export_excel():\n    date = request.args.get('date')\n    export_all_rpa = request.args.get('export_all_rpa')\n\n    if export_all_rpa == 'true':\n        # \u042d\u043a\u0441\u043f\u043e\u0440\u0442\u0438\u0440\u0443\u0435\u043c \u0432\u0441\u0435 \u0437\u0430\u043f\u0438\u0441\u0438 RPA\n        query = TableRow.query.filter_by(arma_type='RPA')\n    else:\n        # \u042d\u043a\u0441\u043f\u043e\u0440\u0442\u0438\u0440\u0443\u0435\u043c \u0437\u0430\u043f\u0438\u0441\u0438 \u0437\u0430 \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u044b\u0439 \u0434\u0435\u043d\u044c\n        query = TableRow.query.filter_by(date=date, arma_type='RPA')\n\n    rows = query.all()\n\n    # \u0421\u043e\u0437\u0434\u0430\u0435\u043c DataFrame \u0441 \u0434\u0430\u043d\u043d\u044b\u043c\u0438\n    data = []\n    for row in rows:\n        data.append({\n            '\u2116': row.row_number,\n            '\u0412\u0440\u0435\u043c\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438': row.timestamp,\n            '\u041d\u043e\u043c\u0435\u0440': row.number,\n            'Serial': row.serial,\n            '\u0413\u0440\u0430\u0444\u0430': row.dl_number,\n            '\u0418\u043c\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u0435\u043b\u044f': row.worker_name,\n            '\u0412\u0440\u0435\u043c\u044f \u0443\u043f\u0430\u043a\u043e\u0432\u043a\u0438': row.pack_time,\n            '\u0422\u0438\u043f \u0410\u0420\u041c\u0410': row.arma_type,\n            '\u0414\u0430\u0442\u0430 \u043e\u0442\u0433\u0440\u0443\u0437\u043a\u0438': row.dateshipment,\n            '\u041d\u043e\u043c\u0435\u0440 \u0430\u043a\u0442\u0430': row.aktshipment,\n            'Bad Recovery': row.bad_recovery,\n        })\n\n    if not data:\n        return jsonify({\"error\": \"\u041d\u0435\u0442 \u0437\u0430\u043f\u0438\u0441\u0435\u0439 \u0434\u043b\u044f \u044d\u043a\u0441\u043f\u043e\u0440\u0442\u0430 \u0441 \u0437\u0430\u0434\u0430\u043d\u043d\u044b\u043c\u0438 \u043a\u0440\u0438\u0442\u0435\u0440\u0438\u044f\u043c\u0438.\"}), 400\n\n    df = pd.DataFrame(data)\n\n    # \u0421\u043e\u0437\u0434\u0430\u0435\u043c Excel \u0444\u0430\u0439\u043b\n    output = BytesIO()\n    with pd.ExcelWriter(output, engine='xlsxwriter') as writer:\n        df.to_excel(writer, index=False, sheet_name='Sheet1')\n\n        # \u041d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u043c \u0444\u043e\u0440\u043c\u0430\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435\n        workbook = writer.book\n        worksheet = writer.sheets['Sheet1']\n\n        # \u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0430\u044f \u0448\u0438\u0440\u0438\u043d\u0430 \u0441\u0442\u043e\u043b\u0431\u0446\u043e\u0432\n        for idx, col in enumerate(df.columns):\n            series = df[col]\n            max_len = max(\n                series.astype(str).map(len).max(),\n                len(str(col))\n            ) + 2\n            worksheet.set_column(idx, idx, max_len)\n\n    output.seek(0)\n\n    filename = 'RPA_export.xlsx' if export_all_rpa == 'true' else f'export_{date}.xlsx'\n    return send_file(\n        output,\n        mimetype='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',\n        as_attachment=True,\n        download_name=filename\n    )\n\n@app.route('/update_serial', methods=['POST'])\ndef update_serial():\n    try:\n        data = request.json\n        row_index = int(data['row_index'])\n        new_value = data['new_value']\n        date = data['date']\n\n        rows = TableRow.query.filter_by(date=date).all()\n        if 0 <= row_index < len(rows):\n            row = rows[row_index]\n            row.serial = new_value\n            db.session.commit()\n            return jsonify({\"status\": \"success\"})\n        return jsonify({\"status\": \"error\", \"message\": \"Invalid row index\"})\n    except Exception as e:\n        db.session.rollback()\n        return jsonify({\"status\": \"error\", \"message\": str(e)})\n\n\ndef initialize_table_for_date(date):\n    # \u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c, \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0442 \u043b\u0438 \u0443\u0436\u0435 \u0437\u0430\u043f\u0438\u0441\u0438 \u0434\u043b\u044f \u044d\u0442\u043e\u0439 \u0434\u0430\u0442\u044b\n    existing = TableRow.query.filter_by(date=date).first()\n    if not existing:\n        # \u0421\u043e\u0437\u0434\u0430\u0435\u043c \u043d\u043e\u0432\u0443\u044e \u0437\u0430\u043f\u0438\u0441\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u0432 \u0441\u043b\u0443\u0447\u0430\u0435 \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445\n        new_row = TableRow(\n            date=date,\n            row_number=str(1),\n            timestamp=datetime.now().strftime(\"%Y-%m-%d %H:%M:%S\"),\n            number='',\n            serial='',\n            dl_number='',\n            worker_name='',\n            arma_type='',\n            pack_time='',\n            dateshipment='',\n            aktshipment='',\n            bad_recovery='',\n        )\n        db.session.add(new_row)\n        \n        # \u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0435\u043c \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0443 \u0434\u043b\u044f \u043d\u043e\u0432\u043e\u0439 \u0434\u0430\u0442\u044b\n        statistics = Statistics(date=date, generate_clicks=0, pack_clicks=0)\n        db.session.add(statistics)\n        \n        db.session.commit()\n\n\n@app.route('/update_serial_arma', methods=['POST'])\ndef update_serial_arma():\n    try:\n        data = request.json\n        date = data['date']\n        serial = data['serial']\n        arma_type = data['arma_type']\n\n        # \u0421\u043e\u0437\u0434\u0430\u0435\u043c \u043d\u043e\u0432\u0443\u044e \u0437\u0430\u043f\u0438\u0441\u044c \u0432 \u0442\u0430\u0431\u043b\u0438\u0446\u0435\n        new_row = TableRow(\n            date=date,\n            serial=serial,\n            arma_type=arma_type,\n            timestamp=datetime.now().strftime(\"%Y-%m-%d %H:%M:%S\")\n        )\n\n        db.session.add(new_row)\n        db.session.commit()\n\n        return jsonify({\"status\": \"success\"})\n    except Exception as e:\n        db.session.rollback()\n        return jsonify({\"status\": \"error\", \"message\": str(e)}), 500\n\n@app.route('/get_statistics')\ndef get_statistics():\n    try:\n        date = request.args.get('date')\n        app.logger.debug(f\"\u041f\u043e\u043b\u0443\u0447\u0435\u043d \u0437\u0430\u043f\u0440\u043e\u0441 \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0438 \u0434\u043b\u044f \u0434\u0430\u0442\u044b: {date}\")\n        \n        # \u041f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0443 \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 \u0438 \u0443\u043f\u0430\u043a\u043e\u0432\u043a\u0438\n        statistics = Statistics.query.filter_by(date=date).first()\n        if not statistics:\n            generate_clicks = 0\n            pack_clicks = 0\n            app.logger.debug(f\"\u0421\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0430 \u0434\u043b\u044f \u0434\u0430\u0442\u044b {date} \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d\u0430. \u0423\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 0.\")\n        else:\n            generate_clicks = statistics.generate_clicks\n            pack_clicks = statistics.pack_clicks\n            app.logger.debug(f\"\u0421\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0430 \u0434\u043b\u044f \u0434\u0430\u0442\u044b {date}: \u0413\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0439 = {generate_clicks}, \u0423\u043f\u0430\u043a\u043e\u0432\u043e\u043a = {pack_clicks}\")\n        \n        # \u041f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0437\u0430\u043f\u0438\u0441\u0435\u0439 \u0442\u0438\u043f\u0430 \"RPA\"\n        rpa_records = TableRow.query.filter_by(date=date, arma_type='RPA').count()\n        app.logger.debug(f\"\u041a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0437\u0430\u043f\u0438\u0441\u0435\u0439 \u0442\u0438\u043f\u0430 RPA \u0434\u043b\u044f \u0434\u0430\u0442\u044b {date}: {rpa_records}\")\n        \n        # \u0421\u0447\u0438\u0442\u0430\u0435\u043c \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0437\u0430\u043f\u0438\u0441\u0435\u0439 \"RPA\" \u0431\u0435\u0437 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0432 \u043a\u043e\u043b\u043e\u043d\u043a\u0435 \"\u0413\u0440\u0430\u0444\u0430\"\n        unpacked_clicks = TableRow.query.filter(\n            TableRow.date == date,\n            TableRow.arma_type == 'RPA',\n            TableRow.dl_number == None\n        ).count()\n        \n        # \u041f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0443\u043f\u0430\u043a\u043e\u0432\u0430\u043d\u043d\u044b\u0445 \u0437\u0430\u043f\u0438\u0441\u0435\u0439 \u0437\u0430 \u0442\u0435\u043a\u0443\u0449\u0438\u0439 \u0447\u0430\u0441\n        current_hour = datetime.now().replace(minute=0, second=0, microsecond=0)\n        next_hour = current_hour + timedelta(hours=1)\n        done_per_hour = TableRow.query.filter(\n            TableRow.date == date,\n            TableRow.arma_type == 'RPA',\n            TableRow.pack_time >= current_hour,\n            TableRow.pack_time < next_hour\n        ).count()\n        \n        return jsonify({\n            \"generate_clicks\": generate_clicks,\n            \"pack_clicks\": pack_clicks,\n            \"rpa_records\": rpa_records,\n            \"unpacked_clicks\": unpacked_clicks,\n            \"done_per_hour\": done_per_hour\n        })\n    except Exception as e:\n        app.logger.error(f\"\u041e\u0448\u0438\u0431\u043a\u0430 \u0432 get_statistics: {str(e)}\")\n        return jsonify({\n            \"generate_clicks\": 0,\n            \"pack_clicks\": 0,\n            \"rpa_records\": 0,\n            \"unpacked_clicks\": 0,\n            \"done_per_hour\": 0,\n            \"error\": str(e)\n        })\n@app.route('/delete_row', methods=['POST'])\ndef delete_row():\n    try:\n        data = request.json\n        row_id = data.get('id')\n\n        if not row_id:\n            return jsonify({'status': 'error', 'message': 'ID \u0437\u0430\u043f\u0438\u0441\u0438 \u043d\u0435 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d'}), 400\n\n        row = TableRow.query.get(row_id)\n        if not row:\n            return jsonify({'status': 'error', 'message': '\u0417\u0430\u043f\u0438\u0441\u044c \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d\u0430'}), 404\n\n        date = row.date  # \u041f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0434\u0430\u0442\u0443 \u0437\u0430\u043f\u0438\u0441\u0438 \u0434\u043b\u044f \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0438\n\n        # \u041f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0437\u0430\u043f\u0438\u0441\u044c \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0438 \u0434\u043b\u044f \u044d\u0442\u043e\u0439 \u0434\u0430\u0442\u044b\n        statistics = Statistics.query.filter_by(date=date).first()\n\n        if statistics:\n            # \u0415\u0441\u043b\u0438 \u0437\u0430\u043f\u0438\u0441\u044c \u0438\u043c\u0435\u043b\u0430 \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 DL \u043d\u043e\u043c\u0435\u0440, \u0443\u043c\u0435\u043d\u044c\u0448\u0430\u0435\u043c generate_clicks\n            if row.dl_number:\n                if statistics.generate_clicks > 0:\n                    statistics.generate_clicks -= 1\n                else:\n                    app.logger.warning(f\"Attempting to decrement generate_clicks below zero for date {date}\")\n\n            # \u0415\u0441\u043b\u0438 \u0437\u0430\u043f\u0438\u0441\u044c \u0431\u044b\u043b\u0430 \u0443\u043f\u0430\u043a\u043e\u0432\u0430\u043d\u0430, \u0443\u043c\u0435\u043d\u044c\u0448\u0430\u0435\u043c pack_clicks\n            if row.pack_time:\n                if statistics.pack_clicks > 0:\n                    statistics.pack_clicks -= 1\n                else:\n                    app.logger.warning(f\"Attempting to decrement pack_clicks below zero for date {date}\")\n\n            db.session.commit()\n        else:\n            app.logger.warning(f\"No Statistics entry found for date {date} when deleting row {row_id}\")\n\n        # \u0423\u0434\u0430\u043b\u044f\u0435\u043c \u0437\u0430\u043f\u0438\u0441\u044c \u0438\u0437 \u0442\u0430\u0431\u043b\u0438\u0446\u044b\n        db.session.delete(row)\n        db.session.commit()\n\n        # \u0423\u043c\u0435\u043d\u044c\u0448\u0430\u0435\u043c \u0441\u0447\u0435\u0442\u0447\u0438\u043a DL, \u0435\u0441\u043b\u0438 \u0437\u0430\u043f\u0438\u0441\u044c \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043b\u0430 DL-\u043d\u043e\u043c\u0435\u0440\n        if row.dl_number:\n            dl_counter = DLCounter.query.filter_by(date=date).first()\n            if dl_counter and dl_counter.counter > 0:\n                dl_counter.counter -= 1\n                db.session.commit()\n\n        # \u041e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u0432 \u043e\u0447\u0435\u0440\u0435\u0434\u044c \u0434\u043b\u044f \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u0432\n        update_queue.put(json.dumps({\"type\": \"delete\", \"date\": date, \"id\": row.id}))\n\n        return jsonify({'status': 'success'})\n    except Exception as e:\n        db.session.rollback()\n        app.logger.error(f\"\u041e\u0448\u0438\u0431\u043a\u0430 \u0432 delete_row: {str(e)}\")\n        return jsonify({'status': 'error', 'message': str(e)}), 500\n\n@app.route('/', methods=['GET', 'POST'])\ndef main():\n    if request.method == 'POST':\n        worker = request.form.get('worker')\n        name = request.form.get('name')\n\n        # \u0421\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u043c \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e \u0432\u0445\u043e\u0434\u0435\n        user = User.query.filter_by(username=name).first()\n        if not user:\n            user = User(username=name)\n            db.session.add(user)\n\n        login_history = LoginHistory(user=user)\n        db.session.add(login_history)\n        db.session.commit()\n\n        resp = make_response(redirect('/welcome'))\n        resp.set_cookie('worker', worker)\n        resp.set_cookie('name', name)\n        return resp\n\n    return render_template('main.html')\n\n\n@app.route('/get_current_dl', methods=['GET'])\ndef get_current_dl():\n    date = request.args.get('date')\n    if not date:\n        return jsonify({\"status\": \"error\", \"message\": \"\u0414\u0430\u0442\u0430 \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u0430\"}), 400\n\n    dl_counter = DLCounter.query.filter_by(date=date).first()\n    if dl_counter:\n        return jsonify({\"status\": \"success\", \"current_dl\": dl_counter.counter})\n    else:\n        return jsonify({\"status\": \"error\", \"message\": \"\u0421\u0447\u0435\u0442\u0447\u0438\u043a DL \u043d\u0435 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d \u0434\u043b\u044f \u044d\u0442\u043e\u0439 \u0434\u0430\u0442\u044b\"}), 404\n\n\n@app.route('/welcome')\ndef welcome():\n    worker = request.cookies.get('worker')\n    name = request.cookies.get('name')\n\n    if not worker or not name:\n        return redirect('/')\n\n    current_time = datetime.utcnow()\n    devices = [device.to_dict(current_time=current_time) for device in Device.query.order_by(Device.name).all()]\n    current_time_str = current_time.isoformat()\n\n    # \u041f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0442\u0435\u043a\u0443\u0449\u0438\u0439 \u043f\u0440\u0435\u0444\u0438\u043a\u0441\n    prefix = Prefix.query.first()\n    dl_prefix = prefix.value if prefix else 'DL'\n\n    return render_template('welcome.html', name=name, worker=worker, table=table, devices=devices, current_time=current_time_str, dl_prefix=dl_prefix)\n\n\n@app.route('/logout')\ndef logout():\n    resp = make_response(redirect('/'))\n    resp.delete_cookie('worker')\n    resp.delete_cookie('name')\n    return resp\n\n@app.route('/get_unpacked_rpa_counts', methods=['GET'])\ndef get_unpacked_rpa_counts():\n    year = request.args.get('year')\n    month = request.args.get('month')\n    \n    if not year or not month:\n        return jsonify({\"status\": \"error\", \"message\": \"\u041d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u0433\u043e\u0434 \u0438 \u043c\u0435\u0441\u044f\u0446\"}), 400\n    \n    try:\n        year = int(year)\n        month = int(month)\n    except ValueError:\n        return jsonify({\"status\": \"error\", \"message\": \"\u0413\u043e\u0434 \u0438 \u043c\u0435\u0441\u044f\u0446 \u0434\u043e\u043b\u0436\u043d\u044b \u0431\u044b\u0442\u044c \u0447\u0438\u0441\u043b\u0430\u043c\u0438\"}), 400\n\n    # \u0424\u043e\u0440\u043c\u0438\u0440\u0443\u0435\u043c \u0444\u043e\u0440\u043c\u0430\u0442 \u0434\u0430\u0442\u044b \u0434\u043b\u044f \u0444\u0438\u043b\u044c\u0442\u0440\u0430\u0446\u0438\u0438\n    month_str = f\"{month:02d}\"\n    \n    # \u0417\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u0435\u043c \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0437\u0430\u043f\u0438\u0441\u0435\u0439 RPA \u0441 \u043f\u0443\u0441\u0442\u044b\u043c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435\u043c \u0432 \u043a\u043e\u043b\u043e\u043d\u043a\u0435 \"\u0412\u0440\u0435\u043c\u044f \u0443\u043f\u0430\u043a\u043e\u0432\u043a\u0438\" \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0434\u043d\u044f\n    unpacked_counts = TableRow.query.filter(\n        TableRow.date.like(f\"{year}-{month_str}-%\"),\n        TableRow.arma_type == 'RPA',\n        or_(TableRow.pack_time == None, TableRow.pack_time == '')\n    ).group_by(TableRow.date).with_entities(TableRow.date, func.count(TableRow.id)).all()\n    \n    # \u041f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u0443\u0435\u043c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0432 \u0441\u043b\u043e\u0432\u0430\u0440\u044c\n    unpacked_counts_dict = {date: count for date, count in unpacked_counts}\n    \n    return jsonify({'status': 'success', 'unpacked_counts': unpacked_counts_dict})\n\n@app.route('/get_last_dl_number_all_time', methods=['GET'])\ndef get_last_dl_number_all_time():\n    # \u041f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u044e\u044e \u0437\u0430\u043f\u0438\u0441\u044c \u0441 \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u044b\u043c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435\u043c DL \u0437\u0430 \u0432\u0441\u0451 \u0432\u0440\u0435\u043c\u044f\n    last_dl_row = TableRow.query.order_by(TableRow.dl_number.desc()).first()\n    if last_dl_row:\n        last_dl = last_dl_row.dl_number\n        if last_dl and last_dl.startswith('DL'):\n            last_dl_number = int(last_dl[2:])\n            next_dl_number = last_dl_number + 1\n        else:\n            next_dl_number = 1\n    else:\n        next_dl_number = 1\n\n    return jsonify({\"status\": \"success\", \"next_dl_number\": next_dl_number})\n\n\n@app.route('/import_excel', methods=['POST'])\ndef import_excel():\n    try:\n        # Check if a file is provided\n        if 'file' not in request.files:\n            return jsonify({\"status\": \"error\", \"message\": \"No file provided\"}), 400\n\n        # Get the uploaded file\n        file = request.files['file']\n\n        # Check the file extension for security reasons\n        if not file.filename.endswith('.xlsx') and not file.filename.endswith('.xls'):\n            return jsonify({\"status\": \"error\", \"message\": \"File type not allowed\"}), 400\n\n        # Read the Excel file into a DataFrame\n        df = pd.read_excel(file)\n\n        # Define the fields expected in the Excel file\n        required_columns = ['\u0412\u0440\u0435\u043c\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438', '\u041d\u043e\u043c\u0435\u0440', 'Serial', '\u0413\u0440\u0430\u0444\u0430', '\u0418\u043c\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u0435\u043b\u044f']\n\n        # Check if all required columns are in the DataFrame\n        if not all(col in df.columns for col in required_columns):\n            return jsonify({\"status\": \"error\", \"message\": f\"Missing required columns. Required columns are: {', '.join(required_columns)}\"}), 400\n\n        # Get current date\n        current_date = datetime.now().date().strftime(\"%Y-%m-%d\")\n\n        # Iterate over DataFrame rows and insert data into the database\n        for _, row in df.iterrows():\n            new_row = TableRow(\n                date=current_date,\n                timestamp=row['\u0412\u0440\u0435\u043c\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438'],\n                number=row['\u041d\u043e\u043c\u0435\u0440'],\n                serial=row['Serial'],\n                dl_number=row['\u0413\u0440\u0430\u0444\u0430'],\n                worker_name=row['\u0418\u043c\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u0435\u043b\u044f'],\n                row_number='',  # Will be calculated later\n                pack_time='0',  # Default value\n                arma_type='0',  # Default value\n                dateshipment='0', \n                aktshipment='0',   # Default value\n                bad_recovery=row.get('bad_recovery', False) ,\n            )\n            db.session.add(new_row)\n        db.session.commit()\n\n        # Update row numbers\n        rows_of_day = TableRow.query.filter_by(date=current_date).order_by(TableRow.id).all()\n        for idx, row in enumerate(rows_of_day, 1):\n            row.row_number = str(idx)\n        db.session.commit()\n\n        return jsonify({\"status\": \"success\", \"message\": \"Data imported successfully\"})\n\n    except Exception as e:\n        db.session.rollback()\n        app.logger.error(f\"Error during Excel import: {str(e)}\")  # \u041b\u043e\u0433\u0438\u0440\u0443\u0435\u043c \u043e\u0448\u0438\u0431\u043a\u0443\n        return jsonify({\"status\": \"error\", \"message\": str(e)}), 500\n    \n@app.route('/delete_imported_data', methods=['POST'])\ndef delete_imported_data():\n    try:\n        current_date = datetime.now().date().strftime(\"%Y-%m-%d\")\n        rows_deleted = TableRow.query.filter_by(date=current_date).delete()\n        db.session.commit()\n\n        return jsonify({\"status\": \"success\", \"message\": f\"{rows_deleted} rows deleted for date {current_date}\"})\n\n    except Exception as e:\n        db.session.rollback()\n        return jsonify({\"status\": \"error\", \"message\": str(e)}), 500\n    \n@app.route('/get_rpa_records', methods=['GET'])\ndef get_rpa_records():\n    try:\n        # \u0417\u0430\u043c\u0435\u043d\u0438\u0442\u0435 \u0444\u0438\u043b\u044c\u0442\u0440 \u043f\u043e \u0438\u043c\u0435\u043d\u0438 'worker_name' \u043d\u0430 \u0444\u0438\u043b\u044c\u0442\u0440 \u043f\u043e 'arma_type'\n        rows = TableRow.query.filter_by(arma_type='RPA').all()\n\n        data = []\n        for row in rows:\n            data.append({\n                'id': row.id,\n                'row_number': row.row_number,\n                'timestamp': row.timestamp,\n                'number': row.number,\n                'serial': row.serial,\n                'dl_number': row.dl_number,\n                'worker_name': row.worker_name,\n                'pack_time': row.pack_time,\n                'arma_type': row.arma_type,\n                'dateshipment': row.dateshipment,\n                'aktshipment': row.aktshipment,\n                'bad_recovery': row.bad_recovery,\n            })\n\n        return jsonify({\"status\": \"success\", \"data\": data})\n\n    except Exception as e:\n        return jsonify({\"status\": \"error\", \"message\": str(e)}), 500\n\n@app.route('/export_rpa_excel')\ndef export_rpa_excel():\n    try:\n        # \u041d\u0430\u0447\u0438\u043d\u0430\u0435\u043c \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d\u0438\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u0441 \u0444\u0438\u043b\u044c\u0442\u0440\u0430\u0446\u0438\u0438 \u043f\u043e \u0442\u0438\u043f\u0443 \u0410\u0420\u041c\u0410 \"RPA\"\n        query = TableRow.query.filter_by(arma_type='RPA')\n\n        # \u0414\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u0443\u0441\u043b\u043e\u0432\u0438\u044f \u0444\u0438\u043b\u044c\u0442\u0440\u0430\u0446\u0438\u0438: \n        # - dl_number \u043d\u0435 \u043f\u0443\u0441\u0442\u043e\u0439\n        # - pack_time \u043d\u0435 \u043f\u0443\u0441\u0442\u043e\u0439\n        query = query.filter(\n            TableRow.dl_number.isnot(None),\n            TableRow.dl_number != '',\n            TableRow.pack_time.isnot(None),\n            TableRow.pack_time != ''\n        )\n\n        rows = query.all()\n\n        # \u0421\u043e\u0437\u0434\u0430\u0435\u043c DataFrame \u0442\u043e\u043b\u044c\u043a\u043e \u0441 \u043e\u0442\u0444\u0438\u043b\u044c\u0442\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u043c\u0438 \u0434\u0430\u043d\u043d\u044b\u043c\u0438\n        data = []\n        for row in rows:\n            data.append({\n                '\u2116': row.row_number,\n                '\u0412\u0440\u0435\u043c\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438': row.timestamp,\n                '\u041d\u043e\u043c\u0435\u0440': row.number,\n                'Serial': row.serial,\n                '\u0413\u0440\u0430\u0444\u0430': row.dl_number,\n                '\u0418\u043c\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u0435\u043b\u044f': row.worker_name,\n                '\u0412\u0440\u0435\u043c\u044f \u0443\u043f\u0430\u043a\u043e\u0432\u043a\u0438': row.pack_time,\n                '\u0422\u0438\u043f \u0410\u0420\u041c\u0410': row.arma_type,\n                '\u0414\u0430\u0442\u0430 \u043e\u0442\u0433\u0440\u0443\u0437\u043a\u0438': row.dateshipment,\n                '\u041d\u043e\u043c\u0435\u0440 \u0430\u043a\u0442\u0430': row.aktshipment,\n                'bad_recovery': row.bad_recovery,\n            })\n\n        if not data:\n            return jsonify({\"error\": \"\u041d\u0435\u0442 \u0437\u0430\u043f\u0438\u0441\u0435\u0439 \u0434\u043b\u044f \u044d\u043a\u0441\u043f\u043e\u0440\u0442\u0430 \u0441 \u0437\u0430\u0434\u0430\u043d\u043d\u044b\u043c\u0438 \u043a\u0440\u0438\u0442\u0435\u0440\u0438\u044f\u043c\u0438.\"}), 400\n\n        df = pd.DataFrame(data)\n\n        # \u0421\u043e\u0437\u0434\u0430\u0435\u043c Excel \u0444\u0430\u0439\u043b\n        output = BytesIO()\n        with pd.ExcelWriter(output, engine='xlsxwriter') as writer:\n            df.to_excel(writer, index=False, sheet_name='Sheet1')\n\n            # \u041d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u043c \u0444\u043e\u0440\u043c\u0430\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435\n            workbook = writer.book\n            worksheet = writer.sheets['Sheet1']\n\n            # \u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0430\u044f \u0448\u0438\u0440\u0438\u043d\u0430 \u0441\u0442\u043e\u043b\u0431\u0446\u043e\u0432\n            for idx, col in enumerate(df.columns):\n                series = df[col]\n                max_len = max(\n                    series.astype(str).map(len).max(),\n                    len(str(col))\n                ) + 2\n                worksheet.set_column(idx, idx, max_len)\n\n                # \u0424\u043e\u0440\u043c\u0430\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0447\u0438\u0441\u043b\u043e\u0432\u044b\u0445 \u0441\u0442\u043e\u043b\u0431\u0446\u043e\u0432\n                if col in ['\u041d\u043e\u043c\u0435\u0440', '\u0413\u0440\u0430\u0444\u0430']:\n                    num_format = workbook.add_format({'num_format': '0'})\n                    worksheet.set_column(idx, idx, max_len, num_format)\n\n        output.seek(0)\n\n        return send_file(\n            output,\n            mimetype='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',\n            as_attachment=True,\n            download_name='RPA_export.xlsx'\n        )\n\n    except Exception as e:\n        print(f\"Export error: {str(e)}\")\n        return jsonify({\"error\": str(e)}), 500\n    \n\n@app.route('/get_duplicates')\ndef get_duplicates():\n    try:\n        # \u041f\u043e\u043b\u0443\u0447\u0438\u043c \u0432\u0441\u0435 \u0441\u0442\u0440\u043e\u043a\u0438 \u0438\u0437 \u0442\u0430\u0431\u043b\u0438\u0446\u044b\n        rows = TableRow.query.all()\n\n        # \u0425\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430 \u0434\u043b\u044f \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u0430 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439\n        numbers = {}\n        serials = {}\n        dl_numbers = {}\n\n        # \u0421\u043e\u0431\u0438\u0440\u0430\u0435\u043c \u0432\u0441\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0438 \u0438\u0445 \u0438\u043d\u0434\u0435\u043a\u0441\u044b\n        data = []\n        for row in rows:\n            row_data = {\n                'id': row.id,\n                'row_number': row.row_number,\n                'timestamp': row.timestamp,\n                'number': row.number,\n                'serial': row.serial,\n                'dl_number': row.dl_number,\n                'worker_name': row.worker_name,\n                'pack_time': row.pack_time,\n                'arma_type': row.arma_type,\n                'dateshipment': row.dateshipment,\n                'aktshipment': row.aktshipment,\n                'bad_recovery': row.bad_recovery,\n            }\n            data.append(row_data)\n            if row.number:\n                clean_number = ''.join(filter(str.isdigit, row.number))\n                if clean_number in numbers:\n                    numbers[clean_number].append(len(data) - 1)\n                else:\n                    numbers[clean_number] = [len(data) - 1]\n\n            if row.serial:\n                clean_serial = ''.join(filter(str.isdigit, row.serial))\n                if clean_serial in serials:\n                    serials[clean_serial].append(len(data) - 1)\n                else:\n                    serials[clean_serial] = [len(data) - 1]\n\n            if row.dl_number:\n                clean_dl_number = ''.join(filter(str.isdigit, row.dl_number))\n                if clean_dl_number in dl_numbers:\n                    dl_numbers[clean_dl_number].append(len(data) - 1)\n                else:\n                    dl_numbers[clean_dl_number] = [len(data) - 1]\n\n        # \u0424\u0438\u043b\u044c\u0442\u0440\u0443\u0435\u043c \u0442\u043e\u043b\u044c\u043a\u043e \u0440\u0435\u0430\u043b\u044c\u043d\u044b\u0435 \u0434\u0443\u0431\u043b\u0438\u043a\u0430\u0442\u044b\n        duplicate_numbers = {k: v for k, v in numbers.items() if len(v) > 1}\n        duplicate_serials = {k: v for k, v in serials.items() if len(v) > 1}\n        duplicate_dl_numbers = {k: v for k, v in dl_numbers.items() if len(v) > 1}\n\n        duplicates = {\n            \"numbers\": duplicate_numbers,\n            \"serials\": duplicate_serials,\n            \"dl_numbers\": duplicate_dl_numbers\n        }\n\n        # \u0421\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u043c \u0438\u043d\u0434\u0435\u043a\u0441\u044b \u0432\u0441\u0435\u0445 \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u044b\u0445 \u0434\u0443\u0431\u043b\u0438\u043a\u0430\u0442\u043e\u0432\n        duplicate_indices = set()\n        for indices in duplicate_numbers.values():\n            duplicate_indices.update(indices)\n        for indices in duplicate_serials.values():\n            duplicate_indices.update(indices)\n        for indices in duplicate_dl_numbers.values():\n            duplicate_indices.update(indices)\n\n        # \u041e\u0442\u0431\u0438\u0440\u0430\u0435\u043c \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u0443\u0431\u043b\u0438\u043a\u0430\u0442\u044b\n        duplicates_data = [data[idx] for idx in duplicate_indices]\n\n        return jsonify({\n            \"status\": \"success\",\n            \"data\": duplicates_data,\n            \"duplicates\": duplicates\n        })\n\n    except Exception as e:\n        return jsonify({\"status\": \"error\", \"message\": str(e)})\n\nif __name__ == '__main__':\n    with app.app_context():\n        db.create_all()\n        create_devices()\n\n\n\n    logging.disable(logging.CRITICAL)\n    os.system('title \u0421\u0415\u0420\u0412\u0415\u0420')\n    app.run(host='192.168.50.110', port=80, debug=True)  #192.168.50.99\nlet isEditing = false;\nlet isRPAFilterActive = false;\nlet isShowingDuplicates = false;\nlet searchTimeout;\nlet lastUpdateTime = 0;\nconst updateInterval = 1000;\nlet eventSource;\nlet lastData = null;\nlet isDeleting = false;\nlet fpInstance;\nlet unpackedDaysCache = {}; // \u041a\u043b\u044e\u0447\u0438 \u0431\u0443\u0434\u0443\u0442 \u0432 \u0444\u043e\u0440\u043c\u0430\u0442\u0435 'YYYY-MM', \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 - Set \u0434\u043d\u0435\u0439\nconst deviceSparklines = {};\n\n// \u0413\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u044b\u0435 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u0434\u043b\u044f \u043e\u0442\u0441\u043b\u0435\u0436\u0438\u0432\u0430\u043d\u0438\u044f \u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u043a\u0438\nlet globalSortColumn = null;\nlet globalSortOrder = 'asc';\n\nfunction getSelectedDate() {\n    return $('#datepicker').val();\n}\n\n// \u0424\u0443\u043d\u043a\u0446\u0438\u044f \u0434\u043b\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u0444\u0438\u043b\u044c\u0442\u0440\u0430\nfunction getArmaFilter() {\n    return $('#armaFilter').is(':checked') ? 'RPA' : '';\n}\n\nfunction updateTable(force = false, highlightNew = false) {\n    return new Promise((resolve, reject) => {\n        const now = Date.now();\n        if (!force && now - lastUpdateTime < updateInterval) {\n            resolve();\n            return;\n        }\n        if (isEditing) {\n            resolve();\n            return;\n        }\n\n        if (isEditing || isDeleting) { // \u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0443 \u043d\u0430 isDeleting\n            resolve();\n            return;\n        }\n\n        // \u041f\u0440\u043e\u0432\u0435\u0440\u044c\u0442\u0435, \u0435\u0441\u043b\u0438 \u0444\u0438\u043b\u044c\u0442\u0440 RPA \u0430\u043a\u0442\u0438\u0432\u0435\u043d, \u043d\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0439\u0442\u0435 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\n        if (isRPAFilterActive) {\n            resolve();\n            return;\n        }\n       \n        if (isShowingDuplicates) {\n            resolve();\n            return;\n        }\n\n        $.ajax({\n            url: '/get_table_data',\n            type: 'GET',\n            data: { \n                date: getSelectedDate(),\n                filter_arma: getArmaFilter()\n            },\n            success: function(response) {\n                var tableBody = $('#tableBody');\n\n                // \u041e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u043c \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435 \u0442\u0430\u0431\u043b\u0438\u0446\u044b\n                updateTableContent(response.data, tableBody, highlightNew);\n\n                // \u041f\u0440\u0438\u043c\u0435\u043d\u044f\u0435\u043c \u0442\u0435\u043a\u0443\u0449\u0443\u044e \u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u043a\u0443\n                if (globalSortColumn !== null) {\n                    sortTable(globalSortColumn, globalSortOrder);\n                }\n\n                updateStatistics();\n                lastUpdateTime = now;\n\n                // \u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c \u0438 \u043f\u043e\u0434\u0441\u0432\u0435\u0447\u0438\u0432\u0430\u0435\u043c \u0434\u0443\u0431\u043b\u0438\u043a\u0430\u0442\u044b\n                highlightDuplicates(response.duplicates);\n\n                // \u0421\u043a\u0440\u044b\u0432\u0430\u0435\u043c \u043e\u043a\u043d\u043e \u0441 \u043e\u0431\u0449\u0438\u043c \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e\u043c RPA \u0438 \u0432\u043e\u0441\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u043e\u043a\u043d\u0430\n                hideRPATotal();\n\n                resolve();\n            },\n            error: function(xhr, status, error) {\n                console.error('Error updating table:', error);\n                reject(error);\n            }\n        });\n    });\n}\nfunction initializeSparklines(activity) {\n    for (const [name, data] of Object.entries(activity)) {\n        const sparklineSpan = $(`#${name}-sparkline`);\n        sparklineSpan.sparkline(data, {\n            type: 'line',\n            width: '300px',  // \u0423\u0432\u0435\u043b\u0438\u0447\u0435\u043d\u043d\u0430\u044f \u0448\u0438\u0440\u0438\u043d\u0430\n            height: '50px',  // \u0422\u0430\u043a\u0436\u0435 \u043c\u043e\u0436\u043d\u043e \u0443\u0432\u0435\u043b\u0438\u0447\u0438\u0442\u044c \u0432\u044b\u0441\u043e\u0442\u0443 \u0434\u043b\u044f \u043b\u0443\u0447\u0448\u0435\u0439 \u0432\u0438\u0434\u0438\u043c\u043e\u0441\u0442\u0438\n            lineColor: 'green',\n            fillColor: 'transparent',\n            spotColor: 'red',          // \u041e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u043f\u0438\u043a\u043e\u0432\n            minSpotColor: 'blue',      // \u041c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u044b\u0435 \u043f\u0438\u043a\u0438\n            maxSpotColor: 'orange',    // \u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u044b\u0435 \u043f\u0438\u043a\u0438\n            highlightSpotColor: 'blue',\n            highlightLineColor: 'blue'\n        });\n        sparklineSpan.data('sparkline-initialized', true);\n    }\n}\n\nfunction updateSparklines(devices, activity) {\n    for (const [name, status] of Object.entries(devices)) {\n        const sparklineSpan = $(`#${name}-sparkline`);\n        const data = activity[name];\n\n        // Determine line color based on device status\n        let lineColor = 'green';  // Default color\n\n        if (status === 'processing') {\n            lineColor = 'green';  // Color for processing state\n        } else if (status === 'copying') {\n            lineColor = 'orange';\n        } else if (status === 'sending_number') {\n            lineColor = 'blue';\n        } else if (status === 'no_internet') {\n            lineColor = 'red';\n        }\n\n        // Check for impulse (e.g., value > 4)\n        const lastValue = data[data.length - 1];\n        if (lastValue > 4) {\n            lineColor = 'purple';  // Color for impulse\n        }\n\n        if (sparklineSpan.data('sparkline-initialized')) {\n            // Update existing Sparkline\n            sparklineSpan.sparkline(data, {\n                type: 'line',\n                width: '100%', \n                height: '20px', \n                lineColor: lineColor,\n                fillColor: 'transparent',\n                spotColor: 'red',\n                minSpotColor: 'blue',\n                maxSpotColor: 'orange',\n                highlightSpotColor: 'blue',\n                highlightLineColor: 'blue'\n            });\n        } else {\n            // Initialize Sparkline if not already\n            sparklineSpan.sparkline(data, {\n                type: 'line',\n                width: '100%', \n                height: '50px', \n                lineColor: lineColor,\n                fillColor: 'transparent',\n                spotColor: 'red',\n                minSpotColor: 'blue',\n                maxSpotColor: 'orange',\n                highlightSpotColor: 'blue',\n                highlightLineColor: 'blue'\n            });\n            sparklineSpan.data('sparkline-initialized', true);\n        }\n    }\n}\n\nfunction fetchDeviceStatuses() {\n    $.ajax({\n        url: '/get_device_status',\n        type: 'GET',\n        success: function(response) {\n            if (response.status === 'success') {\n                const devices = response.devices;\n                const activity = response.activity;\n\n                for (const [name, deviceInfo] of Object.entries(devices)) {\n                    const status = deviceInfo.status;\n\n                    // \u041e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 \u0441\u0442\u0430\u0442\u0443\u0441\u0430 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430\n                    const statusCircle = $(`#${name}-status`);\n                    const statusText = $(`#${name}-status-text`);\n                    statusCircle.removeClass('online offline no_internet copying sending_number processing');\n\n                    if (status === 'offline') {\n                        statusCircle.addClass('offline');\n                        statusText.text('\u041d\u0435\u0442 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f');\n                    } else if (status === 'no_internet') {\n                        statusCircle.addClass('no_internet');\n                        statusText.text('\u041d\u0435\u0442 \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442\u0430');\n                    } else if (status === 'copying') {\n                        statusCircle.addClass('copying');\n                        statusText.text('\u041a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435');\n                    } else if (status === 'sending_number') {\n                        statusCircle.addClass('sending_number');\n                        statusText.text('\u041e\u0442\u043f\u0440\u0430\u0432\u043a\u0430 \u043d\u043e\u043c\u0435\u0440\u0430');\n                    } else if (status === 'online') {\n                        statusCircle.addClass('online');\n                        statusText.text('\u041e\u043d\u043b\u0430\u0439\u043d');\n                    } else if (status === 'processing') {\n                        // \u0415\u0441\u043b\u0438 \u0432\u0441\u0435 \u0435\u0449\u0435 \u0435\u0441\u0442\u044c \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430, \u0434\u043b\u044f \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043d\u0443\u0436\u0435\u043d \u0441\u0442\u0430\u0442\u0443\u0441 'processing'\n                        statusCircle.addClass('processing');\n                        statusText.text('\u041e\u043d\u043b\u0430\u0439\u043d');\n                    }\n                }\n\n                // \u041e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 \u0441\u043f\u0430\u0440\u043a\u043b\u0430\u0439\u043d\u043e\u0432 \u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0441\u0442\u0438\n                updateSparklines(devices, activity);\n            }\n        },\n        error: function(error) {\n            console.error('\u041e\u0448\u0438\u0431\u043a\u0430 \u043f\u0440\u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0438 \u0441\u0442\u0430\u0442\u0443\u0441\u043e\u0432 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432:', error);\n        }\n    });\n}\n\n\nfunction highlightDuplicates(duplicates) {\n    // \u041e\u0447\u0438\u0449\u0430\u0435\u043c \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0438\u0435 \u0432\u044b\u0434\u0435\u043b\u0435\u043d\u0438\u044f\n    $('#tableBody td').removeClass('duplicate-highlight');\n\n    // \u041f\u043e\u0434\u0441\u0432\u0435\u0447\u0438\u0432\u0430\u0435\u043c \u0434\u0443\u0431\u043b\u0438\u043a\u0430\u0442\u044b \u043d\u043e\u043c\u0435\u0440\u043e\u0432\n    for (let number in duplicates.numbers) {\n        duplicates.numbers[number].forEach(index => {\n            $(`#tableBody tr:eq(${index}) td:nth-child(3)`).addClass('duplicate-highlight');\n        });\n    }\n\n    // \u041f\u043e\u0434\u0441\u0432\u0435\u0447\u0438\u0432\u0430\u0435\u043c \u0434\u0443\u0431\u043b\u0438\u043a\u0430\u0442\u044b \u0441\u0435\u0440\u0438\u0439\u043d\u044b\u0445 \u043d\u043e\u043c\u0435\u0440\u043e\u0432\n    for (let serial in duplicates.serials) {\n        duplicates.serials[serial].forEach(index => {\n            $(`#tableBody tr:eq(${index}) td:nth-child(4)`).addClass('duplicate-highlight');\n        });\n    }\n\n    // \u041f\u043e\u0434\u0441\u0432\u0435\u0447\u0438\u0432\u0430\u0435\u043c \u0434\u0443\u0431\u043b\u0438\u043a\u0430\u0442\u044b \"\u0413\u0440\u0430\u0444\u0430\" (dl_number)\n    for (let dl_number in duplicates.dl_numbers) {\n        duplicates.dl_numbers[dl_number].forEach(index => {\n            $(`#tableBody tr:eq(${index}) td:nth-child(5)`).addClass('duplicate-highlight');\n        });\n    }\n}\n\nfunction updateCell(cell, newValue, rowId, cellIndex, rowData) {\n    console.log(`Updating cell: index=${cellIndex}, value=${newValue}, rowId=${rowId}`);\n\n    const excludedArmaTypes = [\"CFA\", \"VND\", \"SRC\"];\n\n    if (cellIndex === 4) { // \u0421\u0442\u043e\u043b\u0431\u0435\u0446 \"\u0413\u0440\u0430\u0444\u0430\"\n        if (rowData.arma_type === 'RPA' && !excludedArmaTypes.includes(rowData.arma_type)) {\n            if (newValue && newValue.startsWith('DL')) {\n                cell.text(newValue)\n                    .addClass('clickable')\n                    .css('cursor', 'pointer')\n                    .off('click') // \u0423\u0434\u0430\u043b\u044f\u0435\u043c \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0438\u0435 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0438\n                    .on('click', function() {\n                        copyToClipboard(newValue);\n                        $(this).addClass('copied');\n                        setTimeout(() => {\n                            $(this).removeClass('copied');\n                        }, 200);\n                    });\n\n                // \u041e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u043c data-value\n                let numericValue = parseDL(newValue) || 0;\n                cell.attr('data-value', numericValue);\n            } else {\n                cell.html('<button class=\"generate-button\">\u0413\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c</button>')\n                    .find('button')\n                    .click(function() {\n                        generateDL(rowId);\n                    });\n\n                // \u041e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u043c data-value\n                cell.attr('data-value', 0);\n            }\n        } else if (!excludedArmaTypes.includes(rowData.arma_type)) {\n            if (newValue && newValue.startsWith('DL')) {\n                cell.text(newValue)\n                    .addClass('clickable')\n                    .css('cursor', 'pointer')\n                    .off('click')\n                    .on('click', function() {\n                        copyToClipboard(newValue);\n                        $(this).addClass('copied');\n                        setTimeout(() => {\n                            $(this).removeClass('copied');\n                        }, 200);\n                    });\n\n                // \u041e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u043c data-value\n                let numericValue = parseDL(newValue) || 0;\n                cell.attr('data-value', numericValue);\n            } else {\n                cell.text(newValue || '');\n                // \u041e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u043c data-value\n                let numericValue = parseDL(newValue) || 0;\n                cell.attr('data-value', numericValue);\n            }\n        } else {\n            cell.text(newValue || '');\n            // \u041e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u043c data-value\n            let numericValue = parseDL(newValue) || 0;\n            cell.attr('data-value', numericValue);\n        }\n    } else if (cellIndex === 6) { // \u0421\u0442\u043e\u043b\u0431\u0435\u0446 \"\u0412\u0440\u0435\u043c\u044f \u0443\u043f\u0430\u043a\u043e\u0432\u043a\u0438\"\n        const dlCell = cell.parent().find('td').eq(4);\n        const dlValue = dlCell.text().trim();\n        const armaType = rowData.arma_type;\n\n        if (dlValue.startsWith('DL') && !newValue && !excludedArmaTypes.includes(armaType)) {\n            cell.html('<button class=\"pack-button\">\u0423\u043f\u0430\u043a\u043e\u0432\u0430\u0442\u044c</button>')\n                .find('button')\n                .click(function() {\n                    packItem(rowId);\n                });\n        } else {\n            cell.text(newValue);\n        }\n    } else if (cellIndex === 7) { // \u0421\u0442\u043e\u043b\u0431\u0435\u0446 \"\u0422\u0438\u043f \u0410\u0420\u041c\u0410\"\n        if (!newValue || newValue.trim() === '') {\n            newValue = 'RPA';\n        }\n        cell.text(newValue)\n            .toggleClass('editable', true)\n            .attr('data-column', cellIndex);\n    } else {\n        cell.text(newValue)\n            .toggleClass('editable', cellIndex === 2 || cellIndex === 3)\n            .attr('data-column', cellIndex);\n    }\n}\n\nfunction sortTable(column, order) {\n    const rows = $('#tableBody > tr').get();\n\n    rows.sort(function(a, b) {\n        let A = $(a).children('td').eq(column).text().trim();\n        let B = $(b).children('td').eq(column).text().trim();\n\n        // \u041e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u043f\u0443\u0441\u0442\u044b\u0445 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439\n        if (A === '' && B === '') return 0;\n        if (A === '') return order === 'asc' ? 1 : -1;\n        if (B === '') return order === 'asc' ? -1 : 1;\n\n        // \u0421\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u0430\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u0434\u043b\u044f \u0441\u0442\u043e\u043b\u0431\u0446\u0430 \"\u0413\u0440\u0430\u0444\u0430\" (dl_number) \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c data-value\n        if (column === 4) { // \u0418\u043d\u0434\u0435\u043a\u0441 \u0441\u0442\u043e\u043b\u0431\u0446\u0430 \"\u0413\u0440\u0430\u0444\u0430\"\n            let numA = parseInt($(a).children('td').eq(column).attr('data-value')) || 0;\n            let numB = parseInt($(b).children('td').eq(column).attr('data-value')) || 0;\n\n            // \u041e\u0442\u043b\u0430\u0434\u043e\u0447\u043d\u044b\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f\n            console.log(`\u0421\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u043a\u0430 \u0413\u0440\u0430\u0444\u0430: numA = ${numA}; numB = ${numB}`);\n\n            return order === 'asc' ? numA - numB : numB - numA;\n        }\n\n        // \u041e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u0434\u0430\u0442 \u0438 \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u0434\u043b\u044f \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0445 \u0441\u0442\u043e\u043b\u0431\u0446\u043e\u0432\n        if (column === 1 || column === 6) {  // \u0421\u0442\u043e\u043b\u0431\u0446\u044b \"\u0412\u0440\u0435\u043c\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438\" \u0438 \"\u0412\u0440\u0435\u043c\u044f \u0443\u043f\u0430\u043a\u043e\u0432\u043a\u0438\"\n            let dateA = Date.parse(A);\n            let dateB = Date.parse(B);\n            if (isNaN(dateA)) dateA = 0;\n            if (isNaN(dateB)) dateB = 0;\n            return order === 'asc' ? dateA - dateB : dateB - dateA;\n        }\n\n        // \u041e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u0447\u0438\u0441\u043b\u043e\u0432\u044b\u0445 \u0441\u0442\u043e\u043b\u0431\u0446\u043e\u0432\n        if (column === 0 || column === 2) {  // \u0421\u0442\u043e\u043b\u0431\u0446\u044b \u0441 \u0447\u0438\u0441\u043b\u0430\u043c\u0438 (\u2116 \u0438 \u041d\u043e\u043c\u0435\u0440)\n            let numA = parseFloat(A) || 0;\n            let numB = parseFloat(B) || 0;\n            return order === 'asc' ? numA - numB : numB - numA;\n        }\n\n        // \u041e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u0441\u0442\u0440\u043e\u043a\u043e\u0432\u044b\u0445 \u0441\u0442\u043e\u043b\u0431\u0446\u043e\u0432\n        if (column === 5) {  // \u0421\u0442\u043e\u043b\u0431\u0435\u0446 \u0441 \u0438\u043c\u0435\u043d\u0435\u043c \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u0435\u043b\u044f\n            A = A.toLowerCase();\n            B = B.toLowerCase();\n        }\n\n        // \u0421\u0442\u0440\u043e\u043a\u043e\u0432\u043e\u0435 \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u0435 \u0434\u043b\u044f \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0445 \u0441\u0442\u043e\u043b\u0431\u0446\u043e\u0432\n        A = A.toUpperCase();\n        B = B.toUpperCase();\n        if (A < B) return order === 'asc' ? -1 : 1;\n        if (A > B) return order === 'asc' ? 1 : -1;\n        return 0;\n    });\n\n    // \u041e\u0447\u0438\u0441\u0442\u043a\u0430 \u0442\u0435\u043b\u0430 \u0442\u0430\u0431\u043b\u0438\u0446\u044b\n    $('#tableBody').empty();\n\n    // \u0414\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043e\u0442\u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0445 \u0441\u0442\u0440\u043e\u043a\n    $.each(rows, function(index, row) {\n        $('#tableBody').append(row);\n    });\n\n    checkDuplicates();\n    bindEventHandlers();\n}\n\nfunction parseDL(dl_number) {\n    if (typeof dl_number !== 'string') return null;\n    dl_number = dl_number.trim();\n    let match = dl_number.match(/^DL[-\\s]?(\\d+)$/i);\n    if (match && match[1]) {\n        return parseInt(match[1], 10);\n    }\n    return null;\n}\n\nfunction generateDL(rowId) {\n    console.log(`Generating DL for row ID ${rowId}`);\n    const selectedDate = getSelectedDate();\n    console.log(\"Selected date:\", selectedDate);\n\n    $.ajax({\n        url: '/generate_dl',\n        type: 'POST',\n        contentType: 'application/json',\n        data: JSON.stringify({\n            id: rowId,\n            date: selectedDate\n        }),\n        success: function(response) {\n            if (response.status === 'success') {\n                console.log('DL \u0443\u0441\u043f\u0435\u0448\u043d\u043e \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d:', response.dl_number);\n                var row = $(`#tableBody tr[data-id='${rowId}']`);\n                var dlCell = row.find('td:eq(4)');\n                var packCell = row.find('td:eq(6)'); // \u0421\u0442\u043e\u043b\u0431\u0435\u0446 \"\u0412\u0440\u0435\u043c\u044f \u0443\u043f\u0430\u043a\u043e\u0432\u043a\u0438\"\n                var armaType = row.find('td:eq(7)').text().trim();\n\n                dlCell.text(response.dl_number)\n                    .addClass('clickable')\n                    .css('cursor', 'pointer')\n                    .off('click') // \u0423\u0434\u0430\u043b\u044f\u0435\u043c \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0438\u0435 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0438\n                    .on('click', function() {\n                        copyToClipboard(response.dl_number);\n                        $(this).addClass('copied');\n                        setTimeout(() => {\n                            $(this).removeClass('copied');\n                        }, 200);\n                    });\n\n                // \u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u043a\u043d\u043e\u043f\u043a\u0443 \u0443\u043f\u0430\u043a\u043e\u0432\u043a\u0438 \u0442\u043e\u043b\u044c\u043a\u043e \u0435\u0441\u043b\u0438 arma_type \u043d\u0435 \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\n                const excludedArmaTypes = [\"CFA\", \"VND\", \"SRC\"];\n                if (!excludedArmaTypes.includes(armaType)) {\n                    packCell.html('<button class=\"pack-button\">\u0423\u043f\u0430\u043a\u043e\u0432\u0430\u0442\u044c</button>')\n                        .find('button')\n                        .click(function() {\n                            packItem(rowId);\n                        });\n                }\n\n                // \u041e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u043c \u043f\u043e\u043b\u0435 initial-dl \u0441 \u0442\u0435\u043a\u0443\u0449\u0438\u043c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435\u043c DL\n                loadCurrentDL();\n            } else {\n                alert('\u041e\u0448\u0438\u0431\u043a\u0430 \u043f\u0440\u0438 \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 DL: ' + response.message);\n            }\n        },\n        error: function(xhr, status, error) {\n            console.error('\u041e\u0448\u0438\u0431\u043a\u0430 \u043f\u0440\u0438 \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 DL:', status, error);\n            alert('\u041e\u0448\u0438\u0431\u043a\u0430 \u043f\u0440\u0438 \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 DL: ' + error);\n        }\n    });\n}\n\nfunction packItem(rowId) {\n    console.log(`\u0423\u043f\u0430\u043a\u043e\u0432\u043a\u0430 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430 \u0434\u043b\u044f \u0441\u0442\u0440\u043e\u043a\u0438 ID ${rowId}`);\n    const selectedDate = getSelectedDate();\n    console.log(\"Selected date:\", selectedDate);\n\n    $.ajax({\n        url: '/pack_item',\n        type: 'POST',\n        contentType: 'application/json',\n        data: JSON.stringify({\n            id: rowId,\n            date: selectedDate\n        }),\n        success: function(response) {\n            console.log(\"\u041e\u0442\u0432\u0435\u0442 \u0441\u0435\u0440\u0432\u0435\u0440\u0430:\", response);\n            if (response.status === 'success') {\n                var row = $(`#tableBody tr[data-id='${rowId}']`);\n                row.addClass('packed-row');\n                var cell = row.find('td:eq(6)'); // \u0421\u0442\u043e\u043b\u0431\u0435\u0446 \"\u0412\u0440\u0435\u043c\u044f \u0443\u043f\u0430\u043a\u043e\u0432\u043a\u0438\"\n                cell.text(response.pack_time);\n                updateStatistics();\n\n                // \u0423\u0434\u0430\u043b\u044f\u0435\u043c \u043a\u043d\u043e\u043f\u043a\u0443 \"\u0423\u043f\u0430\u043a\u043e\u0432\u0430\u0442\u044c\", \u0442\u0430\u043a \u043a\u0430\u043a \u0437\u0430\u043f\u0438\u0441\u044c \u0443\u0436\u0435 \u0443\u043f\u0430\u043a\u043e\u0432\u0430\u043d\u0430\n                cell.find('button.pack-button').remove();\n\n                // \u041e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u043c \u0433\u043e\u0434 \u0438 \u043c\u0435\u0441\u044f\u0446 \u0438\u0437 `selectedDate`\n                const [year, month, day] = selectedDate.split('-').map(Number);\n\n                // \u041f\u0440\u0438\u043d\u0443\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u043c \u043d\u0435\u0443\u043f\u0430\u043a\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u0434\u043d\u0438 \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043c\u0435\u0441\u044f\u0446\u0430\n                markUnpackedDays(year, month, true);\n            } else {\n                alert('\u041e\u0448\u0438\u0431\u043a\u0430 \u043f\u0440\u0438 \u0443\u043f\u0430\u043a\u043e\u0432\u043a\u0435: ' + response.message);\n            }\n        },\n        error: function(xhr, status, error) {\n            console.error(\"\u041e\u0448\u0438\u0431\u043a\u0430 AJAX:\", xhr, status, error);\n            alert('\u041e\u0448\u0438\u0431\u043a\u0430 \u043f\u0440\u0438 \u0443\u043f\u0430\u043a\u043e\u0432\u043a\u0435: ' + error);\n        }\n    });\n}\n\nfunction areSimilarNumbers(num1, num2) {\n    // \u041e\u0447\u0438\u0449\u0430\u0435\u043c \u0441\u0442\u0440\u043e\u043a\u0438 \u043e\u0442 \u043d\u0435\u0446\u0438\u0444\u0440\u043e\u0432\u044b\u0445 \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u0432 \u0438 \u043f\u0440\u043e\u0431\u0435\u043b\u043e\u0432\n    const clean1 = num1.toString().replace(/\\D/g, '').trim();\n    const clean2 = num2.toString().replace(/\\D/g, '').trim();\n    \n    // \u0415\u0441\u043b\u0438 \u0441\u0442\u0440\u043e\u043a\u0438 \u043f\u0443\u0441\u0442\u044b\u0435 \u0438\u043b\u0438 \u0440\u0430\u0437\u043d\u043e\u0439 \u0434\u043b\u0438\u043d\u044b - \u043d\u0435 \u0434\u0443\u0431\u043b\u0438\u043a\u0430\u0442\u044b\n    if (!clean1 || !clean2 || clean1.length !== clean2.length) {\n        return false;\n    }\n    \n    // \u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c \u043d\u0430 \u0442\u043e\u0447\u043d\u043e\u0435 \u0441\u043e\u0432\u043f\u0430\u0434\u0435\u043d\u0438\u0435\n    return clean1 === clean2;\n}\n\nfunction checkDuplicates() {\n    console.log(\"Checking for duplicates...\");\n    const rows = $('#tableBody tr');\n    \n    // \u041e\u0447\u0438\u0449\u0430\u0435\u043c \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0438\u0435 \u0432\u044b\u0434\u0435\u043b\u0435\u043d\u0438\u044f\n    rows.find('td').removeClass('duplicate-highlight');\n    \n    // \u0421\u043e\u0437\u0434\u0430\u0435\u043c \u043c\u0430\u0441\u0441\u0438\u0432\u044b \u0434\u043b\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u043d\u043e\u043c\u0435\u0440\u043e\u0432 \u0438 \u0438\u0445 \u0438\u043d\u0434\u0435\u043a\u0441\u043e\u0432\n    const numbers = new Map();\n    const dl_numbers = new Map();\n    const serials = new Map();\n    \n    // \u0421\u043e\u0431\u0438\u0440\u0430\u0435\u043c \u0432\u0441\u0435 \u043d\u043e\u043c\u0435\u0440\u0430 \u0438 \u0441\u0435\u0440\u0438\u0439\u043d\u044b\u0435 \u043d\u043e\u043c\u0435\u0440\u0430\n    rows.each(function(index) {\n        const number = $(this).find('td:nth-child(3)').text().trim();\n        const serial = $(this).find('td:nth-child(4)').text().trim();\n        const dl_number = $(this).find('td:nth-child(5)').text().trim();\n        \n        if (number) {\n            if (!numbers.has(number)) {\n                numbers.set(number, []);\n            }\n            numbers.get(number).push(index);\n        }\n\n        if (dl_number) {\n            if (!dl_numbers.has(dl_number)) {\n                dl_numbers.set(dl_number, []);\n            }\n            dl_numbers.get(dl_number).push(index);\n        }\n        \n        if (serial) {\n            if (!serials.has(serial)) {\n                serials.set(serial, []);\n            }\n            serials.get(serial).push(index);\n        }\n    });\n    \n    // \u041f\u043e\u0434\u0441\u0432\u0435\u0447\u0438\u0432\u0430\u0435\u043c \u0434\u0443\u0431\u043b\u0438\u043a\u0430\u0442\u044b\n    let duplicatesFound = false;\n    \n\n\n    dl_numbers.forEach((indices, dl_number) => {\n        if (dl_number.startsWith(\"DL\")) {\n            if (indices.length > 1) {\n                indices.forEach(index => {\n                    rows.eq(index).find('td:nth-child(5)').addClass('duplicate-highlight');\n                });\n                duplicatesFound = true;\n            }\n        }\n    });\n\n    // \u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c \u043d\u043e\u043c\u0435\u0440\u0430\n    numbers.forEach((indices, number) => {\n        if (indices.length > 1) {\n            indices.forEach(index => {\n                rows.eq(index).find('td:nth-child(3)').addClass('duplicate-highlight');\n            });\n            duplicatesFound = true;\n        }\n    });\n\n    // // \u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c \u0433\u0440\u0430\u0439\u0432\u0435\u0440\u0430\n    // dl_numbers.forEach((indices, dl_number) => {\n    //     if (indices.length > 1) {\n    //         indices.forEach(index => {\n    //             rows.eq(index).find('td:nth-child(5)').addClass('duplicate-highlight');\n    //         });\n    //         duplicatesFound = true;\n    //     }\n    // });\n    \n    // \u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c \u0441\u0435\u0440\u0438\u0439\u043d\u044b\u0435 \u043d\u043e\u043c\u0435\u0440\u0430\n    serials.forEach((indices, serial) => {\n        if (indices.length > 1) {\n            indices.forEach(index => {\n                rows.eq(index).find('td:nth-child(4)').addClass('duplicate-highlight');\n            });\n            duplicatesFound = true;\n        }\n    });\n\n    return duplicatesFound;\n}\n\nfunction appendNewRow(tableBody, rowData) {\n    console.log(\"\u0414\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043d\u043e\u0432\u043e\u0439 \u0441\u0442\u0440\u043e\u043a\u0438:\", rowData);\n\n    // \u0421\u043e\u0437\u0434\u0430\u0435\u043c \u044d\u043b\u0435\u043c\u0435\u043d\u0442 \u0441\u0442\u0440\u043e\u043a\u0438 \u0438 \u043f\u0440\u0438\u0441\u0432\u0430\u0438\u0432\u0430\u0435\u043c \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u044b\u0439 data-id\n    var tr = $('<tr>').attr('data-id', rowData.id);\n\n    // \u0415\u0441\u043b\u0438 \u0435\u0441\u0442\u044c \u0432\u0440\u0435\u043c\u044f \u0443\u043f\u0430\u043a\u043e\u0432\u043a\u0438 \u0438 \u044d\u0442\u043e \u043d\u0435 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a, \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u043a\u043b\u0430\u0441\u0441 'packed-row'\n    if (rowData.pack_time && rowData.pack_time !== \"\u0412\u0440\u0435\u043c\u044f \u0443\u043f\u0430\u043a\u043e\u0432\u043a\u0438\") {\n        tr.addClass('packed-row');\n    }\n\n    // \u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u044f\u0447\u0435\u0439\u043a\u0438 \u0432 \u0441\u0442\u0440\u043e\u043a\u0443\n    tr.append($('<td>').text(rowData.row_number));\n    tr.append($('<td>').text(rowData.timestamp));\n\n    // \u0421\u0442\u043e\u043b\u0431\u0435\u0446 \"\u041d\u043e\u043c\u0435\u0440\" (\u0422\u0440\u0435\u0442\u0438\u0439 \u0441\u0442\u043e\u043b\u0431\u0435\u0446, \u0438\u043d\u0434\u0435\u043a\u0441 2)\n    var numberCell = $('<td>')\n        .text(rowData.number)\n        .addClass('editable') // \u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u043a\u043b\u0430\u0441\u0441 \u0434\u043b\u044f \u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f\n        .attr('data-column', '2'); // \u0423\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c \u0438\u043d\u0434\u0435\u043a\u0441 \u0441\u0442\u043e\u043b\u0431\u0446\u0430\n    tr.append(numberCell);\n\n    tr.append($('<td>').text(rowData.serial));\n\n    // \u0421\u0442\u043e\u043b\u0431\u0435\u0446 \"\u0413\u0440\u0430\u0444\u0430\" (\u041f\u044f\u0442\u044b\u0439 \u0441\u0442\u043e\u043b\u0431\u0435\u0446, \u0438\u043d\u0434\u0435\u043a\u0441 4)\n    var dlCell = $('<td>')\n        .text(rowData.dl_number || '')\n        .addClass('editable') // \u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u043a\u043b\u0430\u0441\u0441 \u0434\u043b\u044f \u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f\n        .attr('data-column', '4'); // \u0423\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c \u0438\u043d\u0434\u0435\u043a\u0441 \u0441\u0442\u043e\u043b\u0431\u0446\u0430 \"\u0413\u0440\u0430\u0444\u0430\"\n    tr.append(dlCell);\n    \n    // \u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c data-value\n    var numericValue = parseDL(rowData.dl_number) || 0;\n    dlCell.attr('data-value', numericValue);\n\n    // \u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0438 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043a\u043d\u043e\u043f\u043e\u043a \u0438\u043b\u0438 \u043a\u043b\u0438\u043a\u0430\u0431\u0435\u043b\u044c\u043d\u043e\u0433\u043e \u0442\u0435\u043a\u0441\u0442\u0430 \u0434\u043b\u044f \"\u0413\u0440\u0430\u0444\u0430\"\n    const excludedArmaTypes = [\"CFA\", \"VND\", \"SRC\"];\n\n    if (rowData.arma_type === 'RPA' && !excludedArmaTypes.includes(rowData.arma_type)) {\n        // \u0414\u043b\u044f \u0442\u0438\u043f\u0430 \u0410\u0420\u041c\u0410 'RPA', \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c \u043d\u0430\u043b\u0438\u0447\u0438\u0435 \u0438 \u0444\u043e\u0440\u043c\u0430\u0442 dl_number\n        if (!rowData.dl_number || !rowData.dl_number.startsWith('DL')) {\n            // \u0415\u0441\u043b\u0438 dl_number \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u0438\u043b\u0438 \u043d\u0435 \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442\u0441\u044f \u0441 'DL', \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0435\u043c \u043a\u043d\u043e\u043f\u043a\u0443 \"\u0413\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c\"\n            dlCell.html('<button class=\"generate-button\">\u0413\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c</button>')\n                .find('button')\n                .click(function() {\n                    generateDL(rowData.id); // \u041f\u0435\u0440\u0435\u0434\u0430\u0435\u043c \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u044b\u0439 ID \u0441\u0442\u0440\u043e\u043a\u0438\n                });\n        } else {\n            // \u0415\u0441\u043b\u0438 dl_number \u043f\u0440\u0438\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u0438 \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442\u0441\u044f \u0441 'DL', \u0434\u0435\u043b\u0430\u0435\u043c \u0435\u0433\u043e \u043a\u043b\u0438\u043a\u0430\u0431\u0435\u043b\u044c\u043d\u044b\u043c \u0434\u043b\u044f \u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f\n            dlCell.text(rowData.dl_number)\n                .addClass('clickable')\n                .css('cursor', 'pointer')\n                .on('click', function() {\n                    copyToClipboard(rowData.dl_number);\n                    $(this).addClass('copied');\n                    setTimeout(() => {\n                        $(this).removeClass('copied');\n                    }, 200);\n                });\n        }\n    } else if (!excludedArmaTypes.includes(rowData.arma_type)) {\n        // \u0414\u043b\u044f \u0434\u0440\u0443\u0433\u0438\u0445 \u0442\u0438\u043f\u043e\u0432 \u0410\u0420\u041c\u0410, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0435 \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u044b, \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0435\u043c \u0438\u043b\u0438 \u0441\u043a\u0440\u044b\u0432\u0430\u0435\u043c \u043a\u043d\u043e\u043f\u043a\u0443\n        if (rowData.dl_number && rowData.dl_number.startsWith('DL')) {\n            dlCell.text(rowData.dl_number)\n                .addClass('clickable')\n                .css('cursor', 'pointer')\n                .on('click', function() {\n                    copyToClipboard(rowData.dl_number);\n                    $(this).addClass('copied');\n                    setTimeout(() => {\n                        $(this).removeClass('copied');\n                    }, 200);\n                });\n        } else {\n            dlCell.text(rowData.dl_number || '');\n        }\n    } else {\n        // \u0414\u043b\u044f \u0442\u0438\u043f\u043e\u0432 \u0410\u0420\u041c\u0410 \"CFA\", \"VND\", \"SRC\" \u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c \u044f\u0447\u0435\u0439\u043a\u0443 \u043f\u0443\u0441\u0442\u043e\u0439 \u0438\u043b\u0438 \u0441 \u0442\u0435\u043a\u0443\u0449\u0438\u043c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435\u043c\n        dlCell.text(rowData.dl_number || '');\n    }\n\n    // \u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u044f\u0447\u0435\u0439\u043a\u0443 \u0441 \u0438\u043c\u0435\u043d\u0435\u043c \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u0435\u043b\u044f\n    tr.append($('<td>').text(rowData.worker_name));\n\n    /**\n     * \u041e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u044f\u0447\u0435\u0439\u043a\u0438 \"\u0412\u0440\u0435\u043c\u044f \u0443\u043f\u0430\u043a\u043e\u0432\u043a\u0438\" (pack_time)\n     */\n    var packCell = $('<td>');\n\n    if (rowData.dl_number && rowData.dl_number.startsWith('DL') && !rowData.pack_time && !excludedArmaTypes.includes(rowData.arma_type)) {\n        // \u0415\u0441\u043b\u0438 dl_number \u0441 'DL', pack_time \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u0438 arma_type \u043d\u0435 \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d, \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c \u043a\u043d\u043e\u043f\u043a\u0443 \"\u0423\u043f\u0430\u043a\u043e\u0432\u0430\u0442\u044c\"\n        packCell.html('<button class=\"pack-button\">\u0423\u043f\u0430\u043a\u043e\u0432\u0430\u0442\u044c</button>')\n            .find('button')\n            .click(function() {\n                packItem(rowData.id); // \u041f\u0435\u0440\u0435\u0434\u0430\u0435\u043c \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u044b\u0439 ID \u0441\u0442\u0440\u043e\u043a\u0438\n            });\n    } else {\n        // \u0418\u043d\u0430\u0447\u0435 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0435\u043c \u0432\u0440\u0435\u043c\u044f \u0443\u043f\u0430\u043a\u043e\u0432\u043a\u0438 \u0438\u043b\u0438 \u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c \u043f\u0443\u0441\u0442\u044b\u043c\n        packCell.text(rowData.pack_time || '');\n    }\n\n    tr.append(packCell);\n\n    // \u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u044f\u0447\u0435\u0439\u043a\u0443 \u0441 \u0442\u0438\u043f\u043e\u043c \u0410\u0420\u041c\u0410\n    tr.append($('<td>').text(rowData.arma_type || ''));\n\n    tr.append($('<td>').text(rowData.dateshipment));  \n    tr.append($('<td>').text(rowData.aktshipment)); \n    tr.append($('<td>').text(rowData.bad_recovery)); \n   \n    /**\n     * \u0414\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u044f\u0447\u0435\u0439\u043a\u0438 \"\u0414\u0435\u0439\u0441\u0442\u0432\u0438\u0435\" \u0441 \u043a\u043d\u043e\u043f\u043a\u043e\u0439 \"\u0423\u0434\u0430\u043b\u0438\u0442\u044c\"\n     */\n    var actionTd = $('<td>')\n    var deleteButton = $('<button>').text('\u0423\u0434\u0430\u043b\u0438\u0442\u044c').addClass('delete-button btn btn-danger btn-sm')\n    deleteButton.click(function() {\n        initiateDeleteConfirmation(rowData.id); // \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u043d\u043e\u0432\u0443\u044e \u0444\u0443\u043d\u043a\u0446\u0438\u044e\n    });\n    actionTd.append(deleteButton);\n    tr.append(actionTd);\n\n    // \u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0441\u0442\u0440\u043e\u043a\u0443 \u0432 \u0442\u0435\u043b\u043e \u0442\u0430\u0431\u043b\u0438\u0446\u044b\n    tableBody.append(tr);\n\n    /**\n     * \u0414\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u0430\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u043f\u043e\u0441\u043b\u0435 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0441\u0442\u0440\u043e\u043a\u0438\n     */\n    setTimeout(() => {\n        const dlValue = dlCell.text().trim();\n        const packValue = packCell.text().trim();\n\n        if (dlValue.startsWith('DL') && !packValue && !excludedArmaTypes.includes(rowData.arma_type)) {\n            console.log('\u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u043a\u043d\u043e\u043f\u043a\u0443 \u0443\u043f\u0430\u043a\u043e\u0432\u043a\u0438 \u0434\u043b\u044f DL:', dlValue);\n            packCell.html('<button class=\"pack-button\">\u0423\u043f\u0430\u043a\u043e\u0432\u0430\u0442\u044c</button>')\n                .find('button')\n                .click(function() {\n                    packItem(rowData.id); // \u041f\u0435\u0440\u0435\u0434\u0430\u0435\u043c \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u044b\u0439 ID \u0441\u0442\u0440\u043e\u043a\u0438\n                });\n        }\n\n        // \u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c \u0434\u0443\u0431\u043b\u0438\u043a\u0430\u0442\u044b \u043f\u043e\u0441\u043b\u0435 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043d\u043e\u0432\u043e\u0439 \u0441\u0442\u0440\u043e\u043a\u0438\n        checkDuplicates();\n    }, 100);\n}\n\n\nfunction bindEventHandlers() {\n    // \u041f\u0440\u0438\u0432\u044f\u0437\u043a\u0430 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430 \u0434\u043b\u044f \u043a\u043d\u043e\u043f\u043a\u0438 \"\u0413\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c\"\n    $('.generate-button').off('click').on('click', function() {\n        var rowId = $(this).closest('tr').data('id');\n        generateDL(rowId);\n    });\n\n    // \u041f\u0440\u0438\u0432\u044f\u0437\u043a\u0430 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430 \u0434\u043b\u044f \u043a\u043d\u043e\u043f\u043a\u0438 \"\u0423\u043f\u0430\u043a\u043e\u0432\u0430\u0442\u044c\"\n    $('.pack-button').off('click').on('click', function() {\n        var rowId = $(this).closest('tr').data('id');\n        packItem(rowId);\n    });\n\n    // \u041f\u0440\u0438\u0432\u044f\u0437\u043a\u0430 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430 \u0434\u043b\u044f \u043a\u043d\u043e\u043f\u043a\u0438 \"\u0423\u0434\u0430\u043b\u0438\u0442\u044c\"\n    $('.delete-button').off('click').on('click', function() {\n        var rowId = $(this).closest('tr').data('id');\n        initiateDeleteConfirmation(rowId);\n    });\n}\n\nfunction updateTableContent(data, tableBody, highlightNew = false) {\n    tableBody.empty();  // \u041e\u0447\u0438\u0449\u0430\u0435\u043c \u0442\u0435\u043a\u0443\u0449\u0435\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435 \u0442\u0430\u0431\u043b\u0438\u0446\u044b\n    data.forEach(function(rowData) {\n        appendNewRow(tableBody, rowData);\n    });\n    checkDuplicates();\n    bindEventHandlers();  // \u041f\u0440\u0438\u0432\u044f\u0437\u044b\u0432\u0430\u0435\u043c \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0438 \u043f\u043e\u0441\u043b\u0435 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u0442\u0430\u0431\u043b\u0438\u0446\u044b\n}\n\nfunction scheduleNextUpdate() {\n    setTimeout(() => {\n        if (!isEditing) {\n            updateTable(false, false).then(() => {\n                scheduleNextUpdate();\n            });\n        } else {\n            scheduleNextUpdate();\n        }\n    }, 3000);\n}\n\nfunction initializeEventSource() {\n    if (eventSource) {\n        eventSource.close();\n    }\n\n    eventSource = new EventSource('/stream');\n\n    eventSource.onmessage = function(event) {\n        const data = JSON.parse(event.data);\n        if (data.type === 'update' && data.date === getSelectedDate()) {\n            // \u041e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u043c \u0442\u0430\u0431\u043b\u0438\u0446\u0443\n            updateTable(true).then(() => {\n                // \u041f\u043e\u0441\u043b\u0435 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u0442\u0430\u0431\u043b\u0438\u0446\u044b, \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u043c \u043f\u043e\u0434\u0441\u0432\u0435\u0442\u043a\u0443 \u0434\u043d\u0435\u0439\n                const currentDate = new Date(fpInstance.selectedDates[0]);\n                markUnpackedDays(currentDate.getFullYear(), currentDate.getMonth() + 1);\n                fetchDeviceStatuses();\n            });\n        }\n    };\n\n    eventSource.onerror = function(error) {\n        console.error('EventSource failed:', error);\n        eventSource.close();\n        setTimeout(initializeEventSource, 5000);  // \u041f\u043e\u043f\u044b\u0442\u043a\u0430 \u043f\u0435\u0440\u0435\u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u0447\u0435\u0440\u0435\u0437 5 \u0441\u0435\u043a\u0443\u043d\u0434\n    };\n}\n\n// \u041e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0438 \u0441\u043e\u0431\u044b\u0442\u0438\u0439 \u0434\u043b\u044f \u0442\u0430\u0431\u043b\u0438\u0446\u044b\n$(document).ready(function() {\n    updateTable();\n    updateStatistics(); // \u0423\u0431\u0435\u0434\u0438\u0442\u0435\u0441\u044c, \u0447\u0442\u043e \u044d\u0442\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0430\n    initializeEventSource();\n    scheduleNextUpdate();\n    fetchDeviceStatuses();\n    loadCurrentDL();\n    // \u041e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u043a\u0438\n    $('.sortable').click(function() {\n        const column = $(this).data('column');\n        const order = $(this).hasClass('asc') ? 'desc' : 'asc';\n        \n        // \u0423\u0434\u0430\u043b\u044f\u0435\u043c \u043a\u043b\u0430\u0441\u0441\u044b \u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u043a\u0438 \u0441\u043e \u0432\u0441\u0435\u0445 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u043e\u0432\n        $('.sortable').removeClass('asc desc');\n        // \u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u043a\u043b\u0430\u0441\u0441 \u0442\u0435\u043a\u0443\u0449\u0435\u0439 \u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u043a\u0438\n        $(this).addClass(order);\n        \n        // \u0421\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u043c \u0442\u0435\u043a\u0443\u0449\u0438\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u043a\u0438\n        globalSortColumn = column;\n        globalSortOrder = order;\n        \n        // \u0421\u043e\u0440\u0442\u0438\u0440\u0443\u0435\u043c \u0442\u0430\u0431\u043b\u0438\u0446\u0443\n        sortTable(column, order);\n    });\n\n    // \u041e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u043f\u043e\u0438\u0441\u043a\u0430\n    $('#searchButton').click(function() {\n        searchNumber();\n    });\n    $('#searchInput').keypress(function(e) {\n        if (e.which === 13) {\n            searchNumber();\n        }\n    });\n    $('#armaFilter').on('change', function() {\n        updateTable();\n    });\n});\n\n// \u041e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0434\u0430\u0442\u044b\n$('#datepicker').on('change', function() {\n    initializeEventSource();\n    updateTable();\n});\n\n$(document).ready(function() {\n    $('.export-button').on('click', function(e) {\n        e.preventDefault();\n\n        const selectedDate = getSelectedDate();\n        const exportAllRPA = $('#showRPAButton').is(':checked');\n\n        const url = `/export_excel?date=${selectedDate}&export_all_rpa=${exportAllRPA}`;\n\n        fetch(url)\n            .then(response => {\n                if (response.ok) {\n                    return response.blob();\n                }\n                throw new Error('Network response was not ok.');\n            })\n            .then(blob => {\n                const url = window.URL.createObjectURL(blob);\n                const a = document.createElement('a');\n                a.href = url;\n                a.download = exportAllRPA ? 'RPA_export.xlsx' : `export_${selectedDate}.xlsx`;\n                document.body.appendChild(a);\n                a.click();\n                window.URL.revokeObjectURL(url);\n                a.remove();\n            })\n            .catch(error => {\n                console.error('Error:', error);\n                alert('\u041e\u0448\u0438\u0431\u043a\u0430 \u043f\u0440\u0438 \u044d\u043a\u0441\u043f\u043e\u0440\u0442\u0435 \u0444\u0430\u0439\u043b\u0430');\n            });\n    });\n});\n$(document).ready(function() {\n    fpInstance = flatpickr(\"#datepicker\", {\n        locale: \"ru\",\n        dateFormat: \"Y-m-d\",\n        defaultDate: \"today\",\n        onChange: function(selectedDates, dateStr, instance) {\n            updateTable();\n            const selected = selectedDates[0];\n            if (selected) {\n                markUnpackedDays(selected.getFullYear(), selected.getMonth() + 1);\n            }\n        },\n        onMonthChange: function(selectedDates, dateStr, instance) {\n            const selected = instance.currentYear && instance.currentMonth !== undefined\n                ? new Date(instance.currentYear, instance.currentMonth, 1)\n                : new Date();\n            markUnpackedDays(selected.getFullYear(), selected.getMonth() + 1);\n        },\n        onDayCreate: function(dObj, dStr, fp, dayElem) {\n            const year = dayElem.dateObj.getFullYear();\n            const month = dayElem.dateObj.getMonth() + 1; // getMonth() \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 0-11\n            const day = dayElem.dateObj.getDate();\n            const key = `${year}-${String(month).padStart(2, '0')}`;\n            \n            if (unpackedDaysCache[key] && unpackedDaysCache[key].has(day)) {\n                dayElem.style.backgroundColor = 'lightcoral';\n                dayElem.style.color = 'white';\n            } else {\n                // \u0421\u0431\u0440\u043e\u0441 \u0441\u0442\u0438\u043b\u0435\u0439 \u0434\u043b\u044f \u0434\u0440\u0443\u0433\u0438\u0445 \u0434\u043d\u0435\u0439\n                dayElem.style.backgroundColor = '';\n                dayElem.style.color = '';\n            }\n        }\n    });\n\n    // \u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0435\u043c \u0434\u043b\u044f \u0442\u0435\u043a\u0443\u0449\u0435\u0433\u043e \u043c\u0435\u0441\u044f\u0446\u0430\n    const today = new Date();\n    markUnpackedDays(today.getFullYear(), today.getMonth() + 1);\n\n    initializeEventSource();\n    updateTable();\n    updateStatistics();\n    fetchDeviceStatuses();\n    setInterval(fetchDeviceStatuses, 1000); // \u0418\u043d\u0442\u0435\u0440\u0432\u0430\u043b 1 \u0441\u0435\u043a\u0443\u043d\u0434\u0443 (\u0441\u043a\u043e\u0440\u0440\u0435\u043a\u0442\u0438\u0440\u0443\u0439\u0442\u0435 \u043f\u0440\u0438 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438)\n});\n\n\n// \u041e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u0434\u0432\u043e\u0439\u043d\u043e\u0433\u043e \u043a\u043b\u0438\u043a\u0430 \u0434\u043b\u044f \u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u044f\u0447\u0435\u0435\u043a\n$(document).on('dblclick', '.editable', function() {\n    if (isEditing) return; // \u041f\u0440\u0435\u0434\u043e\u0442\u0432\u0440\u0430\u0449\u0430\u0435\u043c \u043c\u043d\u043e\u0433\u043e\u043a\u0440\u0430\u0442\u043d\u043e\u0435 \u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435\n    isEditing = true;\n\n    var td = $(this);\n    var currentValue = td.text();\n    var input = $('<input type=\"text\">')\n        .val(currentValue)\n        .addClass('edit-input');\n\n    td.html(input);\n    input.focus();\n\n    input.on('blur', function() {\n        var newValue = $(this).val().trim();\n        var rowId = td.closest('tr').data('id');\n        var columnIndex = td.attr('data-column');\n\n        // \u041e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u043c URL \u0434\u043b\u044f \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u0432 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u0441\u0442\u043e\u043b\u0431\u0446\u0430\n        let url;\n        let updateData = {\n            id: rowId,\n            new_value: newValue,\n            date: getSelectedDate()\n        };\n\n        if (columnIndex === '2') { // \u0421\u0442\u043e\u043b\u0431\u0435\u0446 \"\u041d\u043e\u043c\u0435\u0440\"\n            url = '/update_number';\n        } else if (columnIndex === '4') { // \u0421\u0442\u043e\u043b\u0431\u0435\u0446 \"\u0413\u0440\u0430\u0444\u0430\"\n            url = '/update_graf';\n        } else {\n            alert('\u041d\u0435\u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u043c\u044b\u0439 \u0441\u0442\u043e\u043b\u0431\u0435\u0446 \u0434\u043b\u044f \u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f');\n            td.text(currentValue);\n            isEditing = false;\n            return;\n        }\n\n        $.ajax({\n            url: url,\n            type: 'POST',\n            contentType: 'application/json',\n            data: JSON.stringify(updateData),\n            success: function(response) {\n                if (response.status === 'success') {\n                    td.text(newValue);\n                    checkDuplicates();\n                } else {\n                    alert('\u041e\u0448\u0438\u0431\u043a\u0430 \u043f\u0440\u0438 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f: ' + response.message);\n                    td.text(currentValue);\n                }\n                isEditing = false;\n            },\n            error: function(xhr, status, error) {\n                alert('\u041e\u0448\u0438\u0431\u043a\u0430 \u043f\u0440\u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0435 \u0434\u0430\u043d\u043d\u044b\u0445: ' + error);\n                td.text(currentValue);\n                isEditing = false;\n            }\n        });\n    });\n\n    input.on('keypress', function(e) {\n        if (e.which === 13) { // \u041d\u0430\u0436\u0430\u0442\u0438\u0435 Enter\n            $(this).blur();\n        }\n    });\n\n    input.on('keydown', function(e) {\n        if (e.key === 'Escape') { // \u041d\u0430\u0436\u0430\u0442\u0438\u0435 Esc\n            td.text(currentValue);\n            isEditing = false;\n        }\n    });\n});\n\nfunction searchNumber() {\n    const searchValue = $('#searchInput').val().trim();\n    if (!searchValue) return;\n\n    // \u0423\u0434\u0430\u043b\u044f\u0435\u043c \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0443\u044e \u043f\u043e\u0434\u0441\u0432\u0435\u0442\u043a\u0443\n    $('.highlight-search').removeClass('highlight-search');\n\n    const rows = $('#tableBody tr');\n    let found = false;\n\n    rows.each(function() {\n        const numberCell = $(this).find('td:nth-child(3)');\n        const cellText = numberCell.text().trim();\n        if (cellText === searchValue) {\n            numberCell.addClass('highlight-search');\n            \n            // \u041f\u0440\u043e\u043a\u0440\u0443\u0442\u043a\u0430 \u043a \u043d\u0430\u0439\u0434\u0435\u043d\u043d\u043e\u0439 \u0441\u0442\u0440\u043e\u043a\u0435\n            $('.table-container').animate({\n                scrollTop: $(this).offset().top - $('.table-container').offset().top + $('.table-container').scrollTop() - 100\n            }, 500);\n\n            found = true;\n\n            // \u0423\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c \u0442\u0430\u0439\u043c\u0435\u0440 \u043d\u0430 \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u0435 \u043f\u043e\u0434\u0441\u0432\u0435\u0442\u043a\u0438 \u0447\u0435\u0440\u0435\u0437 3 \u0441\u0435\u043a\u0443\u043d\u0434\u044b\n            setTimeout(() => {\n                numberCell.removeClass('highlight-search');\n            }, 3000);\n\n            // \u0412\u044b\u0432\u043e\u0434\u0438\u043c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u0432 \u043a\u043e\u043d\u0441\u043e\u043b\u044c \u0434\u043b\u044f \u043e\u0442\u043b\u0430\u0434\u043a\u0438\n            console.log('\u041d\u0430\u0439\u0434\u0435\u043d\u043e \u0441\u043e\u0432\u043f\u0430\u0434\u0435\u043d\u0438\u0435:', cellText);\n\n            return false; // \u041f\u0440\u0435\u0440\u044b\u0432\u0430\u0435\u043c \u0446\u0438\u043a\u043b, \u0442\u0430\u043a \u043a\u0430\u043a \u043d\u0430\u0448\u043b\u0438 \u043d\u0443\u0436\u043d\u0443\u044e \u0441\u0442\u0440\u043e\u043a\u0443\n        }\n    });\n\n    if (!found) {\n        alert('\u0422\u043e\u0447\u043d\u043e\u0435 \u0441\u043e\u0432\u043f\u0430\u0434\u0435\u043d\u0438\u0435 \u043d\u043e\u043c\u0435\u0440\u0430 \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d\u043e');\n    }\n}\n\nfunction initiateDeleteConfirmation(rowId) {\n    isDeleting = true; // \u0423\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c \u0444\u043b\u0430\u0433 \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u044f \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u044f\n    var deleteCell = $(`tr[data-id='${rowId}'] td:last-child`);\n\n    // \u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c, \u043d\u0435 \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u043b\u0438 \u0443\u0436\u0435 \u0432 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0438 \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u044f\n    if (deleteCell.data('confirming')) {\n        return; // \u0415\u0441\u043b\u0438 \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u0435 \u0443\u0436\u0435 \u0437\u0430\u043f\u0440\u043e\u0448\u0435\u043d\u043e, \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u0434\u0435\u043b\u0430\u0435\u043c\n    }\n\n    // \u0423\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c \u0444\u043b\u0430\u0433 \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u044f\n    deleteCell.data('confirming', true);\n\n    // \u0421\u043e\u0437\u0434\u0430\u0435\u043c \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440 \u0434\u043b\u044f \u043a\u043d\u043e\u043f\u043e\u043a \"\u0414\u0430\" \u0438 \"\u041d\u0435\u0442\"\n    var buttonsContainer = $('<div>').addClass('confirm-buttons');\n\n    var yesButton = $('<button>')\n        .text('\u0414\u0430')\n        .addClass('confirm-yes-button btn btn-success btn-sm me-2')\n        .click(function() {\n            deleteConfirmed(rowId);\n        });\n\n    var noButton = $('<button>')\n        .text('\u041d\u0435\u0442')\n        .addClass('confirm-no-button btn btn-secondary btn-sm')\n        .click(function() {\n            cancelDeleteConfirmation(rowId);\n        });\n\n    buttonsContainer.append(yesButton);\n    buttonsContainer.append(noButton);\n\n    // \u0417\u0430\u043c\u0435\u043d\u044f\u0435\u043c \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435 \u044f\u0447\u0435\u0439\u043a\u0438 \u043d\u0430 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440 \u0441 \u043a\u043d\u043e\u043f\u043a\u0430\u043c\u0438\n    deleteCell.empty();\n    deleteCell.append(buttonsContainer);\n}\n\nfunction deleteConfirmed(rowId) {\n    $.ajax({\n        url: '/delete_row',\n        type: 'POST',\n        contentType: 'application/json',\n        data: JSON.stringify({ id: rowId }),\n        success: function(response) {\n            if (response.status === 'success') {\n                // \u0423\u0434\u0430\u043b\u044f\u0435\u043c \u0441\u0442\u0440\u043e\u043a\u0443 \u0438\u0437 \u0442\u0430\u0431\u043b\u0438\u0446\u044b\n                $(`tr[data-id='${rowId}']`).remove();\n                console.log(`Row with ID ${rowId} deleted successfully.`);\n\n                // \u041e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u043c \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0443 \u043f\u043e\u0441\u043b\u0435 \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u044f \u0437\u0430\u043f\u0438\u0441\u0438\n                updateStatistics();\n\n                // \u041e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u043c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 DL \u043d\u0430 \u043a\u043b\u0438\u0435\u043d\u0442\u0435\n                loadCurrentDL();\n            } else {\n                console.error('\u041e\u0448\u0438\u0431\u043a\u0430 \u043f\u0440\u0438 \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u0438 \u0437\u0430\u043f\u0438\u0441\u0438:', response.message);\n                // \u041c\u043e\u0436\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e \u043e \u043d\u0435\u0443\u0434\u0430\u0447\u0435\n            }\n            // \u0412\u043e\u0441\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c \u043a\u043d\u043e\u043f\u043a\u0443 \"\u0423\u0434\u0430\u043b\u0438\u0442\u044c\" \u0438 \u0441\u0431\u0440\u0430\u0441\u044b\u0432\u0430\u0435\u043c \u0444\u043b\u0430\u0433\n            cancelDeleteConfirmation(rowId);\n        },\n        error: function(xhr, status, error) {\n            console.error('\u041f\u0440\u043e\u0438\u0437\u043e\u0448\u043b\u0430 \u043e\u0448\u0438\u0431\u043a\u0430 \u043f\u0440\u0438 \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u0438 \u0437\u0430\u043f\u0438\u0441\u0438:', error);\n            // \u041c\u043e\u0436\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e \u043e \u043d\u0435\u0443\u0434\u0430\u0447\u0435\n            // \u0412\u043e\u0441\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c \u043a\u043d\u043e\u043f\u043a\u0443 \"\u0423\u0434\u0430\u043b\u0438\u0442\u044c\" \u0438 \u0441\u0431\u0440\u0430\u0441\u044b\u0432\u0430\u0435\u043c \u0444\u043b\u0430\u0433\n            cancelDeleteConfirmation(rowId);\n        }\n    });\n}\n\nfunction cancelDeleteConfirmation(rowId) {\n    var deleteCell = $(`tr[data-id='${rowId}'] td:last-child`);\n    // \u0421\u0431\u0440\u0430\u0441\u044b\u0432\u0430\u0435\u043c \u0444\u043b\u0430\u0433 \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u044f\n    deleteCell.data('confirming', false);\n    // \u0412\u043e\u0441\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c \u043a\u043d\u043e\u043f\u043a\u0443 \"\u0423\u0434\u0430\u043b\u0438\u0442\u044c\"\n    deleteCell.empty();\n    var deleteButton = $('<button>')\n        .text('\u0423\u0434\u0430\u043b\u0438\u0442\u044c')\n        .addClass('delete-button btn btn-danger btn-sm')\n        .click(function() {\n            initiateDeleteConfirmation(rowId);\n        });\n    deleteCell.append(deleteButton);\n\n    isDeleting = false; // \u0421\u0431\u0440\u0430\u0441\u044b\u0432\u0430\u0435\u043c \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u044b\u0439 \u0444\u043b\u0430\u0433\n}\n\nfunction loadCurrentDL() {\n    const selectedDate = getSelectedDate();\n    $.ajax({\n        url: '/get_current_dl',\n        type: 'GET',\n        data: { date: selectedDate },\n        success: function(response) {\n            if (response.status === 'success') {\n                $('#initial-dl').val(response.current_dl);\n            } else {\n                $('#initial-dl').val(''); // \u041c\u043e\u0436\u043d\u043e \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u0438\u043b\u0438 \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435\n                console.warn(response.message);\n            }\n        },\n        error: function(xhr, status, error) {\n            console.error('\u041e\u0448\u0438\u0431\u043a\u0430 \u043f\u0440\u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0438 \u0442\u0435\u043a\u0443\u0449\u0435\u0433\u043e DL:', error);\n            $('#initial-dl').val('');\n        }\n    });\n}\nfunction updateInitialDLInput(nextDLNumber) {\n    $('#initial-dl').val(nextDLNumber);\n}\n\n// \u0412\u044b\u0437\u044b\u0432\u0430\u0435\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u044e \u043f\u0440\u0438 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0435 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b\n$(document).ready(function() {\n    loadCurrentDL();\n});\n\nfunction markUnpackedDays(year, month, force = false) {\n    const key = `${year}-${String(month).padStart(2, '0')}`;\n\n    if (!force && unpackedDaysCache[key] !== undefined) {\n        fpInstance.redraw(); // \u041f\u0435\u0440\u0435\u0440\u0438\u0441\u043e\u0432\u044b\u0432\u0430\u0435\u043c \u043a\u0430\u043b\u0435\u043d\u0434\u0430\u0440\u044c \u0434\u043b\u044f \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0441\u0442\u0438\u043b\u0435\u0439\n        return;\n    }\n\n    // \u0417\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u0435\u043c \u043d\u0435\u0443\u043f\u0430\u043a\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u0434\u043d\u0438 \u0434\u043b\u044f \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u043e\u0433\u043e \u043c\u0435\u0441\u044f\u0446\u0430 \u0438 \u0433\u043e\u0434\u0430\n    fetch(`/get_unpacked_days?year=${year}&month=${month}`)\n        .then(response => response.json())\n        .then(data => {\n            if (data.status === 'success') {\n                unpackedDaysCache[key] = new Set(data.unpacked_days);\n                console.log(`\u041d\u0435\u0443\u043f\u0430\u043a\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u0434\u043d\u0438 \u0434\u043b\u044f ${key}:`, unpackedDaysCache[key]);\n            } else {\n                console.error('\u041e\u0448\u0438\u0431\u043a\u0430 \u043f\u0440\u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0438 \u043d\u0435\u0443\u043f\u0430\u043a\u043e\u0432\u0430\u043d\u043d\u044b\u0445 \u0434\u043d\u0435\u0439:', data.message);\n                unpackedDaysCache[key] = new Set(); // \u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0435\u043c \u043f\u0443\u0441\u0442\u044b\u043c \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e\u043c\n            }\n            fpInstance.redraw(); // \u041f\u0435\u0440\u0435\u0440\u0438\u0441\u043e\u0432\u044b\u0432\u0430\u0435\u043c \u043a\u0430\u043b\u0435\u043d\u0434\u0430\u0440\u044c \u043f\u043e\u0441\u043b\u0435 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445\n        })\n        .catch(error => {\n            console.error('\u041e\u0448\u0438\u0431\u043a\u0430 \u043f\u0440\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u0435 \u043d\u0435\u0443\u043f\u0430\u043a\u043e\u0432\u0430\u043d\u043d\u044b\u0445 \u0434\u043d\u0435\u0439:', error);\n            unpackedDaysCache[key] = new Set(); // \u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0435\u043c \u043f\u0443\u0441\u0442\u044b\u043c \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e\u043c\n            fpInstance.redraw();\n        });\n}\ndocument.addEventListener(\"DOMContentLoaded\", function() {\n    flatpickr(\"#datepicker\", {\n        dateFormat: \"Y-m-d\",\n        onMonthChange: function(selectedDates, dateStr, instance) {\n            // \u041f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0434\u043d\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0443\u0436\u043d\u043e \u0432\u044b\u0434\u0435\u043b\u0438\u0442\u044c\n            fetch(`/get_unpacked_days?year=${instance.currentYear}&month=${instance.currentMonth + 1}`)\n                .then(response => response.json())\n                .then(data => {\n                    instance.set(\"disable\", []);\n                    instance.set(\"enable\", []);\n                    instance.set(\"marked\", data.unpacked_days.map(day => {\n                        return `${instance.currentYear}-${instance.currentMonth + 1}-${day}`;\n                    }));\n                });\n        }\n    });\n});\nfunction loadRpaCounts(year, month) {\n    fetch(`/get_rpa_counts?year=${year}&month=${month}`)\n        .then(response => response.json())\n        .then(data => {\n            if (data.status === 'success') {\n                const rpaCounts = data.rpa_counts;\n                fpInstance.redraw(); // \u041f\u0435\u0440\u0435\u0440\u0438\u0441\u043e\u0432\u044b\u0432\u0430\u0435\u043c \u043a\u0430\u043b\u0435\u043d\u0434\u0430\u0440\u044c\n\n                // \u041e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u043c \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0437\u0430\u043f\u0438\u0441\u0435\u0439 RPA \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0434\u043d\u044f\n                fpInstance.days.childNodes.forEach(dayElem => {\n                    const dateStr = dayElem.dateObj.toISOString().split('T')[0];\n                    if (rpaCounts[dateStr]) {\n                        dayElem.classList.add('has-rpa-records');\n                        dayElem.setAttribute('data-rpa-count', rpaCounts[dateStr]);\n                    } else {\n                        dayElem.classList.remove('has-rpa-records');\n                        dayElem.removeAttribute('data-rpa-count');\n                    }\n                });\n\n                // \u0421\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u043c \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0437\u0430\u043f\u0438\u0441\u0435\u0439 RPA \u0432 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u0435 flatpickr\n                fpInstance.rpaCounts = rpaCounts;\n            } else {\n                console.error('\u041e\u0448\u0438\u0431\u043a\u0430 \u043f\u0440\u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0438 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0430 \u0437\u0430\u043f\u0438\u0441\u0435\u0439 RPA:', data.message);\n            }\n        })\n        .catch(error => {\n            console.error('\u041e\u0448\u0438\u0431\u043a\u0430 \u043f\u0440\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0430 \u0437\u0430\u043f\u0438\u0441\u0435\u0439 RPA:', error);\n        });\n}\n\n// \u041e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u043c \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0437\u0430\u043f\u0438\u0441\u0435\u0439 RPA \u043f\u0440\u0438 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0438 \u043c\u0435\u0441\u044f\u0446\u0430\n$('#datepicker').on('change', function() {\n    const selectedDate = new Date(fpInstance.selectedDates[0]);\n    loadRpaCounts(selectedDate.getFullYear(), selectedDate.getMonth() + 1);\n});\n\n// \u041e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u043c \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0437\u0430\u043f\u0438\u0441\u0435\u0439 RPA \u043f\u0440\u0438 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0435 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b\n$(document).ready(function() {\n    const today = new Date();\n    loadRpaCounts(today.getFullYear(), today.getMonth() + 1);\n});\n\n// \u041e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u043c \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0437\u0430\u043f\u0438\u0441\u0435\u0439 RPA \u043f\u0440\u0438 \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0435 \u043d\u0430 \u0434\u0440\u0443\u0433\u043e\u0439 \u0434\u0435\u043d\u044c\nfpInstance.config.onDayCreate = function(dObj, dStr, fp, dayElem) {\n    const dateStr = dayElem.dateObj.toISOString().split('T')[0];\n    if (fpInstance.rpaCounts && fpInstance.rpaCounts[dateStr]) {\n        dayElem.classList.add('has-rpa-records');\n        dayElem.setAttribute('data-rpa-count', fpInstance.rpaCounts[dateStr]);\n    } else {\n        dayElem.classList.remove('has-rpa-records');\n        dayElem.removeAttribute('data-rpa-count');\n    }\n};\n$(document).ready(function() {\n    // \u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043a\u0430\u043b\u0435\u043d\u0434\u0430\u0440\u044f\n    fpInstance = flatpickr(\"#datepicker\", {\n        locale: \"ru\",\n        dateFormat: \"Y-m-d\",\n        defaultDate: \"today\",\n        onChange: function(selectedDates, dateStr, instance) {\n            const selectedDate = selectedDates[0];\n            if (selectedDate) {\n                loadRpaCounts(selectedDate.getFullYear(), selectedDate.getMonth() + 1);\n            }\n        },\n        onMonthChange: function(selectedDates, dateStr, instance) {\n            const selectedDate = new Date(dateStr);\n            loadRpaCounts(selectedDate.getFullYear(), selectedDate.getMonth() + 1);\n        },\n        onDayCreate: function(dObj, dStr, fp, dayElem) {\n            const dateStr = dayElem.dateObj.toISOString().split('T')[0];\n            if (fpInstance.rpaCounts && fpInstance.rpaCounts[dateStr]) {\n                dayElem.classList.add('has-rpa-records');\n                dayElem.setAttribute('data-rpa-count', fpInstance.rpaCounts[dateStr]);\n            } else {\n                dayElem.classList.remove('has-rpa-records');\n                dayElem.removeAttribute('data-rpa-count');\n            }\n        }\n    });\n\n    // \u041f\u0435\u0440\u0435\u0442\u0430\u0441\u043a\u0438\u0432\u0430\u043d\u0438\u0435 \u043a\u0430\u043b\u0435\u043d\u0434\u0430\u0440\u044f\n    let isDragging = false;\n    let dragOffsetX = 0;\n    let dragOffsetY = 0;\n\n    $('.flatpickr-calendar').on('mousedown', function(e) {\n        isDragging = true;\n        dragOffsetX = e.clientX - $(this).offset().left;\n        dragOffsetY = e.clientY - $(this).offset().top;\n        $(this).css('cursor', 'grabbing');\n    });\n\n    $(document).on('mousemove', function(e) {\n        if (isDragging) {\n            $('.flatpickr-calendar').offset({\n                top: e.clientY - dragOffsetY,\n                left: e.clientX - dragOffsetX\n            });\n        }\n    });\n\n    $(document).on('mouseup', function() {\n        isDragging = false;\n        $('.flatpickr-calendar').css('cursor', 'grab');\n    });\n\n    // \u0417\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u043f\u0440\u0438 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0435 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b\n    const today = new Date();\n    loadRpaCounts(today.getFullYear(), today.getMonth() + 1);\n});\ndocument.addEventListener('DOMContentLoaded', function() {\n    // \u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043a\u0430\u043b\u0435\u043d\u0434\u0430\u0440\u044f\n    const fpInstance = flatpickr(\"#datepicker\", {\n        locale: \"ru\",\n        dateFormat: \"Y-m-d\",\n        defaultDate: \"today\",\n        onChange: function(selectedDates, dateStr, instance) {\n            updateDLValue(dateStr);\n        }\n    });\n\n    // \u0424\u0443\u043d\u043a\u0446\u0438\u044f \u0434\u043b\u044f \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f DL\n    function updateDLValue(dateStr) {\n        console.log('Updating DL value for date:', dateStr);\n        fetch(`/get_table_data?date=${dateStr}`)\n            .then(response => response.json())\n            .then(data => {\n                if (data.status === 'success') {\n                    const rows = data.data;\n                    let maxDL = 0;\n\n                    // \u0418\u0449\u0435\u043c \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 DL \u0432 \u0442\u0430\u0431\u043b\u0438\u0446\u0435\n                    rows.forEach(row => {\n                        const dlNumber = parseInt(row.dl_number.replace('DL', ''), 10);\n                        if (!isNaN(dlNumber) && dlNumber > maxDL) {\n                            maxDL = dlNumber;\n                        }\n                    });\n\n                    // \u0423\u0432\u0435\u043b\u0438\u0447\u0438\u0432\u0430\u0435\u043c \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043d\u0430 \u0435\u0434\u0438\u043d\u0438\u0446\u0443\n                    const nextDL = maxDL + 1;\n                    console.log('Next DL value:', nextDL);\n                    document.getElementById('initial-dl').value = `DL${nextDL}`;\n                } else {\n                    console.warn(data.message);\n                }\n            })\n            .catch(error => {\n                console.error('\u041e\u0448\u0438\u0431\u043a\u0430 \u043f\u0440\u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0438 \u0434\u0430\u043d\u043d\u044b\u0445 \u0442\u0430\u0431\u043b\u0438\u0446\u044b:', error);\n            });\n    }\n\n    // \u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f DL \u0434\u043b\u044f \u0442\u0435\u043a\u0443\u0449\u0435\u0439 \u0434\u0430\u0442\u044b\n    const currentDate = new Date().toISOString().split('T')[0];\n    updateDLValue(currentDate);\n});\ndocument.addEventListener('DOMContentLoaded', function() {\n    // \u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043a\u0430\u043b\u0435\u043d\u0434\u0430\u0440\u044f\n    const fpInstance = flatpickr(\"#datepicker\", {\n        locale: \"ru\",\n        dateFormat: \"Y-m-d\",\n        defaultDate: \"today\",\n        onChange: function(selectedDates, dateStr, instance) {\n            updateStatistics(dateStr);\n        }\n    });\n\n    // \u0424\u0443\u043d\u043a\u0446\u0438\u044f \u0434\u043b\u044f \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0438\n    function updateStatistics(dateStr) {\n        console.log('Updating statistics for date:', dateStr);\n        fetch(`/get_statistics?date=${dateStr}`)\n            .then(response => {\n                if (!response.ok) {\n                    throw new Error('Network response was not ok ' + response.statusText);\n                }\n                return response.json();\n            })\n            .then(data => {\n                if (data.status === 'success') {\n                    console.log('Received statistics:', data);\n                    document.getElementById('generateClicks').textContent = data.generate_clicks;\n                    document.getElementById('packClicks').textContent = data.pack_clicks;\n                    const unpackedClicks = data.rpa_records - data.pack_clicks;\n                    console.log('Unpacked clicks:', unpackedClicks);\n                    document.getElementById('unpackedClicks').textContent = unpackedClicks;\n                } else {\n                    console.warn(data.message);\n                }\n            })\n            .catch(error => {\n                console.error('\u041e\u0448\u0438\u0431\u043a\u0430 \u043f\u0440\u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0438 \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0438:', error);\n            });\n    }\n\n    // \u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0438 \u0434\u043b\u044f \u0442\u0435\u043a\u0443\u0449\u0435\u0439 \u0434\u0430\u0442\u044b\n    const currentDate = new Date().toISOString().split('T')[0];\n    updateStatistics(currentDate);\n});\n\nconst toggle = document.getElementById(\"toggle\");\nconst refresh = document.getElementById(\"refresh\");\nconst theme = window.localStorage.getItem(\"theme\");\n\n/* checks if the theme stored in localStorage is dark\nif yes apply the dark theme to the body */\nif (theme === \"dark\") document.body.classList.add(\"dark\");\n\n// event listener stops when the change theme button is clicked\ntoggle.addEventListener(\"click\", () => {\n   document.body.classList.toggle(\"dark\");\n   if (theme === \"dark\") {\n     window.localStorage.setItem(\"theme\", \"light\");\n   } else window.localStorage.setItem(\"theme\", \"dark\");\n});\n\nrefresh.addEventListener(\"click\", () => {\n   window.location.reload();\n});\nfunction toggleDeviceStatusWindow() {\n    const deviceStatusWindow = $('#deviceStatusWindow');\n    if (deviceStatusWindow.hasClass('show')) {\n        deviceStatusWindow.removeClass('show');\n    } else {\n        deviceStatusWindow.addClass('show');\n    }\n}\n\n$(document).ready(function() {\n    // \u041e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u0434\u043b\u044f \u043a\u043d\u043e\u043f\u043a\u0438 \"\u0421\u0442\u0430\u0442\u0443\u0441\u044b \u0423\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\"\n    $('.status-button').on('click', function() {\n        toggleDeviceStatusWindow();\n    });\n\n    // \u041e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u0434\u043b\u044f \u043a\u0440\u0435\u0441\u0442\u0438\u043a\u0430\n    $('.close-button').on('click', function() {\n        $('#deviceStatusWindow').removeClass('show');\n    });\n});\n$(document).ready(function() {\n    // \u041e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u0434\u043b\u044f \u043a\u043d\u043e\u043f\u043a\u0438 \"\u0418\u043c\u043f\u043e\u0440\u0442 \u0438\u0437 Excel\"\n    $('.import-button').on('click', function() {\n        $('#fileInput').click(); // \u0412\u044b\u0437\u044b\u0432\u0430\u0435\u043c \u043a\u043b\u0438\u043a \u043d\u0430 \u0441\u043a\u0440\u044b\u0442\u043e\u043c input[type=\"file\"]\n    });\n\n    // \u041e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u0434\u043b\u044f \u0432\u044b\u0431\u043e\u0440\u0430 \u0444\u0430\u0439\u043b\u0430\n    $('#fileInput').on('change', function(event) {\n        const file = event.target.files[0];\n        if (file) {\n            const formData = new FormData();\n            formData.append('file', file);\n\n            // \u041e\u0442\u043f\u0440\u0430\u0432\u043a\u0430 \u0444\u0430\u0439\u043b\u0430 \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\n            $.ajax({\n                url: '/import_excel', // URL \u0434\u043b\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0444\u0430\u0439\u043b\u0430 \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0435\n                type: 'POST',\n                data: formData,\n                processData: false,\n                contentType: false,\n                success: function(response) {\n                    if (response.status === 'success') {\n                        alert('\u0424\u0430\u0439\u043b \u0443\u0441\u043f\u0435\u0448\u043d\u043e \u0438\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u043d');\n                        // \u041e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u043c \u0442\u0430\u0431\u043b\u0438\u0446\u0443 \u0438\u043b\u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u0434\u0440\u0443\u0433\u0438\u0435 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u043f\u043e\u0441\u043b\u0435 \u0438\u043c\u043f\u043e\u0440\u0442\u0430\n                        updateTable();\n                    } else {\n                        alert('\u041e\u0448\u0438\u0431\u043a\u0430 \u043f\u0440\u0438 \u0438\u043c\u043f\u043e\u0440\u0442\u0435 \u0444\u0430\u0439\u043b\u0430: ' + response.message);\n                    }\n                },\n                error: function(xhr, status, error) {\n                    alert('\u041e\u0448\u0438\u0431\u043a\u0430 \u043f\u0440\u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0435 \u0444\u0430\u0439\u043b\u0430: ' + error);\n                }\n            });\n        }\n    });\n});\n$(document).ready(function() {\n    // \u0423\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043f\u0440\u0435\u0444\u0438\u043a\u0441\u0430 \u043f\u0440\u0438 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0435 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b\n    $('#dl-prefix-input').val('{{ dl_prefix }}');\n\n    // \u041e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u0441\u043e\u0431\u044b\u0442\u0438\u044f \u0434\u043b\u044f \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \u043f\u0440\u0435\u0444\u0438\u043a\u0441\u0430\n    $('#set-prefix-button').on('click', function() {\n        const newPrefix = $('#dl-prefix-input').val().trim();\n\n        if (newPrefix) {\n            $.ajax({\n                url: '/set_dl_prefix',\n                type: 'POST',\n                contentType: 'application/json',\n                data: JSON.stringify({ prefix: newPrefix }),\n                success: function(response) {\n                    if (response.status === 'success') {\n                        $('#prefix-notification').text(`\u041f\u0440\u0435\u0444\u0438\u043a\u0441 \u0443\u0441\u043f\u0435\u0448\u043d\u043e \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d: ${response.new_prefix}`).css('color', 'green');\n                    } else {\n                        $('#prefix-notification').text(`\u041e\u0448\u0438\u0431\u043a\u0430: ${response.message}`).css('color', 'red');\n                    }\n                },\n                error: function(xhr, status, error) {\n                    $('#prefix-notification').text(`\u041e\u0448\u0438\u0431\u043a\u0430 \u043f\u0440\u0438 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0435 \u043f\u0440\u0435\u0444\u0438\u043a\u0441\u0430: ${error}`).css('color', 'red');\n                }\n            });\n        } else {\n            $('#prefix-notification').text('\u041f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430, \u0432\u0432\u0435\u0434\u0438\u0442\u0435 \u043f\u0440\u0435\u0444\u0438\u043a\u0441.').css('color', 'red');\n        }\n    });\n});\n// \u0424\u0443\u043d\u043a\u0446\u0438\u044f \u0434\u043b\u044f \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u043e\u0431\u0449\u0435\u0433\u043e \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0430 RPA \u0438 \u0438\u0445 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0430 \u0437\u0430 \u0432\u0441\u0451 \u0432\u0440\u0435\u043c\u044f\nfunction showRPATotal() {\n    $.ajax({\n        url: '/get_rpa_records',\n        type: 'GET',\n        success: function(response) {\n            if (response.status === 'success') {\n                const totalRPA = response.data.length;\n                $('#total-rpa-records').text(totalRPA);\n                $('#total-rpa-all-time').text(totalRPA);\n                $('#rpa-total-container').show();\n                $('.statistics-container').hide();\n            } else {\n                alert('\u041e\u0448\u0438\u0431\u043a\u0430 \u043f\u0440\u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0438 \u0437\u0430\u043f\u0438\u0441\u0435\u0439 RPA: ' + response.message);\n            }\n        },\n        error: function(xhr, status, error) {\n            console.error('\u041e\u0448\u0438\u0431\u043a\u0430 \u043f\u0440\u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0438 \u0437\u0430\u043f\u0438\u0441\u0435\u0439 RPA:', error);\n            alert('\u041e\u0448\u0438\u0431\u043a\u0430 \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u043f\u0440\u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0438 \u0437\u0430\u043f\u0438\u0441\u0435\u0439 RPA: ' + error);\n        }\n    });\n}\n\n// \u0424\u0443\u043d\u043a\u0446\u0438\u044f \u0434\u043b\u044f \u0441\u043a\u0440\u044b\u0442\u0438\u044f \u043e\u043a\u043d\u0430 \u0441 \u043e\u0431\u0449\u0438\u043c \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e\u043c RPA \u0438 \u0432\u043e\u0441\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u043e\u043a\u043e\u043d\nfunction hideRPATotal() {\n    $('#rpa-total-container').hide();\n    $('.statistics-container').show();\n}\n\nfunction showDuplicates() {\n    isShowingDuplicates = true;\n    const showOnlyRPA = $('#armaFilter').is(':checked');\n\n    $.ajax({\n        url: '/get_duplicates',\n        type: 'GET',\n        success: function(response) {\n            if (response.status === 'success') {\n                var tableBody = $('#tableBody');\n                tableBody.empty();\n\n                // \u0424\u0438\u043b\u044c\u0442\u0440\u0443\u0435\u043c \u0434\u0443\u0431\u043b\u0438\u043a\u0430\u0442\u044b, \u0435\u0441\u043b\u0438 \u0432\u044b\u0431\u0440\u0430\u043d\u043e \"\u041f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e RPA\"\n                let filteredData = response.data;\n                if (showOnlyRPA) {\n                    filteredData = response.data.filter(row => row.arma_type === 'RPA');\n                }\n\n                updateTableContent(filteredData, tableBody, false);\n\n                if (globalSortColumn !== null) {\n                    sortTable(globalSortColumn, globalSortOrder);\n                }\n\n                highlightDuplicates(response.duplicates);\n            } else {\n                alert('\u041e\u0448\u0438\u0431\u043a\u0430 \u043f\u0440\u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0438 \u0434\u0443\u0431\u043b\u0438\u043a\u0430\u0442\u043e\u0432: ' + response.message);\n            }\n        },\n        error: function(xhr, status, error) {\n            console.error('\u041e\u0448\u0438\u0431\u043a\u0430 \u043f\u0440\u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0438 \u0434\u0443\u0431\u043b\u0438\u043a\u0430\u0442\u043e\u0432:', error);\n            alert('\u041e\u0448\u0438\u0431\u043a\u0430 \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u043f\u0440\u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0438 \u0434\u0443\u0431\u043b\u0438\u043a\u0430\u0442\u043e\u0432: ' + error);\n        }\n    });\n}\n\n// \u041e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u0441\u043e\u0431\u044b\u0442\u0438\u044f \u0434\u043b\u044f \u0433\u0430\u043b\u043e\u0447\u043a\u0438 \"\u041f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e RPA\"\n$('#armaFilter').on('change', function() {\n    if (isShowingDuplicates) {\n        showDuplicates();\n    }\n});\n\n// \u041e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u0441\u043e\u0431\u044b\u0442\u0438\u044f \u0434\u043b\u044f \u043a\u043d\u043e\u043f\u043a\u0438 \"\u041f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u0432\u0441\u0435 RPA\"\n$('#showRPAButton').on('click', function() {\n    isRPAFilterActive = true;\n    $.ajax({\n        url: '/get_rpa_records',\n        type: 'GET',\n        success: function(response) {\n            if (response.status === 'success') {\n                var tableBody = $('#tableBody');\n                tableBody.empty();\n                updateTableContent(response.data, tableBody, false);\n\n                if (globalSortColumn !== null) {\n                    sortTable(globalSortColumn, globalSortOrder);\n                }\n\n                checkDuplicates();\n\n                // \u041f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c \u043e\u0431\u0449\u0435\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e RPA \u0438 \u0438\u0445 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0437\u0430 \u0432\u0441\u0451 \u0432\u0440\u0435\u043c\u044f\n                showRPATotal();\n            } else {\n                alert('\u041e\u0448\u0438\u0431\u043a\u0430 \u043f\u0440\u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0438 \u0437\u0430\u043f\u0438\u0441\u0435\u0439 RPA: ' + response.message);\n            }\n        },\n        error: function(xhr, status, error) {\n            console.error('\u041e\u0448\u0438\u0431\u043a\u0430 \u043f\u0440\u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0438 \u0437\u0430\u043f\u0438\u0441\u0435\u0439 RPA:', error);\n            alert('\u041e\u0448\u0438\u0431\u043a\u0430 \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u043f\u0440\u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0438 \u0437\u0430\u043f\u0438\u0441\u0435\u0439 RPA: ' + error);\n        }\n    });\n});\n\n// \u041e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u0441\u043e\u0431\u044b\u0442\u0438\u044f \u0434\u043b\u044f \u043a\u043d\u043e\u043f\u043a\u0438 \"\u041f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u0434\u0443\u0431\u043b\u0438\u043a\u0430\u0442\u044b\"\n$('#showDuplicatesButton').on('click', function() {\n    showDuplicates();\n});\n\n// \u041e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u0441\u043e\u0431\u044b\u0442\u0438\u044f \u0434\u043b\u044f \u0433\u0430\u043b\u043e\u0447\u043a\u0438 \"\u041f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e RPA\"\n$('#armaFilter').on('change', function() {\n    if (isShowingDuplicates) {\n        showDuplicates();\n    }\n});\n\n// \u041e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 updateTable\nfunction updateTable(force = false, highlightNew = false) {\n    return new Promise((resolve, reject) => {\n        const now = Date.now();\n        if (!force && now - lastUpdateTime < updateInterval) {\n            resolve();\n            return;\n        }\n        if (isEditing) {\n            resolve();\n            return;\n        }\n\n        if (isEditing || isDeleting) { // \u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0443 \u043d\u0430 isDeleting\n            resolve();\n            return;\n        }\n\n        // \u041f\u0440\u043e\u0432\u0435\u0440\u044c\u0442\u0435, \u0435\u0441\u043b\u0438 \u0444\u0438\u043b\u044c\u0442\u0440 RPA \u0430\u043a\u0442\u0438\u0432\u0435\u043d, \u043d\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0439\u0442\u0435 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\n        if (isRPAFilterActive) {\n            resolve();\n            return;\n        }\n       \n        if (isShowingDuplicates) {\n            resolve();\n            return;\n        }\n\n        $.ajax({\n            url: '/get_table_data',\n            type: 'GET',\n            data: { \n                date: getSelectedDate(),\n                filter_arma: getArmaFilter()\n            },\n            success: function(response) {\n                var tableBody = $('#tableBody');\n\n                // \u041e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u043c \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435 \u0442\u0430\u0431\u043b\u0438\u0446\u044b\n                updateTableContent(response.data, tableBody, highlightNew);\n\n                // \u041f\u0440\u0438\u043c\u0435\u043d\u044f\u0435\u043c \u0442\u0435\u043a\u0443\u0449\u0443\u044e \u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u043a\u0443\n                if (globalSortColumn !== null) {\n                    sortTable(globalSortColumn, globalSortOrder);\n                }\n\n                updateStatistics();\n                lastUpdateTime = now;\n\n                // \u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c \u0438 \u043f\u043e\u0434\u0441\u0432\u0435\u0447\u0438\u0432\u0430\u0435\u043c \u0434\u0443\u0431\u043b\u0438\u043a\u0430\u0442\u044b\n                highlightDuplicates(response.duplicates);\n\n                // \u0421\u043a\u0440\u044b\u0432\u0430\u0435\u043c \u043e\u043a\u043d\u043e \u0441 \u043e\u0431\u0449\u0438\u043c \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e\u043c RPA \u0438 \u0432\u043e\u0441\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u043e\u043a\u043d\u0430\n                hideRPATotal();\n\n                resolve();\n            },\n            error: function(xhr, status, error) {\n                console.error('Error updating table:', error);\n                reject(error);\n            }\n        });\n    });\n}\ndocument.getElementById('show-all-rpa-button').addEventListener('click', function() {\n    var statBoxes = document.querySelectorAll('.stat-box');\n    statBoxes.forEach(function(box) {\n        box.classList.toggle('hidden');\n    });\n});\ndocument.getElementById('show-all-rpa-button').addEventListener('click', function() {\n    var statBoxes = document.querySelectorAll('.stat-box');\n    statBoxes.forEach(function(box) {\n        box.classList.toggle('hidden');\n    });\n});\n\n// \u0424\u0443\u043d\u043a\u0446\u0438\u044f \u0434\u043b\u044f \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u044f \u043e\u0431\u0449\u0435\u0433\u043e \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0430 RPA\nfunction calculateTotalRPA() {\n    var totalRPA = rpaData.length;\n    document.getElementById('total-rpa-value').textContent = totalRPA;\n}\n\n// \u0412\u044b\u0437\u044b\u0432\u0430\u0435\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u044e \u0434\u043b\u044f \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u044f \u0438 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u043e\u0431\u0449\u0435\u0433\u043e \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0430 RPA\ncalculateTotalRPA();"},{"assistant_initiates":false,"asst_text":"Subject: Update on Defect ID PM11051\n\nDear Team,\n\nI would like to inform you that a defect ID has been raised for this specific case: PM11051. I\u2019m pleased to report that the issue has been resolved in UAT, and we are currently conducting testing.\n\nBest regards,  \n[Your Name]  ","behavior":"degenerate_repetition","conversation_hash":"5e738d145e68ce6d86f9a24fa0701e54","conversation_redacted":false,"conversation_toxic":false,"country":"India","empty_output":false,"evidence_codes":[],"label":"absent","label_present":false,"label_qualified":false,"label_source":"Final dense release","language":"English","model":"gpt-4o-mini-2024-07-18","n_chars":454,"n_turns_in_conversation":13,"n_words":80,"source_row_offset":748,"source_shard":"turns-00054.parquet","timestamp":"Fri, 29 Nov 2024 10:08:23 GMT","turn_id":"4dde1612fe6be074dc10848e","turn_index":0,"user_text":"Dear Team, \n\nThe defect ID has been raised for this specific case with the number  PM11051  and this issue has been resloved in UAT and we are doint testing. \n\n\nplease reframe it"},{"assistant_initiates":false,"asst_text":"Subject: Aadhar Document Analysis Findings\n\nDear Sir,\n\nUpon our analysis, we discovered that the name on the Aadhar document has low visual quality. The text appears blurred, which reduces the sharpness of the character edges. As a result, the OCR may have provided inaccurate details.\n\nRegards,  \nManish","behavior":"degenerate_repetition","conversation_hash":"5e738d145e68ce6d86f9a24fa0701e54","conversation_redacted":false,"conversation_toxic":false,"country":"India","empty_output":false,"evidence_codes":[],"label":"absent","label_present":false,"label_qualified":false,"label_source":"Final dense release","language":"English","model":"gpt-4o-mini-2024-07-18","n_chars":599,"n_turns_in_conversation":13,"n_words":98,"source_row_offset":749,"source_shard":"turns-00054.parquet","timestamp":"Fri, 29 Nov 2024 10:08:23 GMT","turn_id":"73abbcfb29bb18c98f0145e3","turn_index":1,"user_text":"Dear Sir, \n\nBased on our analysis, we found that the name on the Aadhar document is has low visual quality where the text present and the text appear blur , resucing the sharpness of character edges due to which the orc has provided the inaccurate details.  \n\nRegards\nManish.\n\nplease reframe it"},{"assistant_initiates":false,"asst_text":"The error message you're seeing indicates that the AWS CLI (Command Line Interface) on your system cannot find the necessary credentials to access your AWS resources, specifically the S3 bucket you are trying to list. \n\nTo resolve this issue, you'll need to configure your AWS credentials. Here\u2019s how you can do that:\n\n1. **Run AWS Configure Command:**\n   Open your terminal and execute the following command:\n\n   ```bash\n   aws configure\n   ```\n\n2. **Enter Your AWS Credentials:**\n   You will be prompted to enter the following information:\n   - **AWS Access Key ID:** Your AWS access key ID.\n   - **AWS Secret Access Key:** Your AWS secret access key.\n   - **Default region name:** The region where your bucket is located (e.g., `us-east-1`).\n   - **Default output format:** The output format (e.g., `json`, `text`, or `table`). You may leave this blank for JSON.\n\n3. **Verify Credentials:**\n   After configuring, you can verify that the credentials are set correctly by running:\n\n   ```bash\n   aws s3 ls\n   ```\n\n   This command should now work without throwing an error, and it should list the S3 buckets associated with your credentials.\n\n4. **Check IAM Permissions:**\n   Ensure that the IAM user or role associated with the provided AWS credentials has the necessary permissions to access the S3 bucket.\n\n5. **Environment Variables (Optional):**\n   As an alternative, you can also set the AWS credentials through environment variables:\n\n   ```bash\n   export AWS_ACCESS_KEY_ID=your_access_key_id\n   export AWS_SECRET_ACCESS_KEY=your_secret_access_key\n   export AWS_REGION=your_region\n   ```\n\nBy following these steps, you should be able to resolve the \"Unable to locate credentials\" error and successfully list the contents of your S3 bucket.","behavior":"degenerate_repetition","conversation_hash":"5e738d145e68ce6d86f9a24fa0701e54","conversation_redacted":false,"conversation_toxic":false,"country":"India","empty_output":false,"evidence_codes":[],"label":"absent","label_present":false,"label_qualified":false,"label_source":"Final dense release","language":"English","model":"gpt-4o-mini-2024-07-18","n_chars":1922,"n_turns_in_conversation":13,"n_words":270,"source_row_offset":750,"source_shard":"turns-00054.parquet","timestamp":"Fri, 29 Nov 2024 10:08:23 GMT","turn_id":"63cb905fb79d96f3fbdd8943","turn_index":2,"user_text":"[appuser@ip-172-20-16-97 ~]$ aws s3 ls s3://ocr-aadhaar-masking-application-data-uat/\n\nUnable to locate credentials. You can configure credentials by running \"aws configure\".\n"}],"shard":{"index":54,"name":"turns-00054.parquet","rows":67195}}
