diff --git a/project/backend/coordinator/app.py b/project/backend/coordinator/app.py index 2603f42..caeafca 100644 --- a/project/backend/coordinator/app.py +++ b/project/backend/coordinator/app.py @@ -26,6 +26,6 @@ def health_check(): return "OK" -# für Docker wichtig: host='0.0.0.0' +# Für Docker wichtig: host='0.0.0.0' if __name__ == "__main__": socketio.run(app, debug=True, host="0.0.0.0", port=5050) diff --git a/project/backend/coordinator/controller/__init__.py b/project/backend/coordinator/controller/__init__.py index 5b758cb..453a69e 100644 --- a/project/backend/coordinator/controller/__init__.py +++ b/project/backend/coordinator/controller/__init__.py @@ -1,11 +1,12 @@ -from controller.spacy_contoller import spacy_controller -from controller.kpi_setting_controller import kpi_setting_controller +from controller.spacy_controller import spacy_controller +from controller.kpi_setting_controller import kpi_setting_controller, kpi_routes from controller.pitch_book_controller import pitch_book_controller from controller.progress_controller import progress_controller def register_routes(app): app.register_blueprint(kpi_setting_controller) + app.register_blueprint(kpi_routes) app.register_blueprint(pitch_book_controller) app.register_blueprint(spacy_controller) app.register_blueprint(progress_controller) diff --git a/project/backend/coordinator/controller/kpi_setting_controller.py b/project/backend/coordinator/controller/kpi_setting_controller.py index d6328cf..e1f98b1 100644 --- a/project/backend/coordinator/controller/kpi_setting_controller.py +++ b/project/backend/coordinator/controller/kpi_setting_controller.py @@ -2,7 +2,10 @@ from flask import Blueprint, request, jsonify from model.database import db from model.kpi_setting_model import KPISettingModel, KPISettingType +# Routen für /api/kpi/settings (Auslesen im Frontend) +kpi_routes = Blueprint("kpi_routes", __name__, url_prefix="/api/kpi") +# Routen für /api/kpi_setting/ (Hinzufügen, Ändern, Löschen) kpi_setting_controller = Blueprint( "kpi_settings", __name__, url_prefix="/api/kpi_setting" ) @@ -14,12 +17,6 @@ def get_all_kpi_settings(): return jsonify([kpi_setting.to_dict() for kpi_setting in kpi_settings]), 200 -@kpi_setting_controller.route("/", methods=["GET"]) -def get_kpi_setting(id): - kpi_setting = KPISettingModel.query.get_or_404(id) - return jsonify(kpi_setting.to_dict()), 200 - - @kpi_setting_controller.route("/", methods=["POST"]) def create_kpi_setting(): data = request.json @@ -29,13 +26,12 @@ def create_kpi_setting(): required_fields = [ "name", - "description", "mandatory", "type", - "translation", - "example", "position", "active", + "examples", + "is_trained", ] for field in required_fields: if field not in data: @@ -55,13 +51,12 @@ def create_kpi_setting(): new_kpi_setting = KPISettingModel( name=data["name"], - description=data["description"], mandatory=data["mandatory"], type=kpi_type, - translation=data["translation"], - example=data["example"], position=data["position"], active=data["active"], + examples=data.get("examples", []), + is_trained=False, ) db.session.add(new_kpi_setting) @@ -84,9 +79,6 @@ def update_kpi_setting(id): return jsonify({"error": "KPI Setting with this name already exists"}), 409 kpi_setting.name = data["name"] - if "description" in data: - kpi_setting.description = data["description"] - if "mandatory" in data: kpi_setting.mandatory = data["mandatory"] @@ -100,18 +92,18 @@ def update_kpi_setting(id): 400, ) - if "translation" in data: - kpi_setting.translation = data["translation"] - - if "example" in data: - kpi_setting.example = data["example"] - if "position" in data: kpi_setting.position = data["position"] if "active" in data: kpi_setting.active = data["active"] + if "examples" in data: + kpi_setting.examples = data["examples"] + + if "is_trained" in data: + kpi_setting.is_trained = data["is_trained"] + db.session.commit() return jsonify(kpi_setting.to_dict()), 200 @@ -154,3 +146,21 @@ def update_kpi_positions(): except Exception as e: db.session.rollback() return jsonify({"error": f"Failed to update positions: {str(e)}"}), 500 + + +@kpi_routes.route("/settings", methods=["GET"]) +def get_kpi_settings(): + try: + kpis = KPISettingModel.query.all() + return jsonify([k.to_dict() for k in kpis]), 200 + except Exception as e: + return ( + jsonify({"error": "Fehler beim Abrufen der KPIs", "details": str(e)}), + 500, + ) + + +@kpi_setting_controller.route("/", methods=["GET"]) +def get_kpi_setting(id): + kpi_setting = KPISettingModel.query.get_or_404(id) + return jsonify(kpi_setting.to_dict()), 200 diff --git a/project/backend/coordinator/controller/spacy_contoller.py b/project/backend/coordinator/controller/spacy_contoller.py deleted file mode 100644 index 087cf06..0000000 --- a/project/backend/coordinator/controller/spacy_contoller.py +++ /dev/null @@ -1,93 +0,0 @@ -from flask import Blueprint, request, jsonify, send_file -from io import BytesIO - -from model.spacy_model import SpacyModel -import puremagic -from werkzeug.utils import secure_filename -from model.database import db - - -spacy_controller = Blueprint("spacy", __name__, url_prefix="/api/spacy") - - -@spacy_controller.route("/", methods=["GET"]) -def get_all_files(): - files = SpacyModel.query.all() - return jsonify([file.to_dict() for file in files]), 200 - - -@spacy_controller.route("/", methods=["GET"]) -def get_file(id): - file = SpacyModel.query.get_or_404(id) - return jsonify(file.to_dict()), 200 - - -@spacy_controller.route("//download", methods=["GET"]) -def download_file(id): - file = SpacyModel.query.get_or_404(id) - return send_file( - BytesIO(file.file), download_name=file.filename, as_attachment=True - ) - - -@spacy_controller.route("/", methods=["POST"]) -def upload_file(): - print(request) - if "file" not in request.files: - return jsonify({"error": "No file part in the request"}), 400 - - uploaded_file = request.files["file"] - if uploaded_file.filename == "": - return jsonify({"error": "No selected file"}), 400 - - # Read file data once - file_data = uploaded_file.read() - try: - if uploaded_file: - fileName = uploaded_file.filename or "" - new_file = SpacyModel(filename=secure_filename(fileName), file=file_data) - - db.session.add(new_file) - db.session.commit() - - return jsonify(new_file.to_dict()), 201 - except Exception as e: - print(e) - return jsonify({"error": "Invalid file format. Only PDF files are accepted"}), 400 - - -@spacy_controller.route("/", methods=["PUT"]) -def update_file(id): - file = SpacyModel.query.get_or_404(id) - - if "file" in request.files: - uploaded_file = request.files["file"] - if uploaded_file.filename != "": - file.filename = uploaded_file.filename - - # Read file data once - file_data = uploaded_file.read() - try: - if ( - uploaded_file - and puremagic.from_string(file_data, mime=True) == "application/pdf" - ): - file.file = file_data - except Exception as e: - print(e) - - if "kpi" in request.form: - file.kpi = request.form.get("kpi") - - db.session.commit() - - return jsonify(file.to_dict()), 200 - - -@spacy_controller.route("/", methods=["DELETE"]) -def delete_file(id): - file = SpacyModel.query.get_or_404(id) - db.session.delete(file) - db.session.commit() - - return jsonify({"message": f"File {id} deleted successfully"}), 200 diff --git a/project/backend/coordinator/controller/spacy_controller.py b/project/backend/coordinator/controller/spacy_controller.py new file mode 100644 index 0000000..330e9e5 --- /dev/null +++ b/project/backend/coordinator/controller/spacy_controller.py @@ -0,0 +1,149 @@ +from flask import Blueprint, request, jsonify, send_file +from io import BytesIO +from model.spacy_model import SpacyModel +import puremagic +from werkzeug.utils import secure_filename +from model.database import db +import os +import requests +from model.kpi_setting_model import KPISettingModel + + +spacy_controller = Blueprint("spacy", __name__, url_prefix="/api/spacy") + +SPACY_TRAINING_URL = os.getenv("SPACY_TRAINING_URL", "http://spacy:5052/train") +SPACY_URL = os.getenv("SPACY_URL", "http://spacy:5052") + + +@spacy_controller.route("/train", methods=["POST"]) +def trigger_training(): + try: + response = requests.post(SPACY_TRAINING_URL, timeout=600) + if response.ok: + return jsonify({"message": "Training erfolgreich angestoßen."}), 200 + else: + return ( + jsonify({"error": "Training fehlgeschlagen", "details": response.text}), + 500, + ) + except Exception as e: + return ( + jsonify( + {"error": "Fehler beim Senden an Trainingsservice", "details": str(e)} + ), + 500, + ) + + +@spacy_controller.route("/", methods=["GET"]) +def get_all_files(): + files = SpacyModel.query.all() + return jsonify([file.to_dict() for file in files]), 200 + + +@spacy_controller.route("/", methods=["GET"]) +def get_file(id): + file = SpacyModel.query.get_or_404(id) + return jsonify(file.to_dict()), 200 + + +@spacy_controller.route("//download", methods=["GET"]) +def download_file(id): + file = SpacyModel.query.get_or_404(id) + return send_file( + BytesIO(file.file), download_name=file.filename, as_attachment=True + ) + + +@spacy_controller.route("/", methods=["POST"]) +def upload_file(): + if "file" not in request.files: + return jsonify({"error": "No file part in the request"}), 400 + + uploaded_file = request.files["file"] + if uploaded_file.filename == "": + return jsonify({"error": "No selected file"}), 400 + + file_data = uploaded_file.read() + try: + fileName = uploaded_file.filename or "" + new_file = SpacyModel(filename=secure_filename(fileName), file=file_data) + db.session.add(new_file) + db.session.commit() + return jsonify(new_file.to_dict()), 201 + except Exception as e: + print(e) + return jsonify({"error": "Invalid file format. Only PDF files are accepted"}), 400 + + +@spacy_controller.route("/", methods=["PUT"]) +def update_file(id): + file = SpacyModel.query.get_or_404(id) + + if "file" in request.files: + uploaded_file = request.files["file"] + if uploaded_file.filename != "": + file.filename = uploaded_file.filename + file_data = uploaded_file.read() + try: + if puremagic.from_string(file_data, mime=True) == "application/pdf": + file.file = file_data + except Exception as e: + print(e) + + if "kpi" in request.form: + file.kpi = request.form.get("kpi") + + db.session.commit() + return jsonify(file.to_dict()), 200 + + +@spacy_controller.route("/", methods=["DELETE"]) +def delete_file(id): + file = SpacyModel.query.get_or_404(id) + db.session.delete(file) + db.session.commit() + return jsonify({"message": f"File {id} deleted successfully"}), 200 + + +@spacy_controller.route("/append-training-entry", methods=["POST"]) +def forward_training_entry(): + entry = request.get_json() + try: + response = requests.post(f"{SPACY_URL}/append-training-entry", json=entry) + return jsonify(response.json()), response.status_code + except Exception as e: + return jsonify({"error": str(e)}), 500 + + +# globale Variable oben einfügen +current_training_status = {"running": False} + + +@spacy_controller.route("/training/status", methods=["POST"]) +def update_training_status(): + data = request.get_json() + current_training_status["running"] = data.get("running", False) + + if current_training_status["running"] is False: + try: + KPISettingModel.query.update({KPISettingModel.is_trained: True}) + db.session.commit() + except Exception as e: + db.session.rollback() + return ( + jsonify( + { + "error": "is_trained konnte nicht aktualisiert werden", + "details": str(e), + } + ), + 500, + ) + + return jsonify({"status": "success", "running": current_training_status["running"]}) + + +@spacy_controller.route("/train-status", methods=["GET"]) +def training_status(): + return jsonify(current_training_status), 200 diff --git a/project/backend/coordinator/model/kpi_setting_model.py b/project/backend/coordinator/model/kpi_setting_model.py index 11ff33d..b72444a 100644 --- a/project/backend/coordinator/model/kpi_setting_model.py +++ b/project/backend/coordinator/model/kpi_setting_model.py @@ -2,6 +2,8 @@ from model.database import db from sqlalchemy.orm import Mapped, mapped_column from sqlalchemy import Enum as SQLAlchemyEnum from enum import Enum +from sqlalchemy.dialects.postgresql import JSONB +from collections import OrderedDict class KPISettingType(Enum): @@ -18,37 +20,36 @@ class KPISettingModel(db.Model): id: Mapped[int] = mapped_column(primary_key=True) name: Mapped[str] = mapped_column(unique=True) - description: Mapped[str] mandatory: Mapped[bool] type: Mapped[KPISettingType] = mapped_column( SQLAlchemyEnum(KPISettingType, native_enum=True) ) - translation: Mapped[str] - example: Mapped[str] position: Mapped[int] active: Mapped[bool] + examples: Mapped[list] = mapped_column(JSONB, default=[]) + is_trained: Mapped[bool] = mapped_column(default=False) def to_dict(self): - return { - "id": self.id, - "name": self.name, - "description": self.description, - "mandatory": self.mandatory, - "type": self.type.value, - "translation": self.translation, - "example": self.example, - "position": self.position, - "active": self.active, - } + return OrderedDict( + [ + ("id", self.id), + ("name", self.name), + ("mandatory", self.mandatory), + ("type", self.type.value), + ("position", self.position), + ("examples", self.examples), + ("active", self.active), + ("is_trained", self.is_trained), + ] + ) def __init__( - self, name, description, mandatory, type, translation, example, position, active + self, name, mandatory, type, position, active, examples=None, is_trained=False ): self.name = name - self.description = description self.mandatory = mandatory self.type = type - self.translation = translation - self.example = example self.position = position self.active = active + self.examples = examples or [] + self.is_trained = is_trained diff --git a/project/backend/coordinator/model/seed_data.py b/project/backend/coordinator/model/seed_data.py index 28c65c0..ab5727a 100644 --- a/project/backend/coordinator/model/seed_data.py +++ b/project/backend/coordinator/model/seed_data.py @@ -10,153 +10,258 @@ def seed_default_kpi_settings(): default_kpi_settings = [ { "name": "Fondsname", - "description": "Der vollständige Name des Investmentfonds", "mandatory": True, "type": KPISettingType.STRING, - "translation": "Fund Name", - "example": "Alpha Real Estate Fund I", "position": 1, "active": True, + "is_trained": True, + "examples": [ + { + "sentence": "Der Fonds trägt den Namen Alpha Real Estate Fund I.", + "value": "Alpha Real Estate Fund I", + }, + { + "sentence": "Im Pitchbook wird der Fondsname als Alpha Real Estate Fund I angegeben.", + "value": "Alpha Real Estate Fund I", + }, + ], }, { "name": "Fondsmanager", - "description": "Verantwortlicher Manager für die Fondsverwaltung", "mandatory": True, "type": KPISettingType.STRING, - "translation": "Fund Manager", - "example": "Max Mustermann", "position": 2, "active": True, + "is_trained": True, + "examples": [ + { + "sentence": "Fondsmanager des Projekts ist Max Mustermann.", + "value": "Max Mustermann", + }, + { + "sentence": "Die Verwaltung liegt bei Max Mustermann.", + "value": "Max Mustermann", + }, + ], }, { "name": "AIFM", - "description": "Alternative Investment Fund Manager", "mandatory": True, "type": KPISettingType.STRING, - "translation": "AIFM", - "example": "Alpha Investment Management GmbH", "position": 3, "active": True, + "is_trained": True, + "examples": [ + { + "sentence": "AIFM ist die Alpha Investment Management GmbH.", + "value": "Alpha Investment Management GmbH", + }, + { + "sentence": "Die Alpha Investment Management GmbH fungiert als AIFM.", + "value": "Alpha Investment Management GmbH", + }, + ], }, { "name": "Datum", - "description": "Stichtag der Datenerfassung", "mandatory": True, "type": KPISettingType.DATE, - "translation": "Date", - "example": "05.05.2025", "position": 4, "active": True, + "is_trained": True, + "examples": [ + { + "sentence": "Die Daten basieren auf dem Stand vom 05.05.2025.", + "value": "05.05.2025", + }, + { + "sentence": "Stichtag der Angaben ist der 05.05.2025.", + "value": "05.05.2025", + }, + ], }, { "name": "Risikoprofil", - "description": "Klassifizierung des Risikos des Fonds", "mandatory": True, "type": KPISettingType.STRING, - "translation": "Risk Profile", - "example": "Core/Core++", "position": 5, "active": True, + "is_trained": True, + "examples": [ + { + "sentence": "Der Fonds hat das Risikoprofil Core/Core++.", + "value": "Core/Core++", + }, + { + "sentence": "Einstufung des Fondsrisikos: Core/Core++.", + "value": "Core/Core++", + }, + ], }, { "name": "Artikel", - "description": "Artikel 8 SFDR-Klassifizierung", "mandatory": False, "type": KPISettingType.BOOLEAN, - "translation": "Article", - "example": "Artikel 8", "position": 6, "active": True, + "is_trained": True, + "examples": [ + { + "sentence": "Der Fonds erfüllt die Anforderungen von Artikel 8.", + "value": "Artikel 8", + }, + { + "sentence": "Gemäß SFDR fällt dieser Fonds unter Artikel 8.", + "value": "Artikel 8", + }, + ], }, { "name": "Zielrendite", - "description": "Angestrebte jährliche Rendite in Prozent", "mandatory": True, "type": KPISettingType.NUMBER, - "translation": "Target Return", - "example": "6.5", "position": 7, "active": True, + "is_trained": True, + "examples": [ + { + "sentence": "Die angestrebte Zielrendite liegt bei 6.5%.", + "value": "6.5%", + }, + {"sentence": "Zielrendite des Fonds beträgt 6.5%.", "value": "6.5%"}, + ], }, { "name": "Rendite", - "description": "Tatsächlich erzielte Rendite in Prozent", "mandatory": False, "type": KPISettingType.NUMBER, - "translation": "Return", - "example": "5.8", "position": 8, "active": True, + "is_trained": True, + "examples": [ + { + "sentence": "Die Rendite für das Jahr beträgt 5.8%.", + "value": "5.8%", + }, + { + "sentence": "Im letzten Jahr wurde eine Rendite von 5.8% erzielt.", + "value": "5.8%", + }, + ], }, { "name": "Zielausschüttung", - "description": "Geplante Ausschüttung in Prozent", "mandatory": False, "type": KPISettingType.NUMBER, - "translation": "Target Distribution", - "example": "4.0", "position": 9, "active": True, + "is_trained": True, + "examples": [ + {"sentence": "Die Zielausschüttung beträgt 4.0%.", "value": "4.0%"}, + { + "sentence": "Geplante Ausschüttung: 4.0% pro Jahr.", + "value": "4.0%", + }, + ], }, { "name": "Ausschüttung", - "description": "Tatsächliche Ausschüttung in Prozent", "mandatory": False, "type": KPISettingType.NUMBER, - "translation": "Distribution", - "example": "3.8", "position": 10, "active": True, + "is_trained": True, + "examples": [ + { + "sentence": "Die Ausschüttung im Jahr 2024 lag bei 3.8%.", + "value": "3.8%", + }, + { + "sentence": "Es wurde eine Ausschüttung von 3.8% vorgenommen.", + "value": "3.8%", + }, + ], }, { "name": "Laufzeit", - "description": "Geplante Laufzeit des Fonds", "mandatory": True, "type": KPISettingType.STRING, - "translation": "Duration", - "example": "7 Jahre, 10, Evergreen", "position": 11, "active": True, + "is_trained": True, + "examples": [ + { + "sentence": "Die Laufzeit des Fonds beträgt 7 Jahre.", + "value": "7 Jahre", + }, + {"sentence": "Geplante Dauer: Evergreen-Modell.", "value": "Evergreen"}, + ], }, { "name": "LTV", - "description": "Loan-to-Value Verhältnis in Prozent", "mandatory": False, "type": KPISettingType.NUMBER, - "translation": "LTV", - "example": "65.0", "position": 12, "active": True, + "is_trained": True, + "examples": [ + {"sentence": "Der LTV beträgt 65.0%.", "value": "65.0%"}, + {"sentence": "Loan-to-Value-Ratio: 65.0%.", "value": "65.0%"}, + ], }, { "name": "Managementgebühren", - "description": "Jährliche Verwaltungsgebühren in Prozent", "mandatory": True, "type": KPISettingType.NUMBER, - "translation": "Management Fees", - "example": "1.5", "position": 13, "active": True, + "is_trained": True, + "examples": [ + { + "sentence": "Die Managementgebühren betragen jährlich 1.5%.", + "value": "1.5%", + }, + { + "sentence": "Für die Verwaltung wird eine Gebühr von 1.5% erhoben.", + "value": "1.5%", + }, + ], }, { "name": "Sektorenallokation", - "description": "Verteilung der Investments nach Sektoren", "mandatory": False, "type": KPISettingType.ARRAY, - "translation": "Sector Allocation", - "example": "Büro, Wohnen, Logistik, Studentenwohnen", "position": 14, "active": True, + "is_trained": True, + "examples": [ + { + "sentence": "Die Sektorenallokation umfasst Büro, Wohnen und Logistik.", + "value": "Büro, Wohnen, Logistik", + }, + { + "sentence": "Investiert wird in Büro, Logistik und Studentenwohnen.", + "value": "Büro, Logistik, Studentenwohnen", + }, + ], }, { "name": "Länderallokation", - "description": "Geografische Verteilung der Investments", "mandatory": False, "type": KPISettingType.ARRAY, - "translation": "Country Allocation", - "example": "Deutschland,Frankreich, Österreich, Schweiz", "position": 15, "active": True, + "is_trained": True, + "examples": [ + { + "sentence": "Investitionen erfolgen in Deutschland, Frankreich und Österreich.", + "value": "Deutschland, Frankreich, Österreich", + }, + { + "sentence": "Die Länderallokation umfasst Deutschland, Schweiz und Frankreich.", + "value": "Deutschland, Schweiz, Frankreich", + }, + ], }, ] @@ -165,13 +270,12 @@ def seed_default_kpi_settings(): for kpi_data in default_kpi_settings: kpi_setting = KPISettingModel( name=kpi_data["name"], - description=kpi_data["description"], mandatory=kpi_data["mandatory"], type=kpi_data["type"], - translation=kpi_data["translation"], - example=kpi_data["example"], position=kpi_data["position"], active=kpi_data["active"], + examples=kpi_data.get("examples", []), + is_trained=kpi_data["is_trained"], ) db.session.add(kpi_setting) diff --git a/project/backend/exxetaGPT-service/app.py b/project/backend/exxetaGPT-service/app.py index 9b1597b..4c97749 100644 --- a/project/backend/exxetaGPT-service/app.py +++ b/project/backend/exxetaGPT-service/app.py @@ -6,9 +6,12 @@ import json app = Flask(__name__) -VALIDATE_SERVICE_URL = os.getenv("VALIDATE_SERVICE_URL", "http://localhost:5054/validate") +VALIDATE_SERVICE_URL = os.getenv( + "VALIDATE_SERVICE_URL", "http://localhost:5054/validate" +) -@app.route('/extract', methods=['POST']) + +@app.route("/extract", methods=["POST"]) def extract_text_from_ocr_json(): json_data = request.get_json() @@ -16,19 +19,19 @@ def extract_text_from_ocr_json(): pages_data = json_data["extracted_text_per_page"] entities_json = extract_with_exxeta(pages_data, pitchbook_id) - entities = json.loads(entities_json) if isinstance(entities_json, str) else entities_json + entities = ( + json.loads(entities_json) if isinstance(entities_json, str) else entities_json + ) - validate_payload = { - "id": pitchbook_id, - "service": "exxeta", - "entities": entities - } + validate_payload = {"id": pitchbook_id, "service": "exxeta", "entities": entities} print(f"[EXXETA] Sending to validate service: {VALIDATE_SERVICE_URL}") print(f"[EXXETA] Payload: {validate_payload} entities for pitchbook {pitchbook_id}") try: - response = requests.post(VALIDATE_SERVICE_URL, json=validate_payload, timeout=600) + response = requests.post( + VALIDATE_SERVICE_URL, json=validate_payload, timeout=600 + ) print(f"[EXXETA] Validate service response: {response.status_code}") if response.status_code != 200: print(f"[EXXETA] Validate service error: {response.text}") diff --git a/project/backend/exxetaGPT-service/extractExxeta.py b/project/backend/exxetaGPT-service/extractExxeta.py index 3948c8b..94cc746 100644 --- a/project/backend/exxetaGPT-service/extractExxeta.py +++ b/project/backend/exxetaGPT-service/extractExxeta.py @@ -16,6 +16,7 @@ TIMEOUT = 180 logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__name__) + def get_dynamic_labels(): url = f"{COORDINATOR_URL}/api/kpi_setting/" try: @@ -28,6 +29,7 @@ def get_dynamic_labels(): logger.warning(f"Konnte dynamische Labels nicht laden: {e}") return [] + def extract_with_exxeta(pages_json, pitchbook_id): results = [] @@ -39,7 +41,10 @@ def extract_with_exxeta(pages_json, pitchbook_id): for page_data in pages_json: i += 1 if i % 8 == 0: - requests.post(COORDINATOR_URL + "/api/progress", json={"id": pitchbook_id, "progress": 35 + 60/len(pages_json)*i}) + requests.post( + COORDINATOR_URL + "/api/progress", + json={"id": pitchbook_id, "progress": 35 + 60 / len(pages_json) * i}, + ) page_num = page_data.get("page") text = page_data.get("text", "") @@ -100,23 +105,28 @@ def extract_with_exxeta(pages_json, pitchbook_id): headers = { "Content-Type": "application/json", - "Authorization": f"Bearer {EXXETA_API_KEY}" + "Authorization": f"Bearer {EXXETA_API_KEY}", } payload = { "model": MODEL, "messages": [ - {"role": "system", "content": "Du bist ein Finanzanalyst. Antworte ausschließlich mit einem validen JSON-Array."}, - {"role": "user", "content": prompt} + { + "role": "system", + "content": "Du bist ein Finanzanalyst. Antworte ausschließlich mit einem validen JSON-Array.", + }, + {"role": "user", "content": prompt}, ], - "temperature": 0.0 + "temperature": 0.0, } url = f"{EXXETA_BASE_URL}/deployments/{MODEL}/chat/completions" for attempt in range(1, MAX_RETRIES + 1): try: - response = requests.post(url, headers=headers, json=payload, timeout=TIMEOUT) + response = requests.post( + url, headers=headers, json=payload, timeout=TIMEOUT + ) response.raise_for_status() content = response.json()["choices"][0]["message"]["content"].strip() if content.startswith("```json"): @@ -140,9 +150,12 @@ def extract_with_exxeta(pages_json, pitchbook_id): if attempt == MAX_RETRIES: results.extend([]) - requests.post(COORDINATOR_URL + "/api/progress", json={"id": pitchbook_id, "progress": 95}) + requests.post( + COORDINATOR_URL + "/api/progress", json={"id": pitchbook_id, "progress": 95} + ) return json.dumps(results, indent=2, ensure_ascii=False) + if __name__ == "__main__": print("📡 Test-Aufruf get_dynamic_labels:") - print(get_dynamic_labels()) \ No newline at end of file + print(get_dynamic_labels()) diff --git a/project/backend/ocr-service/app.py b/project/backend/ocr-service/app.py index ba6c0ae..472a3d3 100644 --- a/project/backend/ocr-service/app.py +++ b/project/backend/ocr-service/app.py @@ -29,19 +29,17 @@ def convert_pdf_async(temp_path, pitchbook_id): temp_path.unlink() # cleanup return {"error": "OCR processing failed - all PDFs must be OCR'd"}, 500 - with open(ocr_path, 'rb') as ocr_file: + with open(ocr_path, "rb") as ocr_file: ocr_file.seek(0) result = pdf_to_json(ocr_file) - - payload = { - "id": int(pitchbook_id), - "extracted_text_per_page": result["pages"] - } + payload = {"id": int(pitchbook_id), "extracted_text_per_page": result["pages"]} logger.info("Sending payload to EXXETA and SPACY services") - requests.post(COORDINATOR_URL + "/api/progress", json={"id": pitchbook_id, "progress": 35}) + requests.post( + COORDINATOR_URL + "/api/progress", json={"id": pitchbook_id, "progress": 35} + ) try: exxeta_response = requests.post(EXXETA_URL, json=payload, timeout=600) logger.info(f"EXXETA response: {exxeta_response.status_code}") @@ -54,14 +52,16 @@ def convert_pdf_async(temp_path, pitchbook_id): except Exception as e: logger.error(f"Error calling SPACY: {e}") - files=[ - ('file',('',open(ocr_path,'rb'),'application/pdf')) - ] + files = [("file", ("", open(ocr_path, "rb"), "application/pdf"))] headers = {} try: - - requests.put(f"{COORDINATOR_URL}/api/pitch_book/{pitchbook_id}", files=files, timeout=600, headers=headers) + requests.put( + f"{COORDINATOR_URL}/api/pitch_book/{pitchbook_id}", + files=files, + timeout=600, + headers=headers, + ) logger.info("COORDINATOR response: Progress + File updated") except Exception as e: logger.error(f"Error calling COORDINATOR: {e}") @@ -72,7 +72,7 @@ def convert_pdf_async(temp_path, pitchbook_id): logger.error(f"Exception in OCR processing: {str(e)}", exc_info=True) -@app.route('/ocr', methods=['POST']) +@app.route("/ocr", methods=["POST"]) def convert_extract_text_from_pdf(): if "file" not in request.files: return {"error": "No file"}, 400 @@ -85,7 +85,7 @@ def convert_extract_text_from_pdf(): if not pitchbook_id: return {"error": "No ID"}, 400 - with tempfile.NamedTemporaryFile(delete=False, suffix='.pdf') as temp_file: + with tempfile.NamedTemporaryFile(delete=False, suffix=".pdf") as temp_file: file.seek(0) temp_file.write(file.read()) temp_path = Path(temp_file.name) @@ -93,10 +93,7 @@ def convert_extract_text_from_pdf(): thread = threading.Thread(target=convert_pdf_async, args=(temp_path, pitchbook_id)) thread.start() - return { - "status": "sent", - "message": "PDF successfully OCR'd and processed" - }, 200 + return {"status": "sent", "message": "PDF successfully OCR'd and processed"}, 200 if __name__ == "__main__": diff --git a/project/backend/ocr-service/ocr_runner.py b/project/backend/ocr-service/ocr_runner.py index 1ce9599..0b8abfa 100644 --- a/project/backend/ocr-service/ocr_runner.py +++ b/project/backend/ocr-service/ocr_runner.py @@ -17,9 +17,10 @@ log_folder = TEMP_DIR / "logs" output_folder.mkdir(exist_ok=True) log_folder.mkdir(exist_ok=True) + def pdf_to_json(pdf_input): try: - if hasattr(pdf_input, 'read'): + if hasattr(pdf_input, "read"): pdf_input.seek(0) with pdfplumber.open(pdf_input) as pdf: @@ -83,7 +84,9 @@ def ocr_pdf(input_file_path: Path): if result.returncode == 0: if output_file.exists(): - logger.info(f"OCR successful, output file size: {output_file.stat().st_size} bytes") + logger.info( + f"OCR successful, output file size: {output_file.stat().st_size} bytes" + ) return output_file else: logger.error(f"OCR completed but output file not found: {output_file}") @@ -119,4 +122,4 @@ def extract_text_to_json(pdf_path: Path): except Exception as e: logger.error(f"Failed to extract text to JSON: {e}") - return None \ No newline at end of file + return None diff --git a/project/backend/spacy-service/Dockerfile b/project/backend/spacy-service/Dockerfile index d7ad008..20d5817 100644 --- a/project/backend/spacy-service/Dockerfile +++ b/project/backend/spacy-service/Dockerfile @@ -11,6 +11,8 @@ COPY requirements.txt /app RUN pip install --upgrade pip RUN pip install --no-cache-dir -r requirements.txt +RUN pip install flask-cors + RUN python -m spacy download en_core_web_sm diff --git a/project/backend/spacy-service/app.py b/project/backend/spacy-service/app.py index 4e32067..706f7fc 100644 --- a/project/backend/spacy-service/app.py +++ b/project/backend/spacy-service/app.py @@ -1,14 +1,26 @@ from flask import Flask, request, jsonify -from extractSpacy import extract +from extractSpacy import extract, load_model import requests import os import json +from flask_cors import CORS +import shutil +import subprocess + + +training_status = {"running": False} + app = Flask(__name__) +CORS(app) -VALIDATE_SERVICE_URL = os.getenv("VALIDATE_SERVICE_URL", "http://localhost:5054/validate") +COORDINATOR_URL = os.getenv("COORDINATOR_URL", "http://coordinator:5000") +VALIDATE_SERVICE_URL = os.getenv( + "VALIDATE_SERVICE_URL", "http://localhost:5054/validate" +) -@app.route('/extract', methods=['POST']) + +@app.route("/extract", methods=["POST"]) def extract_pdf(): json_data = request.get_json() @@ -16,19 +28,19 @@ def extract_pdf(): pages_data = json_data["extracted_text_per_page"] entities_json = extract(pages_data) - entities = json.loads(entities_json) if isinstance(entities_json, str) else entities_json + entities = ( + json.loads(entities_json) if isinstance(entities_json, str) else entities_json + ) - validate_payload = { - "id": pitchbook_id, - "service": "spacy", - "entities": entities - } + validate_payload = {"id": pitchbook_id, "service": "spacy", "entities": entities} print(f"[SPACY] Sending to validate service: {VALIDATE_SERVICE_URL}") print(f"[SPACY] Payload: {validate_payload} entities for pitchbook {pitchbook_id}") try: - response = requests.post(VALIDATE_SERVICE_URL, json=validate_payload, timeout=600) + response = requests.post( + VALIDATE_SERVICE_URL, json=validate_payload, timeout=600 + ) print(f"[SPACY] Validate service response: {response.status_code}") if response.status_code != 200: print(f"[SPACY] Validate service error: {response.text}") @@ -38,5 +50,90 @@ def extract_pdf(): return jsonify("Sent to validate-service"), 200 +@app.route("/append-training-entry", methods=["POST"]) +def append_training_entry(): + entry = request.get_json() + + if not entry or "text" not in entry or "entities" not in entry: + return ( + jsonify( + {"error": "Ungültiges Format – 'text' und 'entities' erforderlich."} + ), + 400, + ) + + path = os.path.join("spacy_training", "annotation_data.json") + + try: + if os.path.exists(path): + with open(path, "r", encoding="utf-8") as f: + data = json.load(f) + else: + data = [] + + # Duplikate prüfen + if entry in data: + return jsonify({"message": "Eintrag existiert bereits."}), 200 + + data.append(entry) + with open(path, "w", encoding="utf-8") as f: + json.dump(data, f, indent=2, ensure_ascii=False) + + return jsonify({"message": "Eintrag erfolgreich gespeichert."}), 200 + except Exception as e: + print(f"[ERROR] Fehler beim Schreiben der Datei: {e}") + return jsonify({"error": "Interner Fehler beim Schreiben."}), 500 + + +@app.route("/train", methods=["POST"]) +def trigger_training(): + from threading import Thread + + Thread(target=run_training).start() + return jsonify({"message": "Training gestartet"}), 200 + + +@app.route("/reload-model", methods=["POST"]) +def reload_model(): + try: + load_model() + return jsonify({"message": "Modell wurde erfolgreich neu geladen."}), 200 + except Exception as e: + return ( + jsonify({"error": "Fehler beim Neuladen des Modells", "details": str(e)}), + 500, + ) + + +def run_training(): + training_status["running"] = True + notify_coordinator(True) + + try: + if os.path.exists("output/model-last"): + shutil.copytree( + "output/model-last", "output/model-backup", dirs_exist_ok=True + ) + subprocess.run(["python", "spacy_training/ner_trainer.py"], check=True) + load_model() + except Exception as e: + print("Training failed:", e) + training_status["running"] = False + notify_coordinator(False) + + +def notify_coordinator(running: bool): + try: + response = requests.post( + f"{COORDINATOR_URL}/api/spacy/training/status", json={"running": running} + ) + print( + f"[SPACY] Coordinator: running = {running}, Status = {response.status_code}" + ) + + except Exception as e: + print(f"[SPACY] Fehler beim Senden des Trainingsstatus: {e}") + + if __name__ == "__main__": - app.run(host="0.0.0.0", port=5052, debug=True) \ No newline at end of file + app.run(host="0.0.0.0", port=5052, debug=True) diff --git a/project/backend/spacy-service/extractSpacy.py b/project/backend/spacy-service/extractSpacy.py index 8ae4e31..0c607e4 100644 --- a/project/backend/spacy-service/extractSpacy.py +++ b/project/backend/spacy-service/extractSpacy.py @@ -2,9 +2,25 @@ import spacy import os import json + current_dir = os.path.dirname(os.path.abspath(__file__)) model_path = os.path.join(current_dir, "spacy_training/output/model-last") -nlp = spacy.load(model_path) + + +# Globales NLP-Modell +nlp = None + + +def load_model(): + global nlp + print("[INFO] Lade SpaCy-Modell aus spacy_training/output/model-last ...") + nlp = spacy.load("spacy_training/output/model-last") + print("[INFO] Modell erfolgreich geladen.") + + +# Initial einmal laden +load_model() + def extract(pages_json): results = [] @@ -19,10 +35,6 @@ def extract(pages_json): spacy_result = nlp(text) for ent in spacy_result.ents: - results.append({ - "label": ent.label_, - "entity": ent.text, - "page": page_num - }) + results.append({"label": ent.label_, "entity": ent.text, "page": page_num}) - return json.dumps(results, indent=2, ensure_ascii=False) \ No newline at end of file + return json.dumps(results, indent=2, ensure_ascii=False) diff --git a/project/backend/spacy-service/requirements.txt b/project/backend/spacy-service/requirements.txt index e78227c..e003cb3 100644 --- a/project/backend/spacy-service/requirements.txt +++ b/project/backend/spacy-service/requirements.txt @@ -3,4 +3,5 @@ spacy-transformers==1.3.3 transformers==4.35.2 torch flask -requests \ No newline at end of file +requests +flask-cors \ No newline at end of file diff --git a/project/backend/spacy-service/save_training_entry.py b/project/backend/spacy-service/save_training_entry.py new file mode 100644 index 0000000..5029c69 --- /dev/null +++ b/project/backend/spacy-service/save_training_entry.py @@ -0,0 +1,33 @@ +from flask import Flask, request, jsonify +import os +import json + +app = Flask(__name__) + +ANNOTATION_FILE = "spacy_training/annotation_data.json" + + +@app.route("/api/spacy-training-entry", methods=["POST"]) +def append_training_entry(): + new_entry = request.get_json() + + if not new_entry or "text" not in new_entry or "entities" not in new_entry: + return jsonify({"error": "Ungültiges Format"}), 400 + + # Bestehende Datei laden + if os.path.exists(ANNOTATION_FILE): + with open(ANNOTATION_FILE, "r", encoding="utf-8") as f: + data = json.load(f) + else: + data = [] + + # Duplikat vermeiden + if new_entry in data: + return jsonify({"message": "Eintrag bereits vorhanden."}), 200 + + # Anfügen + data.append(new_entry) + with open(ANNOTATION_FILE, "w", encoding="utf-8") as f: + json.dump(data, f, indent=2, ensure_ascii=False) + + return jsonify({"message": "Eintrag erfolgreich gespeichert."}), 200 diff --git a/project/backend/spacy-service/spacy_training/annotation_data.json b/project/backend/spacy-service/spacy_training/annotation_data.json new file mode 100644 index 0000000..398b146 --- /dev/null +++ b/project/backend/spacy-service/spacy_training/annotation_data.json @@ -0,0 +1,1562 @@ +[ + { + "text": "Core", + "entities": [ + [ + 0, + 4, + "RISIKOPROFIL" + ] + ] + }, + { + "text": "Core+", + "entities": [ + [ + 0, + 5, + "RISIKOPROFIL" + ] + ] + }, + { + "text": "Core/Core+", + "entities": [ + [ + 0, + 10, + "RISIKOPROFIL" + ] + ] + }, + { + "text": "Value Add", + "entities": [ + [ + 0, + 9, + "RISIKOPROFIL" + ] + ] + }, + { + "text": "Core/Value Add", + "entities": [ + [ + 0, + 14, + "RISIKOPROFIL" + ] + ] + }, + { + "text": "Core+/Value Add", + "entities": [ + [ + 0, + 15, + "RISIKOPROFIL" + ] + ] + }, + { + "text": "Core/Core+/Value Add", + "entities": [ + [ + 0, + 20, + "RISIKOPROFIL" + ] + ] + }, + { + "text": "The RE portfolio of the fund is a good illustration of Fond expertise in European core/core+ investments .", + "entities": [ + [ + 82, + 92, + "RISIKOPROFIL" + ] + ] + }, + { + "text": "Risk level: Core/Core+", + "entities": [ + [ + 12, + 22, + "RISIKOPROFIL" + ] + ] + }, + { + "text": "Different risk profile (core, core+, value-added)", + "entities": [ + [ + 24, + 48, + "RISIKOPROFIL" + ] + ] + }, + { + "text": "Core/Core+ with OpCo premium", + "entities": [ + [ + 0, + 10, + "RISIKOPROFIL" + ] + ] + }, + { + "text": "Core /Core+ Assets, well-established = Key Gateway Cities in Europe le.g. hotels in the market with minor asset London, Paris, Amsterdam, Berlin] management initiatives", + "entities": [ + [ + 0, + 11, + "RISIKOPROFIL" + ] + ] + }, + { + "text": "Risikoprofil: Core, Core +", + "entities": [ + [ + 14, + 26, + "RISIKOPROFIL" + ] + ] + }, + { + "text": "Name des Fonds Name des Investmentmanagers Allgemeine Informationen Name des Ansprechpartners Telefonnummer des Ansprechpartners E-Mail des Ansprechpartners Art des Anlagevehikels Struktur des Anlagevehikels Sitz des Anlagevehikels Struktur des Antagevehikels vom Manager festgelegter Stil Rechtsform Jahr des ersten Closings Laufzeit Geplantes Jahr der Auflösung Ziel-Netto-IRR / Gesamtrendite* Zielvolumen des Anlagevehikels Ziel-LTY ‚Aktueller LTV Ziirraiaein Maximaler LTV Zielregionfen)/Jand Zielsektoren Zielanlagestrategie INREV Fonds Offen Deutschland Core, Core + Offener Immobilien-Spezialfonds 2022 10 - 12 Jahre 2032 - 2034 7,50%+ 250 Mio. € 20% 0% 20% Führende Metropolregionen Deutschlands und ausgewählte Standorte >50T Einw. Wohnimmobilien Wertstabile Wohnimmobilien (mit Bestandsentwicklungen)", + "entities": [ + [ + 560, + 572, + "RISIKOPROFIL" + ] + ] + }, + { + "text": "Core/Core+ strategy, with tactical exposure to development projects aiming at enhancing the quality of the portfolio over time", + "entities": [ + [ + 0, + 10, + "RISIKOPROFIL" + ] + ] + }, + { + "text": "Strategie - Übersicht Risikoprofil Core+ Halten-Strategie Kaufen — Halten (langfristig) — Exit 1. Nachvermietungsstrategie Anlagestrategien 2. Standortaufwertungsstrategie 3. Strategie der Aufwertung der Immobilien Niederlande (max. 35 %) Länderallokation Frankreich (max. 35 %) (in % vom Zielvolumen) Skandinavien (Schweden, Dänemark) (max. 35 %) Deutschland (<= 10 %)", + "entities": [ + [ + 35, + 40, + "RISIKOPROFIL" + ] + ] + }, + { + "text": "Core and Core+", + "entities": [ + [ + 0, + 14, + "RISIKOPROFIL" + ] + ] + }, + { + "text": "core, core+, value-added", + "entities": [ + [ + 0, + 24, + "RISIKOPROFIL" + ] + ] + }, + { + "text": "Manage to Core: max 20%", + "entities": [ + [ + 10, + 14, + "RISIKOPROFIL" + ] + ] + }, + { + "text": "Benefits of the core/ core+ segment", + "entities": [ + [ + 16, + 27, + "RISIKOPROFIL" + ] + ] + }, + { + "text": "Drawbacks of the core/ core+ segment", + "entities": [ + [ + 17, + 28, + "RISIKOPROFIL" + ] + ] + }, + { + "text": "Why a Core / Core + investment program?", + "entities": [ + [ + 6, + 19, + "RISIKOPROFIL" + ] + ] + }, + { + "text": "Different risk profile (core, core+, value-added)", + "entities": [ + [ + 24, + 48, + "RISIKOPROFIL" + ] + ] + }, + { + "text": "INK MGallery Hotel Area: Amsterdam Core Tenant: Closed in 2018", + "entities": [ + [ + 35, + 39, + "RISIKOPROFIL" + ] + ] + }, + { + "text": "A strategy targeting high quality Core and Core+ buildings, with defined SRI objectives, in order to extract value through an active asset management.", + "entities": [ + [ + 34, + 48, + "RISIKOPROFIL" + ] + ] + }, + { + "text": "Navigate the diversity of the Core/Core+ investment opportunities in European Prime Cities", + "entities": [ + [ + 30, + 40, + "RISIKOPROFIL" + ] + ] + }, + { + "text": "GEDis an open-ended Lux-based fund providing an attractive core/core+ real estate exposure, leveraging GRRE expertise in European RE markets. It offers diversification in terms of pan-European geographies and sectors: Offices, Retail and Hotels.", + "entities": [ + [ + 59, + 69, + "RISIKOPROFIL" + ] + ] + }, + { + "text": "Core assets leave less room for active asset management value creation", + "entities": [ + [ + 0, + 4, + "RISIKOPROFIL" + ] + ] + }, + { + "text": "capital preservation is defined here as a characteristic of core/core+ investments. There is no guarantee of capital.", + "entities": [ + [ + 60, + 70, + "RISIKOPROFIL" + ] + ] + }, + { + "text": "Country / city BELGIUM Brussels BELGIUM Brussels SPAIN Madrid FRANCE Levallois FRANCE Paris 14 BELGIUM Brussels NETHERLANDS Rotterdam NETHERLANDS Rotterdam Sector Offices Offices Offices Offices Offices Offices Offices Logistics Risk Core", + "entities": [ + [ + 234, + 238, + "RISIKOPROFIL" + ] + ] + }, + { + "text": "GERD(a balanced pan-European open ended retail fund — under the form of a French collective undertaking for Real Estate investments “OPCI”) is the flagship ofQin France and combines RE and listed assets (respective targets of 60% and 40%) with max. 40% leverage. The RE portfolio of the fund is a good illustration Of expertise in European core/core+ investments.", + "entities": [ + [ + 340, + 350, + "RISIKOPROFIL" + ] + ] + }, + { + "text": "Prime office assets in Prime markets are very pricey unless rent reversion is real. Risk premium remains attractive on a leveraged basis. Manage to core or build to core can make sense as a LT investor in main cities. Residential is also attractive", + "entities": [ + [ + 148, + 152, + "RISIKOPROFIL" + ] + ] + }, + { + "text": "Paris region is a deep and liquid market. Rents have some potential to improve. Considering current low yield and fierce competition, office right outside CBD for Core + assets can be considered. Manage to core strategies could make sense.", + "entities": [ + [ + 163, + 169, + "RISIKOPROFIL" + ] + ] + }, + { + "text": "Lisbon is a small market but it experienced a rapid economic recovery in recent years and is interesting for Core Offices, quality Retail assetor Hotel walls with top operators. Limited liquidity of this market means investment must be small", + "entities": [ + [ + 109, + 113, + "RISIKOPROFIL" + ] + ] + }, + { + "text": "4,0 %", + "entities": [ + [ + 0, + 5, + "AUSSCHÜTTUNGSRENDITE" + ] + ] + }, + { + "text": "Prognostizierte jährliche Ausschüttung von 4,0%", + "entities": [ + [ + 44, + 48, + "AUSSCHÜTTUNGSRENDITE" + ] + ] + }, + { + "text": "20% über einer @ Ausschüttungsrendite von 4,0%", + "entities": [ + [ + 44, + 48, + "AUSSCHÜTTUNGSRENDITE" + ] + ] + }, + { + "text": "Prognostizierte Ausschüttungsrandite* Mindestanlage Mitgliedschaft Im Anlagesusschuss Ankaufs- / Verkaufs- / Verkaufs(Teflimmobilfe)- / Baumanagementgebahr (inkl. USt.) Parformanceabhängige Vergütung Einmalige Strukturierungsgebühr Laufzeit / Investtionszeltraum Ausschüttungsintervalle Deutsche Metropolregianen und umliegende Regionen mit Städten >50T Einwohner Artikel 8 Wohnimmobilien Deutschland ‚Aktive Bestandsentwicklung Offener Spezial-AlF mit festen Anlagebedingungen rd. 200 Mio. € / max. 20% rd. 250 Mio. € 7,5 % (nach Kosten & Gebühren, vor Steuern) 8 4,0 % {nach Kosten & Gebühren, var Steuern}", + "entities": [ + [ + 570, + 575, + "AUSSCHÜTTUNGSRENDITE" + ] + ] + }, + { + "text": "5,00-5,25 % Ausschüttungsrendite", + "entities": [ + [ + 0, + 11, + "AUSSCHÜTTUNGSRENDITE" + ] + ] + }, + { + "text": "Zielrendite 5,00-5,25 % Ausschüttungsrendite", + "entities": [ + [ + 12, + 23, + "AUSSCHÜTTUNGSRENDITE" + ] + ] + }, + { + "text": "Auschüttungsrendite 4,9% 5,3%", + "entities": [ + [ + 21, + 25, + "AUSSCHÜTTUNGSRENDITE" + ] + ] + }, + { + "text": "Auschüttungsrendite 4,9% 5,3%", + "entities": [ + [ + 26, + 30, + "AUSSCHÜTTUNGSRENDITE" + ] + ] + }, + { + "text": "Auschittungsrendite 3,8% 5,7%", + "entities": [ + [ + 20, + 24, + "AUSSCHÜTTUNGSRENDITE" + ] + ] + }, + { + "text": "Auschittungsrendite 3,8% 5,7%", + "entities": [ + [ + 25, + 29, + "AUSSCHÜTTUNGSRENDITE" + ] + ] + }, + { + "text": "Auschüttungsrendite 4,5% 4,6%", + "entities": [ + [ + 21, + 25, + "AUSSCHÜTTUNGSRENDITE" + ] + ] + }, + { + "text": "Auschüttungsrendite 4,5% 4,6%", + "entities": [ + [ + 26, + 30, + "AUSSCHÜTTUNGSRENDITE" + ] + ] + }, + { + "text": "Auschüttungsrendite 5,0% 4,7%", + "entities": [ + [ + 26, + 30, + "AUSSCHÜTTUNGSRENDITE" + ] + ] + }, + { + "text": "Auschüttungsrendite 5,0% 4,7%", + "entities": [ + [ + 21, + 25, + "AUSSCHÜTTUNGSRENDITE" + ] + ] + }, + { + "text": "Auschüttungsrendite “eons a Nuremberg aha 5,0 % 4,8 %", + "entities": [ + [ + 43, + 48, + "AUSSCHÜTTUNGSRENDITE" + ] + ] + }, + { + "text": "Auschüttungsrendite “eons a Nuremberg aha 5,0 % 4,8 %", + "entities": [ + [ + 49, + 54, + "AUSSCHÜTTUNGSRENDITE" + ] + ] + }, + { + "text": "3-4% dividend yield", + "entities": [ + [ + 0, + 4, + "AUSSCHÜTTUNGSRENDITE" + ] + ] + }, + { + "text": "Zielmärkte Klassifizierung SFDR Invastitionsfokus Rendite- / Risikoprofil Rechtsform Eigenkapital /FK Quote Investftionsvolumen Prognostizierte Gesamtrendite {IRR)* Prognostizierte Ausschüttungsrandite* Mindestanlage Mitgliedschaft Im Anlagesusschuss Ankaufs- / Verkaufs- / Verkaufs(Teflimmobilfe)- / Baumanagementgebahr (inkl. USt.) Parformanceabhängige Vergütung Einmalige Strukturierungsgebühr Deutsche Metropolregianen und umliegende Regionen mit Städten >50T Einwohner Artikel 8 Wohnimmobilien Deutschland ‚Aktive Bestandsentwicklung Offener Spezial-AlF mit festen Anlagebedingungen rd. 200 Mio. € / max. 20% rd. 250 Mio. € 7,5 % (nach Kosten & Gebühren, vor Steuern) 8 4,0 % {nach Kosten & Gebühren, var Steuern} 5Mio.€ Ab 10 Mio. € 1,40 % / 0,80 % /2,12% / 4,91 % Laufzeit / Investtionszeltraum Ausschüttungsintervalle 20 % über einer @ Ausschüttungsrendite von 4,0 % 0,1% der bis zum 31.12.2023 erfolgten Kapitalzusagen (max. 200.000 &) 10 bis 12 Jahre / bis zu 24 Monate angestrebt Mindestens jährlich", + "entities": [ + [ + 945, + 960, + "LAUFZEIT" + ] + ] + }, + { + "text": "10-12 Jahre Laufzeit bei einem LTV von bis zu 20%", + "entities": [ + [ + 0, + 11, + "LAUFZEIT" + ] + ] + }, + { + "text": "vom Manager festgelegter Stil Rechtsform Jahr des ersten Closings Laufzeit Geplantes Jahr der Auflösung Ziel-Netto-IRR / Gesamtrendite* Zielvolumen des Anlagevehikels Ziel-LTY‚Aktueller LTV Zielsektoren Zielanlagestrategie Fonds Offen Deutschland Core, Core + Offener Immobilien-Spezialfonds 2022 10 - 12 Jahre", + "entities": [ + [ + 297, + 310, + "LAUFZEIT" + ], + [ + 247, + 259, + "RISIKOPROFIL" + ] + ] + }, + { + "text": "Allgemeine Annahmen Ankaufsphase Haltedauer Zielobjektgröße Finanzierung Investitions-annahmen Zielrendite 24 Monate Investmentzeitraum 10 Jahre (+) EUR 20-75 Mio. Keine externe Finanzierung zum Auftakt (ausschließlich Darlehen der Anteilseigner). Die Finanzierung wird nach der Ankaufsphase und Stabilisierung der Zinssätze neu geprüft. Angestrebter LTV zwischen 25-40 % Investitionen für Renovierungen und ESG- Verbesserungen werden für jedes Objekt einzeln festgelegt. 5,00-5,25 % Ausschüttungsrendites", + "entities": [ + [ + 136, + 148, + "LAUFZEIT" + ], + [ + 472, + 483, + "AUSSCHÜTTUNGSRENDITE" + ] + ] + }, + { + "text": "Zielrendite 5,00-5,25 % Ausschüttungsrendite 1) Ankauf von Objekten an Tag eins mit 100% Eigenkapital. Die Strategie unterstellt die Aufnahme von Fremdkapital, sobald sich die Zins- und Finanzierungskonditionen nachhaltig stabilisieren. Strategie - Übersicht Risikoprofil Core+", + "entities": [ + [ + 12, + 23, + "AUSSCHÜTTUNGSRENDITE" + ], + [ + 272, + 277, + "RISIKOPROFIL" + ] + ] + }, + { + "text": "Vehicle lifetime / investment period Open-ended fund", + "entities": [ + [ + 37, + 52, + "LAUFZEIT" + ] + ] + }, + { + "text": "Vehicle type (Lux-RAIF) (net of fees) IRR6.5% ACCOR Vehicle structure Open-ended Targetvehiclesize € 400m (equity) Manager-defined Core/Core+ with | style OpCo Premium darge CLV. 50% Pt H | LTO N WORLDWIDE Year of first closing 2020 Target no. ofinvestors 1-5 Fund life (yrs} Open-ended Min-commitmentper —¢ 400m", + "entities": [ + [ + 131, + 141, + "RISIKOPROFIL" + ], + [ + 70, + 80, + "LAUFZEIT" + ] + ] + }, + { + "text": "Fund term: Open-ended", + "entities": [ + [ + 11, + 21, + "LAUFZEIT" + ] + ] + }, + { + "text": "Abdeckung der Risiko-Rendite-Bandbreite (Core, Core+, Value-Add)", + "entities": [ + [ + 41, + 63, + "RISIKOPROFIL" + ] + ] + }, + { + "text": "5,1% - 8,5% IRR!", + "entities": [ + [ + 0, + 11, + "RENDITE" + ] + ] + }, + { + "text": "Retailinvestitionsvolumen nach Ländern (2024) Vereinigtes Königreich, 26,4% Deutschland, 19,0% Andere, 19,7% Italien, 8,2% Irland, 3,3% N | Frankreich, Spanien, 8,1%", + "entities": [ + [ + 46, + 75, + "LÄNDERALLOKATION" + ], + [ + 76, + 94, + "LÄNDERALLOKATION" + ], + [ + 95, + 108, + "LÄNDERALLOKATION" + ], + [ + 109, + 122, + "LÄNDERALLOKATION" + ], + [ + 123, + 135, + "LÄNDERALLOKATION" + ] + ] + }, + { + "text": "Erwartete IRR 5 (je nach Objekt- ‘A(E) 6.00% - 8,00%", + "entities": [ + [ + 39, + 52, + "RENDITE" + ] + ] + }, + { + "text": "Zielmarkts Deutsche Metropolregianen und umliegende Regionen mit Städten >50T Einwohner Klassifizierung SFDR Artikel 8 Invastitionsfokus Wohnimmobilien Deutschland Rendite- / Risikoprofil ‚Aktive Bestandsentwicklung Rechtsform Offener Spezial-AlF mit festen Anlagebedingungen Eigenkapital /FK Quote rd. 200 Mio. € / max. 20% Investftionsvolumen rd. 250 Mio. € Prognostiderte Gesamtrendite {IRR)* 7,5 % (nach Kosten & Gebühren, vor Steuern) Prognostizierte Ausschüttungsrandite* @ 4,0 % {nach Kosten & Gebühren, var Steuern} Mindestanlage 5Mio.€ Mitgliedschaft Im Anlagesusschuss Ab 10 Mio. € Ankaufs- / Verkaufs- / Verkaufs(Teflimmobilfe)- / Baumanagementgebahr (inkl. USt) 1,40 %/080%/212%/491% Parformanceabhängige Vergütung 20 % über einer ® Ausschüttungsrendite von 4,0% Einmalige Strukturierungsgebühr 0,1% der bis zum 31.12.2023 erfolgten Kapitalzusagen (max. 200.000 €) Laufzelt / Investtonszeltraum 10 bis 12 Jahre / bis zu 24 Monate angestrebt Ausschüttungsintervalle Mindestens jährlich", + "entities": [ + [ + 396, + 401, + "RENDITE" + ], + [ + 482, + 487, + "AUSSCHÜTTUNGSRENDITE" + ], + [ + 914, + 929, + "LAUFZEIT" + ] + ] + }, + { + "text": "= Prognostizierte jährliche Ausschüttung von @ 4,0%* = Prognostizierte Gesamtrendite (IRR) von 7,5%*", + "entities": [ + [ + 48, + 52, + "AUSSCHÜTTUNGSRENDITE" + ], + [ + 96, + 100, + "RENDITE" + ] + ] + }, + { + "text": "= Lagefokussierung: Metropolregionen Deutschlands = Finanzierung: max. 20% LTV = Risikoprofil: Core, Core +", + "entities": [ + [ + 95, + 107, + "RISIKOPROFIL" + ] + ] + }, + { + "text": "Performance-Fee: 20% über einer @ Ausschüttungsrendite von 4,0%", + "entities": [ + [ + 61, + 65, + "AUSSCHÜTTUNGSRENDITE" + ] + ] + }, + { + "text": "Fondstyp Offener Spezial-AIF nach KAGB mit festen Anlagebedingungen ESG-Klassifizierung Fonds gemäß Artikel 8 EU-Offenlegungsverordnung KVG IntReal GmbH, Hamburg Anlagestrategie Aufbau eines Objektportfolios aus Ärztehäusern, die langfristig vermietet sind Ärztehäuser, Laborimmobilien, im Verbund mit Ärztehäusern auch ambulant Zielobjekte betreute Wohngemeinschaften; Mietanteil Medizin und medizinnahe Dienstleistungen/Handel > 65 % (Objektebene) WALT >5 Jahre bei Ankauf Objektbaujahre Ab 2000 Anlagegrenzen Einzelinvestment 8-30 Mio. EUR Anzahl Objekte 10-20 Deutschland bundesweit; jeweiliges Einzugsgebiet > 25.000 Einwohner mit Regionen stabiler Bevölkerungsprognose Risikoprofil Core / Core +", + "entities": [ + [ + 689, + 702, + "RISIKOPROFIL" + ] + ] + }, + { + "text": "Fondsvolumen 300 Mio. EUR Zielrendite (IRR) > 6,0 % p. a. Ausschuttung >5,0 % p. a. Ankaufszeitraum 2024-2026 Laufzeit 31.12.2036 Mindestanlage 10 Mio. EUR Anlageausschuss Ja, entscheidet u. a. über Objekterwerb (Mitglied kann ab 20 Mio. EUR gestellt werden) Gebührenstruktur Marktüblich (auf Anfrage) Projektentwicklungen keine Forward-Deals Möglich, maximal 18 Monate Vorlauf; keine Projektentwicklungsrisiken beim Fonds Erbbaurechte Möglich, sofern Laufzeit > 60 Jahre und angemessene Entschädigung bei Ablauf und Heimfall Status Objektpipeline vorhanden: siehe Folie 16 ff.", + "entities": [ + [ + 44, + 57, + "RENDITE" + ], + [ + 71, + 83, + "AUSSCHÜTTUNGSRENDITE" + ], + [ + 120, + 130, + "LAUFZEIT" + ] + ] + }, + { + "text": "Niederlande (max. 35 %) Länderallokation Frankreich (max. 35 %) (in % vom Zielvolumen) Skandinavien (Schweden, Dänemark) (max. 35 %) Deutschland (<= 10 %)", + "entities": [ + [ + 0, + 23, + "LÄNDERALLOKATION" + ], + [ + 41, + 63, + "LÄNDERALLOKATION" + ], + [ + 87, + 132, + "LÄNDERALLOKATION" + ], + [ + 133, + 154, + "LÄNDERALLOKATION" + ] + ] + }, + { + "text": "Führender Immobilien-Investmentmanager in den Nordics für globale ll institutionelle Investoren in Value Add und Core Strategien", + "entities": [ + [ + 101, + 119, + "RISIKOPROFIL" + ] + ] + }, + { + "text": "Core und Core+ Fonds", + "entities": [ + [ + 0, + 14, + "RISIKOPROFIL" + ] + ] + }, + { + "text": "Risikoprofil Core / Core+", + "entities": [ + [ + 13, + 25, + "RISIKOPROFIL" + ] + ] + }, + { + "text": "Durchschnittlich geplante jährliche Ausschüttung von 4,5-5,5% auf das investierte Eigenkapital an die Anleger Geplante Gesamtrendite von 5-6% (IRR) auf das eingezahlte Eigenkapital", + "entities": [ + [ + 54, + 62, + "AUSSCHÜTTUNGSRENDITE" + ], + [ + 138, + 142, + "RENDITE" + ] + ] + }, + { + "text": "Geografische Zielallokation nach Investitionsphase des Fonds: 1) Schweden 20-60% Allokation Länder 2) Finnland 20-60% 3) Norwegen 10-40% 4) Dänemark 10-40%", + "entities": [ + [ + 65, + 80, + "LÄNDERALLOKATION" + ], + [ + 102, + 117, + "LÄNDERALLOKATION" + ], + [ + 121, + 136, + "LÄNDERALLOKATION" + ], + [ + 140, + 155, + "LÄNDERALLOKATION" + ] + ] + }, + { + "text": "Deutsches Spezial-Sondervermögen mit festen Anlagebedingungen ($284 KAGB) Immobilien- oder Infrastrukturquote (nach Solvency II) Core / Core+ Euro Hauptstadtregionen und andere Großstädte in den Nordics €500 Mio. 4,5-5,5% 15 Jahre; Fonds hat unbegrenzte Laufzeit; Investmentphase 4 Jahre Maximaler Fremdkapitalanteil 50% (LTV-Ziel bei Ankauf), Langfristiges LTV-Ziel auf Fondsebene ist 45% 0,625% p. a. des Bruttofondsvermögens Zeichnungen ab € 30 Mio. - 0,03 % Rabatt Zeichnungen ab € 50 Mio. - zusatzl. 0,03 % Rabatt 1,1% des Verkehrswertes 0,6% der Bruttoverkaufswert 10% wenn Hurdle Rate 5,0 % p. a. (IRR netto) überschritten wird (nach 15 Jahren berechnet) Ja", + "entities": [ + [ + 129, + 141, + "RISIKOPROFIL" + ], + [ + 213, + 221, + "ZIELRENDITE" + ], + [ + 242, + 262, + "LAUFZEIT" + ] + ] + }, + { + "text": "Standort Helsinki, Finnland Sektor Bildungswesen, Schule& Kindertagesstätte Vermietbare Fläche 3.321 m? Leerstand bei Ankauf 0% / 0% Ankaufspreis+ Investitionen €21,4 Mio. + €0,2 Mio Eigenkapital €21,6 Mio. Ankaufs- / Stabilisierungs- / Exitrendite 5,0%/ 5,5%/ 5,0% NOI zum Ankaufszeitpunkt / Exit-NOI €1.1m/ €1.2m Zielrenditen (netto für LPs) 5,4% IRR/ 1.5x EM / DY 4,3% Ankauf / Exit Dezember 2023/ Dezember 2033", + "entities": [ + [ + 345, + 349, + "ZIELRENDITE" + ] + ] + }, + { + "text": "Evergreen/offene Fondsstrukturenv Core / Core+ Strategien", + "entities": [ + [ + 34, + 46, + "RISIKOPROFIL" + ] + ] + }, + { + "text": "BEE Henderson German 2012 Logistik Core/D/Art. 8 € 336 Mio. 12 (voll investiert) 13,0 % p.a.", + "entities": [ + [ + 35, + 39, + "RISIKOPROFIL" + ], + [ + 81, + 87, + "RENDITE" + ] + ] + }, + { + "text": "ICF German Logistics 2014 Logistik Core/D/Art. 8 € 400 Mio. 16 (voll investiert) 12,0 % p.a.", + "entities": [ + [ + 35, + 39, + "RISIKOPROFIL" + ], + [ + 81, + 87, + "RENDITE" + ] + ] + }, + { + "text": "Individualmandat 2015 Logistik Core / D+AU/ ArTt. 6 € 200 Mio. 8 (realisiert) 8,0 % p.a.", + "entities": [ + [ + 31, + 35, + "RISIKOPROFIL" + ], + [ + 78, + 83, + "RENDITE" + ] + ] + }, + { + "text": "European Logistics Partnership” 2017 Logistik Value-Add / Europ/a - € 1.000 Mio. 28 (realisiert) 20,0 % p.a.", + "entities": [ + [ + 46, + 55, + "RISIKOPROFIL" + ], + [ + 97, + 103, + "RENDITE" + ] + ] + }, + { + "text": "European Core Logistics Fund (ECLF 1) 2021 Logistik Core / Euro/p Arat. 8 € 314 Mio. 12 (voll investiert) 7,50 % p.a.", + "entities": [ + [ + 9, + 13, + "RISIKOPROFIL" + ], + [ + 106, + 112, + "RENDITE" + ] + ] + }, + { + "text": "P-Logistik Europa Fonds (ECLF 2) 2022 Logistik Core / Euro/p Arat. 8 € 150 Mio.? A (voll investiert) 6,5 % p.a.?", + "entities": [ + [ + 47, + 51, + "RISIKOPROFIL" + ], + [ + 101, + 106, + "RENDITE" + ] + ] + }, + { + "text": "First Business Parks 2015 Light Industrial Value Add / D+AUT € 100 Mio. 6 (realisiert) 16,0 % p.a.", + "entities": [ + [ + 43, + 52, + "RISIKOPROFIL" + ], + [ + 87, + 93, + "RENDITE" + ] + ] + }, + { + "text": "Unternehmensimmobilien Club 1 2016 Light Industrial Core+/D € 186 Mio. 9 (voll investiert) 13,0 % p.a.", + "entities": [ + [ + 91, + 97, + "RENDITE" + ] + ] + }, + { + "text": "Individualmandat 2022 Light Industrial Value-Add / Nordics € 100 Mio. 5 (voll investiert) 18,0 % p.a.", + "entities": [ + [ + 39, + 48, + "RISIKOPROFIL" + ], + [ + 90, + 96, + "RENDITE" + ] + ] + }, + { + "text": "EUROPEAN CORE LOGISTICS FUND 3", + "entities": [ + [ + 9, + 13, + "RISIKOPROFIL" + ] + ] + }, + { + "text": "Core Investitionen", + "entities": [ + [ + 0, + 4, + "RISIKOPROFIL" + ] + ] + }, + { + "text": "8 % IRR", + "entities": [ + [ + 0, + 3, + "RENDITE" + ] + ] + }, + { + "text": "Rendite-Risiko-Profil Core ° Geographischer Fokus Kontinentaleuropaische Kernvolkswirtschaften nach Allokationsprofil * Sektoraler Fokus Logistikimmobilien nach Allokationsprofil Kapitalstruktur ° Eigenkapital € 250 Mio. ° Fremdkapital 50 % angestrebt, max. 60 % der Immobilienwerte (Objektebene) °e Mindestzeichnung € 10 Mio. Vehikelstruktur ° Rechtsform Immobilien-Spezial-AlF mit festen Anlagebedingungen nach 3 284 KAGB ° Klassifikation Artikel 8 Offenlegungsverordnung ¢ Anlagehorizont 10 Jahre mit Verlängerungsoption um 2 Jahre! ° Geplante Auflage 01 2025 Performanceziel? ° Ausschüttung 6,0 % p.a. (Durchschnitt 10 Jahre Haltedauer) ° Interner Zinsfuß (IRR) 8,0 % p.a. (10 Jahre Haltedauer, Target-IRR)", + "entities": [ + [ + 22, + 26, + "RISIKOPROFIL" + ], + [ + 596, + 601, + "AUSSCHÜTTUNGSRENDITE" + ], + [ + 667, + 672, + "RENDITE" + ] + ] + }, + { + "text": "Core/Core+, mit Cash-Flow-Stabilität", + "entities": [ + [ + 0, + 10, + "RISIKOPROFIL" + ] + ] + }, + { + "text": "Zielausschüttung: min. 5,10%", + "entities": [ + [ + 24, + 29, + "ZIELAUSSCHÜTTUNG" + ] + ] + }, + { + "text": "Zielrendite (IRR): min. 5,50%", + "entities": [ + [ + 24, + 29, + "ZIELRENDITE" + ] + ] + }, + { + "text": "Rewe & Lidl Maxhütte-Haidhof é ae: 6 s Bahnhof Ankermieter REWE & Lidl er WALT 20 und 17 Jahre Miete p.a. 1.127.916 € Kaufpreis 21,43 Mio. € Faktor 19,00 x LTV / Zins 80% / 4,0% Ausschüttung 5,7 % IRR 7,1%", + "entities": [ + [ + 193, + 198, + "AUSSCHÜTTUNGSRENDITE" + ], + [ + 203, + 207, + "ZIELRENDITE" + ] + ] + }, + { + "text": "Real Estate Prime Europe Access the Core of European Prime Cities with a green SRI fund including a genuine low carbon commitment", + "entities": [ + [ + 36, + 40, + "RISIKOPROFIL" + ] + ] + }, + { + "text": "(FR, UK, DE, BE, NL, LU, Nordics, Allocation SP, IT, CH)", + "entities": [ + [ + 1, + 32, + "LÄNDERALLOKATION" + ], + [ + 45, + 55, + "LÄNDERALLOKATION" + ] + ] + }, + { + "text": "IRR: 6% - 7%", + "entities": [ + [ + 5, + 12, + "RENDITE" + ] + ] + }, + { + "text": "Europe | Germany 67 Value Add", + "entities": [ + [ + 9, + 16, + "LÄNDERALLOKATION" + ], + [ + 20, + 29, + "RISIKOPROFIL" + ] + ] + }, + { + "text": "Germany, Norway 336 Core Plus", + "entities": [ + [ + 0, + 7, + "LÄNDERALLOKATION" + ], + [ + 20, + 29, + "RISIKOPROFIL" + ] + ] + }, + { + "text": "UK", + "entities": [ + [ + 0, + 2, + "LÄNDERALLOKATION" + ] + ] + }, + { + "text": "NORWAY", + "entities": [ + [ + 0, + 6, + "LÄNDERALLOKATION" + ] + ] + }, + { + "text": "9.8% IRR", + "entities": [ + [ + 0, + 4, + "RENDITE" + ] + ] + }, + { + "text": "Investment volume down 52% to €2.3 billion, with 4,000 100 14% value-add and core-plus increasing YoY", + "entities": [ + [ + 63, + 86, + "RISIKOPROFIL" + ] + ] + }, + { + "text": "Geared Gross IRR‘ seeking a range of 16-18% per annum", + "entities": [ + [ + 37, + 43, + "RENDITE" + ] + ] + }, + { + "text": "Open-ended fund 24 months, incl. rolling reinvestment Sale of individual assets with respective management contracts or geared leases IRR: >6.5% | CoC: >5.0%", + "entities": [ + [ + 0, + 10, + "LAUFZEIT" + ], + [ + 139, + 144, + "RENDITE" + ] + ] + }, + { + "text": "Our investment strategy focuses on investing in upscale hotels in European prime locations, including DACH, Italy, Spain, Portugal, France, UK, Denmark, Benelux,and Poland.", + "entities": [ + [ + 102, + 171, + "LÄNDERALLOKATION" + ] + ] + }, + { + "text": "Core+ assets with value-add potential, Emerging Gateway Cities Helsinki] Core+ with Value well-mitigated risk and great upside Potential potential through asset improvement or = Max. 20% UK & Ireland {no contract renegotiation currency risk hedging], 80% tinental E > IRR target of 6-9%", + "entities": [ + [ + 0, + 5, + "RISIKOPROFIL" + ], + [ + 282, + 286, + "RENDITE" + ] + ] + }, + { + "text": "10% net IRR since inception in 2018?", + "entities": [ + [ + 0, + 3, + "RENDITE" + ] + ] + }, + { + "text": "Eurozone: Benelux, France and Germany", + "entities": [ + [ + 10, + 37, + "LÄNDERALLOKATION" + ] + ] + }, + { + "text": "Open-ended, with quarterly liquidity (redemption rights, dual pricing)", + "entities": [ + [ + 0, + 10, + "LAUFZEIT" + ] + ] + }, + { + "text": "Class A & B (Institutional): 0.93% on NAV; Class D (Wholesale): 1.80% on NAV; Class P (Wholesale): 1.25% on NAV", + "entities": [ + [ + 29, + 34, + "MANAGMENTGEBÜHREN" + ], + [ + 64, + 69, + "MANAGMENTGEBÜHREN" + ], + [ + 99, + 104, + "MANAGMENTGEBÜHREN" + ] + ] + }, + { + "text": "Risk profile: favour core > © at least and core+ assets with a targeted N 2 n allocation to value add assets to enhance returns", + "entities": [ + [ + 21, + 25, + "RISIKOPROFIL" + ], + [ + 43, + 48, + "RISIKOPROFIL" + ] + ] + }, + { + "text": "The Netherlands (38 assets) = Germany (9 assets) 10 largest Country assets split France (8 assets)", + "entities": [ + [ + 0, + 15, + "LÄNDERALLOKATION" + ], + [ + 30, + 37, + "LÄNDERALLOKATION" + ], + [ + 81, + 87, + "LÄNDERALLOKATION" + ] + ] + }, + { + "text": "Expected IRR 10.9%", + "entities": [ + [ + 13, + 18, + "ZIELRENDITE" + ] + ] + }, + { + "text": "Structure Open-end, perpetual life, Luxembourg domiciled Initial Target Size* €2 billion 6-8% total return,", + "entities": [ + [ + 10, + 18, + "LAUFZEIT" + ], + [ + 89, + 93, + "RENDITE" + ] + ] + }, + { + "text": "Geographic Focus: UK, Ireland, Iberia, Nordics, Netherlands, Germany, France, Italy", + "entities": [ + [ + 18, + 83, + "LÄNDERALLOKATION" + ] + ] + }, + { + "text": "IRR of 13-14%", + "entities": [ + [ + 7, + 13, + "RENDITE" + ] + ] + }, + { + "text": "Value-add", + "entities": [ + [ + 0, + 9, + "RISIKOPROFIL" + ] + ] + }, + { + "text": "Geographic allocation NORDICS UNITED KINGDOM GERMANY FRANCE PORTUGAL BENELUX", + "entities": [ + [ + 22, + 76, + "LÄNDERALLOKATION" + ] + ] + }, + { + "text": "Strong track record delivering a 17% net IRR, 1.7x net multiple across all divested assets (both discretionary and non-discretionary mandates)", + "entities": [ + [ + 33, + 36, + "RENDITE" + ] + ] + }, + { + "text": "Targeting a 7-8% net annual return and a 3-4% dividend yield, reflecting a target LTV of 35% (capped at 37.5%)", + "entities": [ + [ + 12, + 16, + "RENDITE" + ] + ] + }, + { + "text": "Sweden Norway Denmark Finland", + "entities": [ + [ + 0, + 29, + "LÄNDERALLOKATION" + ] + ] + }, + { + "text": "Logistics Residential Office Other", + "entities": [ + [ + 0, + 34, + "SEKTORENALLOKATION" + ] + ] + }, + { + "text": "Fund Term Open-ended with an initial 24-month lock-in for new investors", + "entities": [ + [ + 10, + 20, + "LAUFZEIT" + ] + ] + }, + { + "text": "Management fee of 85 bps on NAV.", + "entities": [ + [ + 18, + 24, + "MANAGMENTGEBÜHREN" + ] + ] + }, + { + "text": "Core/Core+ strategy, with tactical exposure to development projects aiming at enhancing the quality of the portfolio over time", + "entities": [ + [ + 0, + 10, + "RISIKOPROFIL" + ] + ] + }, + { + "text": "Fund term: Open-ended", + "entities": [ + [ + 11, + 21, + "LAUFZEIT" + ] + ] + }, + { + "text": "Return targets: The fund targets a net internal rate of return (IRR) of 8% and a net annual income yield of 5% with planned quarterly distributions’.", + "entities": [ + [ + 72, + 74, + "RENDITE" + ] + ] + }, + { + "text": "Geographic scope: The fund has a broad mandate to invest in commercial and residential real estate across Sweden, Denmark, Finland, and Norway. 50% LTV Asset selection: Heirs to acquire high-quality, income-generating properties in major Nordic cities and enhance their value through active asset management. Portfolio construction: The goal is to build diversified portfolios that are appealing to core buyers upon exit.", + "entities": [ + [ + 106, + 142, + "LÄNDERALLOKATION" + ] + ] + }, + { + "text": "Experience: Since 2012, | | has demonstrated its capability to build diversified and resilient portfolios for its core-plus funds. German Real Estate Quota advantage . Local expertise: extensive local relationships and proprietary deal flow in key Nordic markets provide a strategic advantage.", + "entities": [ + [ + 114, + 123, + "RISIKOPROFIL" + ] + ] + }, + { + "text": "Target returns: 8% net IRR with 5% net annual income yield! * Geographic focus: Sweden, Denmark, Norway and Finland « Target leverage: 50% LTV (excluding short-term borrowing) « Sector exposure: office, logistics, public properties, retail (focused on grocery anchored and necessity driven retail) and residentials « Investment focus: high quality properties,", + "entities": [ + [ + 16, + 18, + "RENDITE" + ], + [ + 80, + 115, + "LÄNDERALLOKATION" + ], + [ + 195, + 239, + "SEKTORENALLOKATION" + ] + ] + }, + { + "text": "The Fund 2 xemoours common limited partnership (SCS) (SICAV-RAIF) Investment Objective To pursue investments in commercial and residential properties throughout the Nordic Region Fund Target Size €300 million (equity) Return Targets Target net IRR of 8%, target net annual income yield of 5%", + "entities": [ + [ + 251, + 253, + "RENDITE" + ] + ] + } +] \ No newline at end of file diff --git a/project/backend/spacy-service/spacy_training/base_config.cfg b/project/backend/spacy-service/spacy_training/base_config.cfg deleted file mode 100644 index f7ffac0..0000000 --- a/project/backend/spacy-service/spacy_training/base_config.cfg +++ /dev/null @@ -1,85 +0,0 @@ -# This is an auto-generated partial config. To use it with 'spacy train' -# you can run spacy init fill-config to auto-fill all default settings: -# python -m spacy init fill-config ./base_config.cfg ./config.cfg -[paths] -train = ./data/train.spacy -dev = ./data/train.spacy -vectors = null -[system] -gpu_allocator = null - -[nlp] -lang = "de" -pipeline = ["tok2vec","ner"] -batch_size = 1000 - -[components] - -[components.tok2vec] -factory = "tok2vec" - -[components.tok2vec.model] -@architectures = "spacy.Tok2Vec.v2" - -[components.tok2vec.model.embed] -@architectures = "spacy.MultiHashEmbed.v2" -width = ${components.tok2vec.model.encode.width} -attrs = ["NORM", "PREFIX", "SUFFIX", "SHAPE"] -rows = [5000, 1000, 2500, 2500] -include_static_vectors = false - -[components.tok2vec.model.encode] -@architectures = "spacy.MaxoutWindowEncoder.v2" -width = 96 -depth = 4 -window_size = 1 -maxout_pieces = 3 - -[components.ner] -factory = "ner" - -[components.ner.model] -@architectures = "spacy.TransitionBasedParser.v2" -state_type = "ner" -extra_state_tokens = false -hidden_width = 64 -maxout_pieces = 2 -use_upper = true -nO = null - -[components.ner.model.tok2vec] -@architectures = "spacy.Tok2VecListener.v1" -width = ${components.tok2vec.model.encode.width} - -[corpora] - -[corpora.train] -@readers = "spacy.Corpus.v1" -path = ${paths.train} -max_length = 0 - -[corpora.dev] -@readers = "spacy.Corpus.v1" -path = ${paths.dev} -max_length = 0 - -[training] -dev_corpus = "corpora.dev" -train_corpus = "corpora.train" - -[training.optimizer] -@optimizers = "Adam.v1" - -[training.batcher] -@batchers = "spacy.batch_by_words.v1" -discard_oversize = false -tolerance = 0.2 - -[training.batcher.size] -@schedules = "compounding.v1" -start = 100 -stop = 1000 -compound = 1.001 - -[initialize] -vectors = ${paths.vectors} \ No newline at end of file diff --git a/project/backend/spacy-service/spacy_training/json_append_to_ann.py b/project/backend/spacy-service/spacy_training/json_append_to_ann.py new file mode 100644 index 0000000..0d1cc1e --- /dev/null +++ b/project/backend/spacy-service/spacy_training/json_append_to_ann.py @@ -0,0 +1,18 @@ +import json + +# Alte Daten laden +with open("annotation_data.json", "r", encoding="utf-8") as f: + data = json.load(f) + +# Neue Kennzahl (als Dict/Objekt) +neuer_eintrag = { + "text": "Hier steht der Beispielsatz mit der neuen Kennzahl.", + "entities": [[1, 5, "NEUEKENNZAHL"]], +} + +# Anhängen +data.append(neuer_eintrag) + +# Wieder speichern +with open("annotation_data.json", "w", encoding="utf-8") as f: + json.dump(data, f, ensure_ascii=False, indent=2) diff --git a/project/backend/spacy-service/spacy_training/ner_trainer.py b/project/backend/spacy-service/spacy_training/ner_trainer.py new file mode 100644 index 0000000..52cda7a --- /dev/null +++ b/project/backend/spacy-service/spacy_training/ner_trainer.py @@ -0,0 +1,81 @@ +import spacy +from spacy.training.example import Example +import json +import os +import shutil +import sys + + +def load_data(file_path): + with open(file_path, "r", encoding="utf8") as f: + raw = json.load(f) + return [ + ( + entry["text"], + { + "entities": [ + (start, end, label) for start, end, label in entry["entities"] + ] + }, + ) + for entry in raw + ] + + +def main(): + # Stelle sicher, dass der "output"-Ordner existiert + os.makedirs("output", exist_ok=True) + + TRAIN_DATA = load_data(os.path.join("spacy_training", "annotation_data.json")) + + nlp = spacy.blank("de") + ner = nlp.add_pipe("ner") + ner.add_label("KENNZAHL") + + optimizer = nlp.begin_training() + for i in range(20): + for text, annotations in TRAIN_DATA: + example = Example.from_dict(nlp.make_doc(text), annotations) + nlp.update([example], drop=0.2, sgd=optimizer) + + temp_model_dir = "output/temp-model" + final_model_dir = "output/model-last" + backup_dir = "output/model-backup" + + try: + # Vorheriges temporäres Verzeichnis entfernen + if os.path.exists(temp_model_dir): + shutil.rmtree(temp_model_dir) + + # Modell zunächst in temp speichern + nlp.to_disk(temp_model_dir) + + # Backup der letzten Version (falls vorhanden) + if os.path.exists(final_model_dir): + if os.path.exists(backup_dir): + shutil.rmtree(backup_dir) + shutil.copytree(final_model_dir, backup_dir) + + shutil.rmtree(final_model_dir) + + # Modell verschieben + shutil.move(temp_model_dir, final_model_dir) + print("[INFO] Training abgeschlossen und Modell gespeichert.") + + nlp.to_disk("spacy_training/output/model-last") + + # Training beendet – Status auf False setzen + with open("spacy_training/training_running.json", "w") as f: + json.dump({"running": False}, f) + + sys.exit(0) + + except Exception as e: + print(f"[FEHLER] Während des Trainings ist ein Fehler aufgetreten: {e}") + if os.path.exists(temp_model_dir): + shutil.rmtree(temp_model_dir) + sys.exit(1) + + +if __name__ == "__main__": + main() diff --git a/project/backend/spacy-service/spacy_training/config.cfg b/project/backend/spacy-service/spacy_training/output/model-backup/config.cfg similarity index 76% rename from project/backend/spacy-service/spacy_training/config.cfg rename to project/backend/spacy-service/spacy_training/output/model-backup/config.cfg index 1cf80c4..be02f9c 100644 --- a/project/backend/spacy-service/spacy_training/config.cfg +++ b/project/backend/spacy-service/spacy_training/output/model-backup/config.cfg @@ -1,21 +1,21 @@ [paths] -train = "./data/train.spacy" -dev = "./data/train.spacy" +train = null +dev = null vectors = null init_tok2vec = null [system] -gpu_allocator = null seed = 0 +gpu_allocator = null [nlp] lang = "de" -pipeline = ["tok2vec","ner"] -batch_size = 1000 +pipeline = ["ner"] disabled = [] before_creation = null after_creation = null after_pipeline_creation = null +batch_size = 1000 tokenizer = {"@tokenizers":"spacy.Tokenizer.v1"} vectors = {"@vectors":"spacy.Vectors.v1"} @@ -38,51 +38,34 @@ use_upper = true nO = null [components.ner.model.tok2vec] -@architectures = "spacy.Tok2VecListener.v1" -width = ${components.tok2vec.model.encode.width} -upstream = "*" - -[components.tok2vec] -factory = "tok2vec" - -[components.tok2vec.model] -@architectures = "spacy.Tok2Vec.v2" - -[components.tok2vec.model.embed] -@architectures = "spacy.MultiHashEmbed.v2" -width = ${components.tok2vec.model.encode.width} -attrs = ["NORM","PREFIX","SUFFIX","SHAPE"] -rows = [5000,1000,2500,2500] -include_static_vectors = false - -[components.tok2vec.model.encode] -@architectures = "spacy.MaxoutWindowEncoder.v2" +@architectures = "spacy.HashEmbedCNN.v2" +pretrained_vectors = null width = 96 depth = 4 +embed_size = 2000 window_size = 1 maxout_pieces = 3 +subword_features = true [corpora] [corpora.dev] @readers = "spacy.Corpus.v1" path = ${paths.dev} -max_length = 0 gold_preproc = false +max_length = 0 limit = 0 augmenter = null [corpora.train] @readers = "spacy.Corpus.v1" path = ${paths.train} -max_length = 0 gold_preproc = false +max_length = 0 limit = 0 augmenter = null [training] -dev_corpus = "corpora.dev" -train_corpus = "corpora.train" seed = ${system.seed} gpu_allocator = ${system.gpu_allocator} dropout = 0.1 @@ -93,6 +76,8 @@ max_steps = 20000 eval_frequency = 200 frozen_components = [] annotating_components = [] +dev_corpus = "corpora.dev" +train_corpus = "corpora.train" before_to_disk = null before_update = null diff --git a/project/backend/spacy-service/spacy_training/output/model-backup/meta.json b/project/backend/spacy-service/spacy_training/output/model-backup/meta.json new file mode 100644 index 0000000..9526bed --- /dev/null +++ b/project/backend/spacy-service/spacy_training/output/model-backup/meta.json @@ -0,0 +1,63 @@ +{ + "lang":"de", + "name":"pipeline", + "version":"0.0.0", + "spacy_version":">=3.8.7,<3.9.0", + "description":"", + "author":"", + "email":"", + "url":"", + "license":"", + "spacy_git_version":"4b65aa7", + "vectors":{ + "width":0, + "vectors":0, + "keys":0, + "name":null, + "mode":"default" + }, + "labels":{ + "ner":[ + "AUSSCH\u00dcTTUNGSRENDITE", + "ESFCG", + "HHGK", + "KENNZAHL", + "LAUFZEIT", + "LAUFZEIT2", + "L\u00c4NDERALLOKATION", + "MANAGMENTGEB\u00dcHREN", + "RENDITE", + "RISIKOPROFIL", + "SEKTORENALLOKATION", + "TEST", + "TEST3", + "TEST323", + "TEST33", + "TEST34", + "TEST345", + "TEST35", + "TEST36", + "TEST37", + "TEST4", + "TEST44", + "TEST45", + "TEST5", + "TEST65", + "TEST67", + "TEST88", + "TEST99", + "ZIELAUSSCH\u00dcTTUNG", + "ZIELRENDITE", + "ZZGER 33" + ] + }, + "pipeline":[ + "ner" + ], + "components":[ + "ner" + ], + "disabled":[ + + ] +} \ No newline at end of file diff --git a/project/backend/spacy-service/spacy_training/output/model-backup/ner/cfg b/project/backend/spacy-service/spacy_training/output/model-backup/ner/cfg new file mode 100644 index 0000000..6cd11cf --- /dev/null +++ b/project/backend/spacy-service/spacy_training/output/model-backup/ner/cfg @@ -0,0 +1,13 @@ +{ + "moves":null, + "update_with_oracle_cut_size":100, + "multitasks":[ + + ], + "min_action_freq":1, + "learn_tokens":false, + "beam_width":1, + "beam_density":0.0, + "beam_update_prob":0.0, + "incorrect_spans_key":null +} \ No newline at end of file diff --git a/project/backend/spacy-service/spacy_training/output/model-backup/ner/model b/project/backend/spacy-service/spacy_training/output/model-backup/ner/model new file mode 100644 index 0000000..3e73eb2 Binary files /dev/null and b/project/backend/spacy-service/spacy_training/output/model-backup/ner/model differ diff --git a/project/backend/spacy-service/spacy_training/output/model-backup/ner/moves b/project/backend/spacy-service/spacy_training/output/model-backup/ner/moves new file mode 100644 index 0000000..fecd73d --- /dev/null +++ b/project/backend/spacy-service/spacy_training/output/model-backup/ner/moves @@ -0,0 +1 @@ +moves{"0":{},"1":{"KENNZAHL":-1,"RISIKOPROFIL":-2,"AUSSCH\u00dcTTUNGSRENDITE":-3,"LAUFZEIT":-4,"RENDITE":-5,"L\u00c4NDERALLOKATION":-6,"ZIELRENDITE":-7,"ZIELAUSSCH\u00dcTTUNG":-8,"MANAGMENTGEB\u00dcHREN":-9,"SEKTORENALLOKATION":-10,"LAUFZEIT2":-11,"TEST":-12,"TEST3":-13,"TEST4":-14,"TEST5":-15,"TEST34":-16,"TEST35":-17,"TEST36":-18,"TEST37":-19,"HHGK":-20,"TEST67":-21,"ESFCG":-22,"ZZGER 33":-23,"TEST65":-24,"TEST99":-25,"TEST88":-26,"TEST44":-27,"TEST33":-28,"TEST345":-29,"TEST45":-30,"TEST323":-31},"2":{"KENNZAHL":-1,"RISIKOPROFIL":-2,"AUSSCH\u00dcTTUNGSRENDITE":-3,"LAUFZEIT":-4,"RENDITE":-5,"L\u00c4NDERALLOKATION":-6,"ZIELRENDITE":-7,"ZIELAUSSCH\u00dcTTUNG":-8,"MANAGMENTGEB\u00dcHREN":-9,"SEKTORENALLOKATION":-10,"LAUFZEIT2":-11,"TEST":-12,"TEST3":-13,"TEST4":-14,"TEST5":-15,"TEST34":-16,"TEST35":-17,"TEST36":-18,"TEST37":-19,"HHGK":-20,"TEST67":-21,"ESFCG":-22,"ZZGER 33":-23,"TEST65":-24,"TEST99":-25,"TEST88":-26,"TEST44":-27,"TEST33":-28,"TEST345":-29,"TEST45":-30,"TEST323":-31},"3":{"KENNZAHL":-1,"RISIKOPROFIL":-2,"AUSSCH\u00dcTTUNGSRENDITE":-3,"LAUFZEIT":-4,"RENDITE":-5,"L\u00c4NDERALLOKATION":-6,"ZIELRENDITE":-7,"ZIELAUSSCH\u00dcTTUNG":-8,"MANAGMENTGEB\u00dcHREN":-9,"SEKTORENALLOKATION":-10,"LAUFZEIT2":-11,"TEST":-12,"TEST3":-13,"TEST4":-14,"TEST5":-15,"TEST34":-16,"TEST35":-17,"TEST36":-18,"TEST37":-19,"HHGK":-20,"TEST67":-21,"ESFCG":-22,"ZZGER 33":-23,"TEST65":-24,"TEST99":-25,"TEST88":-26,"TEST44":-27,"TEST33":-28,"TEST345":-29,"TEST45":-30,"TEST323":-31},"4":{"":1,"KENNZAHL":-1,"RISIKOPROFIL":-2,"AUSSCH\u00dcTTUNGSRENDITE":-3,"LAUFZEIT":-4,"RENDITE":-5,"L\u00c4NDERALLOKATION":-6,"ZIELRENDITE":-7,"ZIELAUSSCH\u00dcTTUNG":-8,"MANAGMENTGEB\u00dcHREN":-9,"SEKTORENALLOKATION":-10,"LAUFZEIT2":-11,"TEST":-12,"TEST3":-13,"TEST4":-14,"TEST5":-15,"TEST34":-16,"TEST35":-17,"TEST36":-18,"TEST37":-19,"HHGK":-20,"TEST67":-21,"ESFCG":-22,"ZZGER 33":-23,"TEST65":-24,"TEST99":-25,"TEST88":-26,"TEST44":-27,"TEST33":-28,"TEST345":-29,"TEST45":-30,"TEST323":-31},"5":{"":1}}cfgneg_key \ No newline at end of file diff --git a/project/backend/spacy-service/spacy_training/output/model-backup/tok2vec/cfg b/project/backend/spacy-service/spacy_training/output/model-backup/tok2vec/cfg new file mode 100644 index 0000000..0e0dcd2 --- /dev/null +++ b/project/backend/spacy-service/spacy_training/output/model-backup/tok2vec/cfg @@ -0,0 +1,3 @@ +{ + +} \ No newline at end of file diff --git a/project/backend/spacy-service/spacy_training/output/model-backup/tok2vec/model b/project/backend/spacy-service/spacy_training/output/model-backup/tok2vec/model new file mode 100644 index 0000000..4c7f5bb Binary files /dev/null and b/project/backend/spacy-service/spacy_training/output/model-backup/tok2vec/model differ diff --git a/project/backend/spacy-service/spacy_training/output/model-backup/tokenizer b/project/backend/spacy-service/spacy_training/output/model-backup/tokenizer new file mode 100644 index 0000000..9cdc922 --- /dev/null +++ b/project/backend/spacy-service/spacy_training/output/model-backup/tokenizer @@ -0,0 +1,3 @@ +prefix_search ^``|^§|^%|^=|^—|^–|^\+(?![0-9])|^…|^……|^,|^:|^;|^\!|^\?|^¿|^؟|^¡|^\(|^\)|^\[|^\]|^\{|^\}|^<|^>|^_|^#|^\*|^&|^。|^?|^!|^,|^、|^;|^:|^~|^·|^।|^،|^۔|^؛|^٪|^\.\.+|^…|^\'|^"|^”|^“|^`|^‘|^´|^’|^‚|^,|^„|^»|^«|^「|^」|^『|^』|^(|^)|^〔|^〕|^【|^】|^《|^》|^〈|^〉|^〈|^〉|^⟦|^⟧|^\$|^£|^€|^¥|^฿|^US\$|^C\$|^A\$|^₽|^﷼|^₴|^₠|^₡|^₢|^₣|^₤|^₥|^₦|^₧|^₨|^₩|^₪|^₫|^€|^₭|^₮|^₯|^₰|^₱|^₲|^₳|^₴|^₵|^₶|^₷|^₸|^₹|^₺|^₻|^₼|^₽|^₾|^₿|^[\u00A6\u00A9\u00AE\u00B0\u0482\u058D\u058E\u060E\u060F\u06DE\u06E9\u06FD\u06FE\u07F6\u09FA\u0B70\u0BF3-\u0BF8\u0BFA\u0C7F\u0D4F\u0D79\u0F01-\u0F03\u0F13\u0F15-\u0F17\u0F1A-\u0F1F\u0F34\u0F36\u0F38\u0FBE-\u0FC5\u0FC7-\u0FCC\u0FCE\u0FCF\u0FD5-\u0FD8\u109E\u109F\u1390-\u1399\u1940\u19DE-\u19FF\u1B61-\u1B6A\u1B74-\u1B7C\u2100\u2101\u2103-\u2106\u2108\u2109\u2114\u2116\u2117\u211E-\u2123\u2125\u2127\u2129\u212E\u213A\u213B\u214A\u214C\u214D\u214F\u218A\u218B\u2195-\u2199\u219C-\u219F\u21A1\u21A2\u21A4\u21A5\u21A7-\u21AD\u21AF-\u21CD\u21D0\u21D1\u21D3\u21D5-\u21F3\u2300-\u2307\u230C-\u231F\u2322-\u2328\u232B-\u237B\u237D-\u239A\u23B4-\u23DB\u23E2-\u2426\u2440-\u244A\u249C-\u24E9\u2500-\u25B6\u25B8-\u25C0\u25C2-\u25F7\u2600-\u266E\u2670-\u2767\u2794-\u27BF\u2800-\u28FF\u2B00-\u2B2F\u2B45\u2B46\u2B4D-\u2B73\u2B76-\u2B95\u2B98-\u2BC8\u2BCA-\u2BFE\u2CE5-\u2CEA\u2E80-\u2E99\u2E9B-\u2EF3\u2F00-\u2FD5\u2FF0-\u2FFB\u3004\u3012\u3013\u3020\u3036\u3037\u303E\u303F\u3190\u3191\u3196-\u319F\u31C0-\u31E3\u3200-\u321E\u322A-\u3247\u3250\u3260-\u327F\u328A-\u32B0\u32C0-\u32FE\u3300-\u33FF\u4DC0-\u4DFF\uA490-\uA4C6\uA828-\uA82B\uA836\uA837\uA839\uAA77-\uAA79\uFDFD\uFFE4\uFFE8\uFFED\uFFEE\uFFFC\uFFFD\U00010137-\U0001013F\U00010179-\U00010189\U0001018C-\U0001018E\U00010190-\U0001019B\U000101A0\U000101D0-\U000101FC\U00010877\U00010878\U00010AC8\U0001173F\U00016B3C-\U00016B3F\U00016B45\U0001BC9C\U0001D000-\U0001D0F5\U0001D100-\U0001D126\U0001D129-\U0001D164\U0001D16A-\U0001D16C\U0001D183\U0001D184\U0001D18C-\U0001D1A9\U0001D1AE-\U0001D1E8\U0001D200-\U0001D241\U0001D245\U0001D300-\U0001D356\U0001D800-\U0001D9FF\U0001DA37-\U0001DA3A\U0001DA6D-\U0001DA74\U0001DA76-\U0001DA83\U0001DA85\U0001DA86\U0001ECAC\U0001F000-\U0001F02B\U0001F030-\U0001F093\U0001F0A0-\U0001F0AE\U0001F0B1-\U0001F0BF\U0001F0C1-\U0001F0CF\U0001F0D1-\U0001F0F5\U0001F110-\U0001F16B\U0001F170-\U0001F1AC\U0001F1E6-\U0001F202\U0001F210-\U0001F23B\U0001F240-\U0001F248\U0001F250\U0001F251\U0001F260-\U0001F265\U0001F300-\U0001F3FA\U0001F400-\U0001F6D4\U0001F6E0-\U0001F6EC\U0001F6F0-\U0001F6F9\U0001F700-\U0001F773\U0001F780-\U0001F7D8\U0001F800-\U0001F80B\U0001F810-\U0001F847\U0001F850-\U0001F859\U0001F860-\U0001F887\U0001F890-\U0001F8AD\U0001F900-\U0001F90B\U0001F910-\U0001F93E\U0001F940-\U0001F970\U0001F973-\U0001F976\U0001F97A\U0001F97C-\U0001F9A2\U0001F9B0-\U0001F9B9\U0001F9C0-\U0001F9C2\U0001F9D0-\U0001F9FF\U0001FA60-\U0001FA6D]suffix_search2''$|/$|…$|……$|,$|:$|;$|\!$|\?$|¿$|؟$|¡$|\($|\)$|\[$|\]$|\{$|\}$|<$|>$|_$|#$|\*$|&$|。$|?$|!$|,$|、$|;$|:$|~$|·$|।$|،$|۔$|؛$|٪$|\.\.+$|…$|\'$|"$|”$|“$|`$|‘$|´$|’$|‚$|,$|„$|»$|«$|「$|」$|『$|』$|($|)$|〔$|〕$|【$|】$|《$|》$|〈$|〉$|〈$|〉$|⟦$|⟧$|[\u00A6\u00A9\u00AE\u00B0\u0482\u058D\u058E\u060E\u060F\u06DE\u06E9\u06FD\u06FE\u07F6\u09FA\u0B70\u0BF3-\u0BF8\u0BFA\u0C7F\u0D4F\u0D79\u0F01-\u0F03\u0F13\u0F15-\u0F17\u0F1A-\u0F1F\u0F34\u0F36\u0F38\u0FBE-\u0FC5\u0FC7-\u0FCC\u0FCE\u0FCF\u0FD5-\u0FD8\u109E\u109F\u1390-\u1399\u1940\u19DE-\u19FF\u1B61-\u1B6A\u1B74-\u1B7C\u2100\u2101\u2103-\u2106\u2108\u2109\u2114\u2116\u2117\u211E-\u2123\u2125\u2127\u2129\u212E\u213A\u213B\u214A\u214C\u214D\u214F\u218A\u218B\u2195-\u2199\u219C-\u219F\u21A1\u21A2\u21A4\u21A5\u21A7-\u21AD\u21AF-\u21CD\u21D0\u21D1\u21D3\u21D5-\u21F3\u2300-\u2307\u230C-\u231F\u2322-\u2328\u232B-\u237B\u237D-\u239A\u23B4-\u23DB\u23E2-\u2426\u2440-\u244A\u249C-\u24E9\u2500-\u25B6\u25B8-\u25C0\u25C2-\u25F7\u2600-\u266E\u2670-\u2767\u2794-\u27BF\u2800-\u28FF\u2B00-\u2B2F\u2B45\u2B46\u2B4D-\u2B73\u2B76-\u2B95\u2B98-\u2BC8\u2BCA-\u2BFE\u2CE5-\u2CEA\u2E80-\u2E99\u2E9B-\u2EF3\u2F00-\u2FD5\u2FF0-\u2FFB\u3004\u3012\u3013\u3020\u3036\u3037\u303E\u303F\u3190\u3191\u3196-\u319F\u31C0-\u31E3\u3200-\u321E\u322A-\u3247\u3250\u3260-\u327F\u328A-\u32B0\u32C0-\u32FE\u3300-\u33FF\u4DC0-\u4DFF\uA490-\uA4C6\uA828-\uA82B\uA836\uA837\uA839\uAA77-\uAA79\uFDFD\uFFE4\uFFE8\uFFED\uFFEE\uFFFC\uFFFD\U00010137-\U0001013F\U00010179-\U00010189\U0001018C-\U0001018E\U00010190-\U0001019B\U000101A0\U000101D0-\U000101FC\U00010877\U00010878\U00010AC8\U0001173F\U00016B3C-\U00016B3F\U00016B45\U0001BC9C\U0001D000-\U0001D0F5\U0001D100-\U0001D126\U0001D129-\U0001D164\U0001D16A-\U0001D16C\U0001D183\U0001D184\U0001D18C-\U0001D1A9\U0001D1AE-\U0001D1E8\U0001D200-\U0001D241\U0001D245\U0001D300-\U0001D356\U0001D800-\U0001D9FF\U0001DA37-\U0001DA3A\U0001DA6D-\U0001DA74\U0001DA76-\U0001DA83\U0001DA85\U0001DA86\U0001ECAC\U0001F000-\U0001F02B\U0001F030-\U0001F093\U0001F0A0-\U0001F0AE\U0001F0B1-\U0001F0BF\U0001F0C1-\U0001F0CF\U0001F0D1-\U0001F0F5\U0001F110-\U0001F16B\U0001F170-\U0001F1AC\U0001F1E6-\U0001F202\U0001F210-\U0001F23B\U0001F240-\U0001F248\U0001F250\U0001F251\U0001F260-\U0001F265\U0001F300-\U0001F3FA\U0001F400-\U0001F6D4\U0001F6E0-\U0001F6EC\U0001F6F0-\U0001F6F9\U0001F700-\U0001F773\U0001F780-\U0001F7D8\U0001F800-\U0001F80B\U0001F810-\U0001F847\U0001F850-\U0001F859\U0001F860-\U0001F887\U0001F890-\U0001F8AD\U0001F900-\U0001F90B\U0001F910-\U0001F93E\U0001F940-\U0001F970\U0001F973-\U0001F976\U0001F97A\U0001F97C-\U0001F9A2\U0001F9B0-\U0001F9B9\U0001F9C0-\U0001F9C2\U0001F9D0-\U0001F9FF\U0001FA60-\U0001FA6D]$|(?<=[0-9])\+$|(?<=°[FfCcKk])\.$|(?<=[0-9])(?:\$|£|€|¥|฿|US\$|C\$|A\$|₽|﷼|₴|₠|₡|₢|₣|₤|₥|₦|₧|₨|₩|₪|₫|€|₭|₮|₯|₰|₱|₲|₳|₴|₵|₶|₷|₸|₹|₺|₻|₼|₽|₾|₿)$|(?<=[0-9])(?:km|km²|km³|m|m²|m³|dm|dm²|dm³|cm|cm²|cm³|mm|mm²|mm³|ha|µm|nm|yd|in|ft|kg|g|mg|µg|t|lb|oz|m/s|km/h|kmh|mph|hPa|Pa|mbar|mb|MB|kb|KB|gb|GB|tb|TB|T|G|M|K|%|км|км²|км³|м|м²|м³|дм|дм²|дм³|см|см²|см³|мм|мм²|мм³|нм|кг|г|мг|м/с|км/ч|кПа|Па|мбар|Кб|КБ|кб|Мб|МБ|мб|Гб|ГБ|гб|Тб|ТБ|тбكم|كم²|كم³|م|م²|م³|سم|سم²|سم³|مم|مم²|مم³|كم|غرام|جرام|جم|كغ|ملغ|كوب|اكواب)$|(?<=[a-z\uFF41-\uFF5A\u00DF-\u00F6\u00F8-\u00FF\u0101\u0103\u0105\u0107\u0109\u010B\u010D\u010F\u0111\u0113\u0115\u0117\u0119\u011B\u011D\u011F\u0121\u0123\u0125\u0127\u0129\u012B\u012D\u012F\u0131\u0133\u0135\u0137\u0138\u013A\u013C\u013E\u0140\u0142\u0144\u0146\u0148\u0149\u014B\u014D\u014F\u0151\u0153\u0155\u0157\u0159\u015B\u015D\u015F\u0161\u0163\u0165\u0167\u0169\u016B\u016D\u016F\u0171\u0173\u0175\u0177\u017A\u017C\u017E\u017F\u0180\u0183\u0185\u0188\u018C\u018D\u0192\u0195\u0199-\u019B\u019E\u01A1\u01A3\u01A5\u01A8\u01AA\u01AB\u01AD\u01B0\u01B4\u01B6\u01B9\u01BA\u01BD-\u01BF\u01C6\u01C9\u01CC\u01CE\u01D0\u01D2\u01D4\u01D6\u01D8\u01DA\u01DC\u01DD\u01DF\u01E1\u01E3\u01E5\u01E7\u01E9\u01EB\u01ED\u01EF\u01F0\u01F3\u01F5\u01F9\u01FB\u01FD\u01FF\u0201\u0203\u0205\u0207\u0209\u020B\u020D\u020F\u0211\u0213\u0215\u0217\u0219\u021B\u021D\u021F\u0221\u0223\u0225\u0227\u0229\u022B\u022D\u022F\u0231\u0233-\u0239\u023C\u023F\u0240\u0242\u0247\u0249\u024B\u024D\u024F\u2C61\u2C65\u2C66\u2C68\u2C6A\u2C6C\u2C71\u2C73\u2C74\u2C76-\u2C7B\uA723\uA725\uA727\uA729\uA72B\uA72D\uA72F-\uA731\uA733\uA735\uA737\uA739\uA73B\uA73D\uA73F\uA741\uA743\uA745\uA747\uA749\uA74B\uA74D\uA74F\uA751\uA753\uA755\uA757\uA759\uA75B\uA75D\uA75F\uA761\uA763\uA765\uA767\uA769\uA76B\uA76D\uA76F\uA771-\uA778\uA77A\uA77C\uA77F\uA781\uA783\uA785\uA787\uA78C\uA78E\uA791\uA793-\uA795\uA797\uA799\uA79B\uA79D\uA79F\uA7A1\uA7A3\uA7A5\uA7A7\uA7A9\uA7AF\uA7B5\uA7B7\uA7B9\uA7FA\uAB30-\uAB5A\uAB60-\uAB64\u0250-\u02AF\u1D00-\u1D25\u1D6B-\u1D77\u1D79-\u1D9A\u1E01\u1E03\u1E05\u1E07\u1E09\u1E0B\u1E0D\u1E0F\u1E11\u1E13\u1E15\u1E17\u1E19\u1E1B\u1E1D\u1E1F\u1E21\u1E23\u1E25\u1E27\u1E29\u1E2B\u1E2D\u1E2F\u1E31\u1E33\u1E35\u1E37\u1E39\u1E3B\u1E3D\u1E3F\u1E41\u1E43\u1E45\u1E47\u1E49\u1E4B\u1E4D\u1E4F\u1E51\u1E53\u1E55\u1E57\u1E59\u1E5B\u1E5D\u1E5F\u1E61\u1E63\u1E65\u1E67\u1E69\u1E6B\u1E6D\u1E6F\u1E71\u1E73\u1E75\u1E77\u1E79\u1E7B\u1E7D\u1E7F\u1E81\u1E83\u1E85\u1E87\u1E89\u1E8B\u1E8D\u1E8F\u1E91\u1E93\u1E95-\u1E9D\u1E9F\u1EA1\u1EA3\u1EA5\u1EA7\u1EA9\u1EAB\u1EAD\u1EAF\u1EB1\u1EB3\u1EB5\u1EB7\u1EB9\u1EBB\u1EBD\u1EBF\u1EC1\u1EC3\u1EC5\u1EC7\u1EC9\u1ECB\u1ECD\u1ECF\u1ED1\u1ED3\u1ED5\u1ED7\u1ED9\u1EDB\u1EDD\u1EDF\u1EE1\u1EE3\u1EE5\u1EE7\u1EE9\u1EEB\u1EED\u1EEF\u1EF1\u1EF3\u1EF5\u1EF7\u1EF9\u1EFB\u1EFD\u1EFFёа-яәөүҗңһα-ωάέίόώήύа-щюяіїєґѓѕјљњќѐѝ\u1200-\u137F\u0980-\u09FF\u0591-\u05F4\uFB1D-\uFB4F\u0620-\u064A\u066E-\u06D5\u06E5-\u06FF\u0750-\u077F\u08A0-\u08BD\uFB50-\uFBB1\uFBD3-\uFD3D\uFD50-\uFDC7\uFDF0-\uFDFB\uFE70-\uFEFC\U0001EE00-\U0001EEBB\u0D80-\u0DFF\u0900-\u097F\u0C80-\u0CFF\u0B80-\u0BFF\u0C00-\u0C7F\uAC00-\uD7AF\u1100-\u11FF\u3040-\u309F\u30A0-\u30FFー\u4E00-\u62FF\u6300-\u77FF\u7800-\u8CFF\u8D00-\u9FFF\u3400-\u4DBF\U00020000-\U000215FF\U00021600-\U000230FF\U00023100-\U000245FF\U00024600-\U000260FF\U00026100-\U000275FF\U00027600-\U000290FF\U00029100-\U0002A6DF\U0002A700-\U0002B73F\U0002B740-\U0002B81F\U0002B820-\U0002CEAF\U0002CEB0-\U0002EBEF\u2E80-\u2EFF\u2F00-\u2FDF\u2FF0-\u2FFF\u3000-\u303F\u31C0-\u31EF\u3200-\u32FF\u3300-\u33FF\uF900-\uFAFF\uFE30-\uFE4F\U0001F200-\U0001F2FF\U0002F800-\U0002FA1F%²\-\+…|……|,|:|;|\!|\?|¿|؟|¡|\(|\)|\[|\]|\{|\}|<|>|_|#|\*|&|。|?|!|,|、|;|:|~|·|।|،|۔|؛|٪(?:\'"”“`‘´’‚,„»«「」『』()〔〕【】《》〈〉〈〉⟦⟧)])\.$|(?<=[A-Z\uFF21-\uFF3A\u00C0-\u00D6\u00D8-\u00DE\u0100\u0102\u0104\u0106\u0108\u010A\u010C\u010E\u0110\u0112\u0114\u0116\u0118\u011A\u011C\u011E\u0120\u0122\u0124\u0126\u0128\u012A\u012C\u012E\u0130\u0132\u0134\u0136\u0139\u013B\u013D\u013F\u0141\u0143\u0145\u0147\u014A\u014C\u014E\u0150\u0152\u0154\u0156\u0158\u015A\u015C\u015E\u0160\u0162\u0164\u0166\u0168\u016A\u016C\u016E\u0170\u0172\u0174\u0176\u0178\u0179\u017B\u017D\u0181\u0182\u0184\u0186\u0187\u0189-\u018B\u018E-\u0191\u0193\u0194\u0196-\u0198\u019C\u019D\u019F\u01A0\u01A2\u01A4\u01A6\u01A7\u01A9\u01AC\u01AE\u01AF\u01B1-\u01B3\u01B5\u01B7\u01B8\u01BC\u01C4\u01C7\u01CA\u01CD\u01CF\u01D1\u01D3\u01D5\u01D7\u01D9\u01DB\u01DE\u01E0\u01E2\u01E4\u01E6\u01E8\u01EA\u01EC\u01EE\u01F1\u01F4\u01F6-\u01F8\u01FA\u01FC\u01FE\u0200\u0202\u0204\u0206\u0208\u020A\u020C\u020E\u0210\u0212\u0214\u0216\u0218\u021A\u021C\u021E\u0220\u0222\u0224\u0226\u0228\u022A\u022C\u022E\u0230\u0232\u023A\u023B\u023D\u023E\u0241\u0243-\u0246\u0248\u024A\u024C\u024E\u2C60\u2C62-\u2C64\u2C67\u2C69\u2C6B\u2C6D-\u2C70\u2C72\u2C75\u2C7E\u2C7F\uA722\uA724\uA726\uA728\uA72A\uA72C\uA72E\uA732\uA734\uA736\uA738\uA73A\uA73C\uA73E\uA740\uA742\uA744\uA746\uA748\uA74A\uA74C\uA74E\uA750\uA752\uA754\uA756\uA758\uA75A\uA75C\uA75E\uA760\uA762\uA764\uA766\uA768\uA76A\uA76C\uA76E\uA779\uA77B\uA77D\uA77E\uA780\uA782\uA784\uA786\uA78B\uA78D\uA790\uA792\uA796\uA798\uA79A\uA79C\uA79E\uA7A0\uA7A2\uA7A4\uA7A6\uA7A8\uA7AA-\uA7AE\uA7B0-\uA7B4\uA7B6\uA7B8\u1E00\u1E02\u1E04\u1E06\u1E08\u1E0A\u1E0C\u1E0E\u1E10\u1E12\u1E14\u1E16\u1E18\u1E1A\u1E1C\u1E1E\u1E20\u1E22\u1E24\u1E26\u1E28\u1E2A\u1E2C\u1E2E\u1E30\u1E32\u1E34\u1E36\u1E38\u1E3A\u1E3C\u1E3E\u1E40\u1E42\u1E44\u1E46\u1E48\u1E4A\u1E4C\u1E4E\u1E50\u1E52\u1E54\u1E56\u1E58\u1E5A\u1E5C\u1E5E\u1E60\u1E62\u1E64\u1E66\u1E68\u1E6A\u1E6C\u1E6E\u1E70\u1E72\u1E74\u1E76\u1E78\u1E7A\u1E7C\u1E7E\u1E80\u1E82\u1E84\u1E86\u1E88\u1E8A\u1E8C\u1E8E\u1E90\u1E92\u1E94\u1E9E\u1EA0\u1EA2\u1EA4\u1EA6\u1EA8\u1EAA\u1EAC\u1EAE\u1EB0\u1EB2\u1EB4\u1EB6\u1EB8\u1EBA\u1EBC\u1EBE\u1EC0\u1EC2\u1EC4\u1EC6\u1EC8\u1ECA\u1ECC\u1ECE\u1ED0\u1ED2\u1ED4\u1ED6\u1ED8\u1EDA\u1EDC\u1EDE\u1EE0\u1EE2\u1EE4\u1EE6\u1EE8\u1EEA\u1EEC\u1EEE\u1EF0\u1EF2\u1EF4\u1EF6\u1EF8\u1EFA\u1EFC\u1EFEЁА-ЯӘӨҮҖҢҺΑ-ΩΆΈΊΌΏΉΎА-ЩЮЯІЇЄҐЃЅЈЉЊЌЀЍ\u1200-\u137F\u0980-\u09FF\u0591-\u05F4\uFB1D-\uFB4F\u0620-\u064A\u066E-\u06D5\u06E5-\u06FF\u0750-\u077F\u08A0-\u08BD\uFB50-\uFBB1\uFBD3-\uFD3D\uFD50-\uFDC7\uFDF0-\uFDFB\uFE70-\uFEFC\U0001EE00-\U0001EEBB\u0D80-\u0DFF\u0900-\u097F\u0C80-\u0CFF\u0B80-\u0BFF\u0C00-\u0C7F\uAC00-\uD7AF\u1100-\u11FF\u3040-\u309F\u30A0-\u30FFー\u4E00-\u62FF\u6300-\u77FF\u7800-\u8CFF\u8D00-\u9FFF\u3400-\u4DBF\U00020000-\U000215FF\U00021600-\U000230FF\U00023100-\U000245FF\U00024600-\U000260FF\U00026100-\U000275FF\U00027600-\U000290FF\U00029100-\U0002A6DF\U0002A700-\U0002B73F\U0002B740-\U0002B81F\U0002B820-\U0002CEAF\U0002CEB0-\U0002EBEF\u2E80-\u2EFF\u2F00-\u2FDF\u2FF0-\u2FFF\u3000-\u303F\u31C0-\u31EF\u3200-\u32FF\u3300-\u33FF\uF900-\uFAFF\uFE30-\uFE4F\U0001F200-\U0001F2FF\U0002F800-\U0002FA1F][A-Z\uFF21-\uFF3A\u00C0-\u00D6\u00D8-\u00DE\u0100\u0102\u0104\u0106\u0108\u010A\u010C\u010E\u0110\u0112\u0114\u0116\u0118\u011A\u011C\u011E\u0120\u0122\u0124\u0126\u0128\u012A\u012C\u012E\u0130\u0132\u0134\u0136\u0139\u013B\u013D\u013F\u0141\u0143\u0145\u0147\u014A\u014C\u014E\u0150\u0152\u0154\u0156\u0158\u015A\u015C\u015E\u0160\u0162\u0164\u0166\u0168\u016A\u016C\u016E\u0170\u0172\u0174\u0176\u0178\u0179\u017B\u017D\u0181\u0182\u0184\u0186\u0187\u0189-\u018B\u018E-\u0191\u0193\u0194\u0196-\u0198\u019C\u019D\u019F\u01A0\u01A2\u01A4\u01A6\u01A7\u01A9\u01AC\u01AE\u01AF\u01B1-\u01B3\u01B5\u01B7\u01B8\u01BC\u01C4\u01C7\u01CA\u01CD\u01CF\u01D1\u01D3\u01D5\u01D7\u01D9\u01DB\u01DE\u01E0\u01E2\u01E4\u01E6\u01E8\u01EA\u01EC\u01EE\u01F1\u01F4\u01F6-\u01F8\u01FA\u01FC\u01FE\u0200\u0202\u0204\u0206\u0208\u020A\u020C\u020E\u0210\u0212\u0214\u0216\u0218\u021A\u021C\u021E\u0220\u0222\u0224\u0226\u0228\u022A\u022C\u022E\u0230\u0232\u023A\u023B\u023D\u023E\u0241\u0243-\u0246\u0248\u024A\u024C\u024E\u2C60\u2C62-\u2C64\u2C67\u2C69\u2C6B\u2C6D-\u2C70\u2C72\u2C75\u2C7E\u2C7F\uA722\uA724\uA726\uA728\uA72A\uA72C\uA72E\uA732\uA734\uA736\uA738\uA73A\uA73C\uA73E\uA740\uA742\uA744\uA746\uA748\uA74A\uA74C\uA74E\uA750\uA752\uA754\uA756\uA758\uA75A\uA75C\uA75E\uA760\uA762\uA764\uA766\uA768\uA76A\uA76C\uA76E\uA779\uA77B\uA77D\uA77E\uA780\uA782\uA784\uA786\uA78B\uA78D\uA790\uA792\uA796\uA798\uA79A\uA79C\uA79E\uA7A0\uA7A2\uA7A4\uA7A6\uA7A8\uA7AA-\uA7AE\uA7B0-\uA7B4\uA7B6\uA7B8\u1E00\u1E02\u1E04\u1E06\u1E08\u1E0A\u1E0C\u1E0E\u1E10\u1E12\u1E14\u1E16\u1E18\u1E1A\u1E1C\u1E1E\u1E20\u1E22\u1E24\u1E26\u1E28\u1E2A\u1E2C\u1E2E\u1E30\u1E32\u1E34\u1E36\u1E38\u1E3A\u1E3C\u1E3E\u1E40\u1E42\u1E44\u1E46\u1E48\u1E4A\u1E4C\u1E4E\u1E50\u1E52\u1E54\u1E56\u1E58\u1E5A\u1E5C\u1E5E\u1E60\u1E62\u1E64\u1E66\u1E68\u1E6A\u1E6C\u1E6E\u1E70\u1E72\u1E74\u1E76\u1E78\u1E7A\u1E7C\u1E7E\u1E80\u1E82\u1E84\u1E86\u1E88\u1E8A\u1E8C\u1E8E\u1E90\u1E92\u1E94\u1E9E\u1EA0\u1EA2\u1EA4\u1EA6\u1EA8\u1EAA\u1EAC\u1EAE\u1EB0\u1EB2\u1EB4\u1EB6\u1EB8\u1EBA\u1EBC\u1EBE\u1EC0\u1EC2\u1EC4\u1EC6\u1EC8\u1ECA\u1ECC\u1ECE\u1ED0\u1ED2\u1ED4\u1ED6\u1ED8\u1EDA\u1EDC\u1EDE\u1EE0\u1EE2\u1EE4\u1EE6\u1EE8\u1EEA\u1EEC\u1EEE\u1EF0\u1EF2\u1EF4\u1EF6\u1EF8\u1EFA\u1EFC\u1EFEЁА-ЯӘӨҮҖҢҺΑ-ΩΆΈΊΌΏΉΎА-ЩЮЯІЇЄҐЃЅЈЉЊЌЀЍ\u1200-\u137F\u0980-\u09FF\u0591-\u05F4\uFB1D-\uFB4F\u0620-\u064A\u066E-\u06D5\u06E5-\u06FF\u0750-\u077F\u08A0-\u08BD\uFB50-\uFBB1\uFBD3-\uFD3D\uFD50-\uFDC7\uFDF0-\uFDFB\uFE70-\uFEFC\U0001EE00-\U0001EEBB\u0D80-\u0DFF\u0900-\u097F\u0C80-\u0CFF\u0B80-\u0BFF\u0C00-\u0C7F\uAC00-\uD7AF\u1100-\u11FF\u3040-\u309F\u30A0-\u30FFー\u4E00-\u62FF\u6300-\u77FF\u7800-\u8CFF\u8D00-\u9FFF\u3400-\u4DBF\U00020000-\U000215FF\U00021600-\U000230FF\U00023100-\U000245FF\U00024600-\U000260FF\U00026100-\U000275FF\U00027600-\U000290FF\U00029100-\U0002A6DF\U0002A700-\U0002B73F\U0002B740-\U0002B81F\U0002B820-\U0002CEAF\U0002CEB0-\U0002EBEF\u2E80-\u2EFF\u2F00-\u2FDF\u2FF0-\u2FFF\u3000-\u303F\u31C0-\u31EF\u3200-\u32FF\u3300-\u33FF\uF900-\uFAFF\uFE30-\uFE4F\U0001F200-\U0001F2FF\U0002F800-\U0002FA1F])\.$infix_finditerZ\.\.+|…|[\u00A6\u00A9\u00AE\u00B0\u0482\u058D\u058E\u060E\u060F\u06DE\u06E9\u06FD\u06FE\u07F6\u09FA\u0B70\u0BF3-\u0BF8\u0BFA\u0C7F\u0D4F\u0D79\u0F01-\u0F03\u0F13\u0F15-\u0F17\u0F1A-\u0F1F\u0F34\u0F36\u0F38\u0FBE-\u0FC5\u0FC7-\u0FCC\u0FCE\u0FCF\u0FD5-\u0FD8\u109E\u109F\u1390-\u1399\u1940\u19DE-\u19FF\u1B61-\u1B6A\u1B74-\u1B7C\u2100\u2101\u2103-\u2106\u2108\u2109\u2114\u2116\u2117\u211E-\u2123\u2125\u2127\u2129\u212E\u213A\u213B\u214A\u214C\u214D\u214F\u218A\u218B\u2195-\u2199\u219C-\u219F\u21A1\u21A2\u21A4\u21A5\u21A7-\u21AD\u21AF-\u21CD\u21D0\u21D1\u21D3\u21D5-\u21F3\u2300-\u2307\u230C-\u231F\u2322-\u2328\u232B-\u237B\u237D-\u239A\u23B4-\u23DB\u23E2-\u2426\u2440-\u244A\u249C-\u24E9\u2500-\u25B6\u25B8-\u25C0\u25C2-\u25F7\u2600-\u266E\u2670-\u2767\u2794-\u27BF\u2800-\u28FF\u2B00-\u2B2F\u2B45\u2B46\u2B4D-\u2B73\u2B76-\u2B95\u2B98-\u2BC8\u2BCA-\u2BFE\u2CE5-\u2CEA\u2E80-\u2E99\u2E9B-\u2EF3\u2F00-\u2FD5\u2FF0-\u2FFB\u3004\u3012\u3013\u3020\u3036\u3037\u303E\u303F\u3190\u3191\u3196-\u319F\u31C0-\u31E3\u3200-\u321E\u322A-\u3247\u3250\u3260-\u327F\u328A-\u32B0\u32C0-\u32FE\u3300-\u33FF\u4DC0-\u4DFF\uA490-\uA4C6\uA828-\uA82B\uA836\uA837\uA839\uAA77-\uAA79\uFDFD\uFFE4\uFFE8\uFFED\uFFEE\uFFFC\uFFFD\U00010137-\U0001013F\U00010179-\U00010189\U0001018C-\U0001018E\U00010190-\U0001019B\U000101A0\U000101D0-\U000101FC\U00010877\U00010878\U00010AC8\U0001173F\U00016B3C-\U00016B3F\U00016B45\U0001BC9C\U0001D000-\U0001D0F5\U0001D100-\U0001D126\U0001D129-\U0001D164\U0001D16A-\U0001D16C\U0001D183\U0001D184\U0001D18C-\U0001D1A9\U0001D1AE-\U0001D1E8\U0001D200-\U0001D241\U0001D245\U0001D300-\U0001D356\U0001D800-\U0001D9FF\U0001DA37-\U0001DA3A\U0001DA6D-\U0001DA74\U0001DA76-\U0001DA83\U0001DA85\U0001DA86\U0001ECAC\U0001F000-\U0001F02B\U0001F030-\U0001F093\U0001F0A0-\U0001F0AE\U0001F0B1-\U0001F0BF\U0001F0C1-\U0001F0CF\U0001F0D1-\U0001F0F5\U0001F110-\U0001F16B\U0001F170-\U0001F1AC\U0001F1E6-\U0001F202\U0001F210-\U0001F23B\U0001F240-\U0001F248\U0001F250\U0001F251\U0001F260-\U0001F265\U0001F300-\U0001F3FA\U0001F400-\U0001F6D4\U0001F6E0-\U0001F6EC\U0001F6F0-\U0001F6F9\U0001F700-\U0001F773\U0001F780-\U0001F7D8\U0001F800-\U0001F80B\U0001F810-\U0001F847\U0001F850-\U0001F859\U0001F860-\U0001F887\U0001F890-\U0001F8AD\U0001F900-\U0001F90B\U0001F910-\U0001F93E\U0001F940-\U0001F970\U0001F973-\U0001F976\U0001F97A\U0001F97C-\U0001F9A2\U0001F9B0-\U0001F9B9\U0001F9C0-\U0001F9C2\U0001F9D0-\U0001F9FF\U0001FA60-\U0001FA6D]|(?<=[a-z\uFF41-\uFF5A\u00DF-\u00F6\u00F8-\u00FF\u0101\u0103\u0105\u0107\u0109\u010B\u010D\u010F\u0111\u0113\u0115\u0117\u0119\u011B\u011D\u011F\u0121\u0123\u0125\u0127\u0129\u012B\u012D\u012F\u0131\u0133\u0135\u0137\u0138\u013A\u013C\u013E\u0140\u0142\u0144\u0146\u0148\u0149\u014B\u014D\u014F\u0151\u0153\u0155\u0157\u0159\u015B\u015D\u015F\u0161\u0163\u0165\u0167\u0169\u016B\u016D\u016F\u0171\u0173\u0175\u0177\u017A\u017C\u017E\u017F\u0180\u0183\u0185\u0188\u018C\u018D\u0192\u0195\u0199-\u019B\u019E\u01A1\u01A3\u01A5\u01A8\u01AA\u01AB\u01AD\u01B0\u01B4\u01B6\u01B9\u01BA\u01BD-\u01BF\u01C6\u01C9\u01CC\u01CE\u01D0\u01D2\u01D4\u01D6\u01D8\u01DA\u01DC\u01DD\u01DF\u01E1\u01E3\u01E5\u01E7\u01E9\u01EB\u01ED\u01EF\u01F0\u01F3\u01F5\u01F9\u01FB\u01FD\u01FF\u0201\u0203\u0205\u0207\u0209\u020B\u020D\u020F\u0211\u0213\u0215\u0217\u0219\u021B\u021D\u021F\u0221\u0223\u0225\u0227\u0229\u022B\u022D\u022F\u0231\u0233-\u0239\u023C\u023F\u0240\u0242\u0247\u0249\u024B\u024D\u024F\u2C61\u2C65\u2C66\u2C68\u2C6A\u2C6C\u2C71\u2C73\u2C74\u2C76-\u2C7B\uA723\uA725\uA727\uA729\uA72B\uA72D\uA72F-\uA731\uA733\uA735\uA737\uA739\uA73B\uA73D\uA73F\uA741\uA743\uA745\uA747\uA749\uA74B\uA74D\uA74F\uA751\uA753\uA755\uA757\uA759\uA75B\uA75D\uA75F\uA761\uA763\uA765\uA767\uA769\uA76B\uA76D\uA76F\uA771-\uA778\uA77A\uA77C\uA77F\uA781\uA783\uA785\uA787\uA78C\uA78E\uA791\uA793-\uA795\uA797\uA799\uA79B\uA79D\uA79F\uA7A1\uA7A3\uA7A5\uA7A7\uA7A9\uA7AF\uA7B5\uA7B7\uA7B9\uA7FA\uAB30-\uAB5A\uAB60-\uAB64\u0250-\u02AF\u1D00-\u1D25\u1D6B-\u1D77\u1D79-\u1D9A\u1E01\u1E03\u1E05\u1E07\u1E09\u1E0B\u1E0D\u1E0F\u1E11\u1E13\u1E15\u1E17\u1E19\u1E1B\u1E1D\u1E1F\u1E21\u1E23\u1E25\u1E27\u1E29\u1E2B\u1E2D\u1E2F\u1E31\u1E33\u1E35\u1E37\u1E39\u1E3B\u1E3D\u1E3F\u1E41\u1E43\u1E45\u1E47\u1E49\u1E4B\u1E4D\u1E4F\u1E51\u1E53\u1E55\u1E57\u1E59\u1E5B\u1E5D\u1E5F\u1E61\u1E63\u1E65\u1E67\u1E69\u1E6B\u1E6D\u1E6F\u1E71\u1E73\u1E75\u1E77\u1E79\u1E7B\u1E7D\u1E7F\u1E81\u1E83\u1E85\u1E87\u1E89\u1E8B\u1E8D\u1E8F\u1E91\u1E93\u1E95-\u1E9D\u1E9F\u1EA1\u1EA3\u1EA5\u1EA7\u1EA9\u1EAB\u1EAD\u1EAF\u1EB1\u1EB3\u1EB5\u1EB7\u1EB9\u1EBB\u1EBD\u1EBF\u1EC1\u1EC3\u1EC5\u1EC7\u1EC9\u1ECB\u1ECD\u1ECF\u1ED1\u1ED3\u1ED5\u1ED7\u1ED9\u1EDB\u1EDD\u1EDF\u1EE1\u1EE3\u1EE5\u1EE7\u1EE9\u1EEB\u1EED\u1EEF\u1EF1\u1EF3\u1EF5\u1EF7\u1EF9\u1EFB\u1EFD\u1EFFёа-яәөүҗңһα-ωάέίόώήύа-щюяіїєґѓѕјљњќѐѝ\u1200-\u137F\u0980-\u09FF\u0591-\u05F4\uFB1D-\uFB4F\u0620-\u064A\u066E-\u06D5\u06E5-\u06FF\u0750-\u077F\u08A0-\u08BD\uFB50-\uFBB1\uFBD3-\uFD3D\uFD50-\uFDC7\uFDF0-\uFDFB\uFE70-\uFEFC\U0001EE00-\U0001EEBB\u0D80-\u0DFF\u0900-\u097F\u0C80-\u0CFF\u0B80-\u0BFF\u0C00-\u0C7F\uAC00-\uD7AF\u1100-\u11FF\u3040-\u309F\u30A0-\u30FFー\u4E00-\u62FF\u6300-\u77FF\u7800-\u8CFF\u8D00-\u9FFF\u3400-\u4DBF\U00020000-\U000215FF\U00021600-\U000230FF\U00023100-\U000245FF\U00024600-\U000260FF\U00026100-\U000275FF\U00027600-\U000290FF\U00029100-\U0002A6DF\U0002A700-\U0002B73F\U0002B740-\U0002B81F\U0002B820-\U0002CEAF\U0002CEB0-\U0002EBEF\u2E80-\u2EFF\u2F00-\u2FDF\u2FF0-\u2FFF\u3000-\u303F\u31C0-\u31EF\u3200-\u32FF\u3300-\u33FF\uF900-\uFAFF\uFE30-\uFE4F\U0001F200-\U0001F2FF\U0002F800-\U0002FA1F])\.(?=[A-Z\uFF21-\uFF3A\u00C0-\u00D6\u00D8-\u00DE\u0100\u0102\u0104\u0106\u0108\u010A\u010C\u010E\u0110\u0112\u0114\u0116\u0118\u011A\u011C\u011E\u0120\u0122\u0124\u0126\u0128\u012A\u012C\u012E\u0130\u0132\u0134\u0136\u0139\u013B\u013D\u013F\u0141\u0143\u0145\u0147\u014A\u014C\u014E\u0150\u0152\u0154\u0156\u0158\u015A\u015C\u015E\u0160\u0162\u0164\u0166\u0168\u016A\u016C\u016E\u0170\u0172\u0174\u0176\u0178\u0179\u017B\u017D\u0181\u0182\u0184\u0186\u0187\u0189-\u018B\u018E-\u0191\u0193\u0194\u0196-\u0198\u019C\u019D\u019F\u01A0\u01A2\u01A4\u01A6\u01A7\u01A9\u01AC\u01AE\u01AF\u01B1-\u01B3\u01B5\u01B7\u01B8\u01BC\u01C4\u01C7\u01CA\u01CD\u01CF\u01D1\u01D3\u01D5\u01D7\u01D9\u01DB\u01DE\u01E0\u01E2\u01E4\u01E6\u01E8\u01EA\u01EC\u01EE\u01F1\u01F4\u01F6-\u01F8\u01FA\u01FC\u01FE\u0200\u0202\u0204\u0206\u0208\u020A\u020C\u020E\u0210\u0212\u0214\u0216\u0218\u021A\u021C\u021E\u0220\u0222\u0224\u0226\u0228\u022A\u022C\u022E\u0230\u0232\u023A\u023B\u023D\u023E\u0241\u0243-\u0246\u0248\u024A\u024C\u024E\u2C60\u2C62-\u2C64\u2C67\u2C69\u2C6B\u2C6D-\u2C70\u2C72\u2C75\u2C7E\u2C7F\uA722\uA724\uA726\uA728\uA72A\uA72C\uA72E\uA732\uA734\uA736\uA738\uA73A\uA73C\uA73E\uA740\uA742\uA744\uA746\uA748\uA74A\uA74C\uA74E\uA750\uA752\uA754\uA756\uA758\uA75A\uA75C\uA75E\uA760\uA762\uA764\uA766\uA768\uA76A\uA76C\uA76E\uA779\uA77B\uA77D\uA77E\uA780\uA782\uA784\uA786\uA78B\uA78D\uA790\uA792\uA796\uA798\uA79A\uA79C\uA79E\uA7A0\uA7A2\uA7A4\uA7A6\uA7A8\uA7AA-\uA7AE\uA7B0-\uA7B4\uA7B6\uA7B8\u1E00\u1E02\u1E04\u1E06\u1E08\u1E0A\u1E0C\u1E0E\u1E10\u1E12\u1E14\u1E16\u1E18\u1E1A\u1E1C\u1E1E\u1E20\u1E22\u1E24\u1E26\u1E28\u1E2A\u1E2C\u1E2E\u1E30\u1E32\u1E34\u1E36\u1E38\u1E3A\u1E3C\u1E3E\u1E40\u1E42\u1E44\u1E46\u1E48\u1E4A\u1E4C\u1E4E\u1E50\u1E52\u1E54\u1E56\u1E58\u1E5A\u1E5C\u1E5E\u1E60\u1E62\u1E64\u1E66\u1E68\u1E6A\u1E6C\u1E6E\u1E70\u1E72\u1E74\u1E76\u1E78\u1E7A\u1E7C\u1E7E\u1E80\u1E82\u1E84\u1E86\u1E88\u1E8A\u1E8C\u1E8E\u1E90\u1E92\u1E94\u1E9E\u1EA0\u1EA2\u1EA4\u1EA6\u1EA8\u1EAA\u1EAC\u1EAE\u1EB0\u1EB2\u1EB4\u1EB6\u1EB8\u1EBA\u1EBC\u1EBE\u1EC0\u1EC2\u1EC4\u1EC6\u1EC8\u1ECA\u1ECC\u1ECE\u1ED0\u1ED2\u1ED4\u1ED6\u1ED8\u1EDA\u1EDC\u1EDE\u1EE0\u1EE2\u1EE4\u1EE6\u1EE8\u1EEA\u1EEC\u1EEE\u1EF0\u1EF2\u1EF4\u1EF6\u1EF8\u1EFA\u1EFC\u1EFEЁА-ЯӘӨҮҖҢҺΑ-ΩΆΈΊΌΏΉΎА-ЩЮЯІЇЄҐЃЅЈЉЊЌЀЍ\u1200-\u137F\u0980-\u09FF\u0591-\u05F4\uFB1D-\uFB4F\u0620-\u064A\u066E-\u06D5\u06E5-\u06FF\u0750-\u077F\u08A0-\u08BD\uFB50-\uFBB1\uFBD3-\uFD3D\uFD50-\uFDC7\uFDF0-\uFDFB\uFE70-\uFEFC\U0001EE00-\U0001EEBB\u0D80-\u0DFF\u0900-\u097F\u0C80-\u0CFF\u0B80-\u0BFF\u0C00-\u0C7F\uAC00-\uD7AF\u1100-\u11FF\u3040-\u309F\u30A0-\u30FFー\u4E00-\u62FF\u6300-\u77FF\u7800-\u8CFF\u8D00-\u9FFF\u3400-\u4DBF\U00020000-\U000215FF\U00021600-\U000230FF\U00023100-\U000245FF\U00024600-\U000260FF\U00026100-\U000275FF\U00027600-\U000290FF\U00029100-\U0002A6DF\U0002A700-\U0002B73F\U0002B740-\U0002B81F\U0002B820-\U0002CEAF\U0002CEB0-\U0002EBEF\u2E80-\u2EFF\u2F00-\u2FDF\u2FF0-\u2FFF\u3000-\u303F\u31C0-\u31EF\u3200-\u32FF\u3300-\u33FF\uF900-\uFAFF\uFE30-\uFE4F\U0001F200-\U0001F2FF\U0002F800-\U0002FA1F])|(?<=[A-Za-z\uFF21-\uFF3A\uFF41-\uFF5A\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u00FF\u0100-\u017F\u0180-\u01BF\u01C4-\u024F\u2C60-\u2C7B\u2C7E\u2C7F\uA722-\uA76F\uA771-\uA787\uA78B-\uA78E\uA790-\uA7B9\uA7FA\uAB30-\uAB5A\uAB60-\uAB64\u0250-\u02AF\u1D00-\u1D25\u1D6B-\u1D77\u1D79-\u1D9A\u1E00-\u1EFFёа-яЁА-ЯәөүҗңһӘӨҮҖҢҺα-ωάέίόώήύΑ-ΩΆΈΊΌΏΉΎа-щюяіїєґА-ЩЮЯІЇЄҐѓѕјљњќѐѝЃЅЈЉЊЌЀЍ\u1200-\u137F\u0980-\u09FF\u0591-\u05F4\uFB1D-\uFB4F\u0620-\u064A\u066E-\u06D5\u06E5-\u06FF\u0750-\u077F\u08A0-\u08BD\uFB50-\uFBB1\uFBD3-\uFD3D\uFD50-\uFDC7\uFDF0-\uFDFB\uFE70-\uFEFC\U0001EE00-\U0001EEBB\u0D80-\u0DFF\u0900-\u097F\u0C80-\u0CFF\u0B80-\u0BFF\u0C00-\u0C7F\uAC00-\uD7AF\u1100-\u11FF\u3040-\u309F\u30A0-\u30FFー\u4E00-\u62FF\u6300-\u77FF\u7800-\u8CFF\u8D00-\u9FFF\u3400-\u4DBF\U00020000-\U000215FF\U00021600-\U000230FF\U00023100-\U000245FF\U00024600-\U000260FF\U00026100-\U000275FF\U00027600-\U000290FF\U00029100-\U0002A6DF\U0002A700-\U0002B73F\U0002B740-\U0002B81F\U0002B820-\U0002CEAF\U0002CEB0-\U0002EBEF\u2E80-\u2EFF\u2F00-\u2FDF\u2FF0-\u2FFF\u3000-\u303F\u31C0-\u31EF\u3200-\u32FF\u3300-\u33FF\uF900-\uFAFF\uFE30-\uFE4F\U0001F200-\U0001F2FF\U0002F800-\U0002FA1F])[,!?](?=[A-Za-z\uFF21-\uFF3A\uFF41-\uFF5A\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u00FF\u0100-\u017F\u0180-\u01BF\u01C4-\u024F\u2C60-\u2C7B\u2C7E\u2C7F\uA722-\uA76F\uA771-\uA787\uA78B-\uA78E\uA790-\uA7B9\uA7FA\uAB30-\uAB5A\uAB60-\uAB64\u0250-\u02AF\u1D00-\u1D25\u1D6B-\u1D77\u1D79-\u1D9A\u1E00-\u1EFFёа-яЁА-ЯәөүҗңһӘӨҮҖҢҺα-ωάέίόώήύΑ-ΩΆΈΊΌΏΉΎа-щюяіїєґА-ЩЮЯІЇЄҐѓѕјљњќѐѝЃЅЈЉЊЌЀЍ\u1200-\u137F\u0980-\u09FF\u0591-\u05F4\uFB1D-\uFB4F\u0620-\u064A\u066E-\u06D5\u06E5-\u06FF\u0750-\u077F\u08A0-\u08BD\uFB50-\uFBB1\uFBD3-\uFD3D\uFD50-\uFDC7\uFDF0-\uFDFB\uFE70-\uFEFC\U0001EE00-\U0001EEBB\u0D80-\u0DFF\u0900-\u097F\u0C80-\u0CFF\u0B80-\u0BFF\u0C00-\u0C7F\uAC00-\uD7AF\u1100-\u11FF\u3040-\u309F\u30A0-\u30FFー\u4E00-\u62FF\u6300-\u77FF\u7800-\u8CFF\u8D00-\u9FFF\u3400-\u4DBF\U00020000-\U000215FF\U00021600-\U000230FF\U00023100-\U000245FF\U00024600-\U000260FF\U00026100-\U000275FF\U00027600-\U000290FF\U00029100-\U0002A6DF\U0002A700-\U0002B73F\U0002B740-\U0002B81F\U0002B820-\U0002CEAF\U0002CEB0-\U0002EBEF\u2E80-\u2EFF\u2F00-\u2FDF\u2FF0-\u2FFF\u3000-\u303F\u31C0-\u31EF\u3200-\u32FF\u3300-\u33FF\uF900-\uFAFF\uFE30-\uFE4F\U0001F200-\U0001F2FF\U0002F800-\U0002FA1F])|(?<=[A-Za-z\uFF21-\uFF3A\uFF41-\uFF5A\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u00FF\u0100-\u017F\u0180-\u01BF\u01C4-\u024F\u2C60-\u2C7B\u2C7E\u2C7F\uA722-\uA76F\uA771-\uA787\uA78B-\uA78E\uA790-\uA7B9\uA7FA\uAB30-\uAB5A\uAB60-\uAB64\u0250-\u02AF\u1D00-\u1D25\u1D6B-\u1D77\u1D79-\u1D9A\u1E00-\u1EFFёа-яЁА-ЯәөүҗңһӘӨҮҖҢҺα-ωάέίόώήύΑ-ΩΆΈΊΌΏΉΎа-щюяіїєґА-ЩЮЯІЇЄҐѓѕјљњќѐѝЃЅЈЉЊЌЀЍ\u1200-\u137F\u0980-\u09FF\u0591-\u05F4\uFB1D-\uFB4F\u0620-\u064A\u066E-\u06D5\u06E5-\u06FF\u0750-\u077F\u08A0-\u08BD\uFB50-\uFBB1\uFBD3-\uFD3D\uFD50-\uFDC7\uFDF0-\uFDFB\uFE70-\uFEFC\U0001EE00-\U0001EEBB\u0D80-\u0DFF\u0900-\u097F\u0C80-\u0CFF\u0B80-\u0BFF\u0C00-\u0C7F\uAC00-\uD7AF\u1100-\u11FF\u3040-\u309F\u30A0-\u30FFー\u4E00-\u62FF\u6300-\u77FF\u7800-\u8CFF\u8D00-\u9FFF\u3400-\u4DBF\U00020000-\U000215FF\U00021600-\U000230FF\U00023100-\U000245FF\U00024600-\U000260FF\U00026100-\U000275FF\U00027600-\U000290FF\U00029100-\U0002A6DF\U0002A700-\U0002B73F\U0002B740-\U0002B81F\U0002B820-\U0002CEAF\U0002CEB0-\U0002EBEF\u2E80-\u2EFF\u2F00-\u2FDF\u2FF0-\u2FFF\u3000-\u303F\u31C0-\u31EF\u3200-\u32FF\u3300-\u33FF\uF900-\uFAFF\uFE30-\uFE4F\U0001F200-\U0001F2FF\U0002F800-\U0002FA1F])[:<>=](?=[A-Za-z\uFF21-\uFF3A\uFF41-\uFF5A\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u00FF\u0100-\u017F\u0180-\u01BF\u01C4-\u024F\u2C60-\u2C7B\u2C7E\u2C7F\uA722-\uA76F\uA771-\uA787\uA78B-\uA78E\uA790-\uA7B9\uA7FA\uAB30-\uAB5A\uAB60-\uAB64\u0250-\u02AF\u1D00-\u1D25\u1D6B-\u1D77\u1D79-\u1D9A\u1E00-\u1EFFёа-яЁА-ЯәөүҗңһӘӨҮҖҢҺα-ωάέίόώήύΑ-ΩΆΈΊΌΏΉΎа-щюяіїєґА-ЩЮЯІЇЄҐѓѕјљњќѐѝЃЅЈЉЊЌЀЍ\u1200-\u137F\u0980-\u09FF\u0591-\u05F4\uFB1D-\uFB4F\u0620-\u064A\u066E-\u06D5\u06E5-\u06FF\u0750-\u077F\u08A0-\u08BD\uFB50-\uFBB1\uFBD3-\uFD3D\uFD50-\uFDC7\uFDF0-\uFDFB\uFE70-\uFEFC\U0001EE00-\U0001EEBB\u0D80-\u0DFF\u0900-\u097F\u0C80-\u0CFF\u0B80-\u0BFF\u0C00-\u0C7F\uAC00-\uD7AF\u1100-\u11FF\u3040-\u309F\u30A0-\u30FFー\u4E00-\u62FF\u6300-\u77FF\u7800-\u8CFF\u8D00-\u9FFF\u3400-\u4DBF\U00020000-\U000215FF\U00021600-\U000230FF\U00023100-\U000245FF\U00024600-\U000260FF\U00026100-\U000275FF\U00027600-\U000290FF\U00029100-\U0002A6DF\U0002A700-\U0002B73F\U0002B740-\U0002B81F\U0002B820-\U0002CEAF\U0002CEB0-\U0002EBEF\u2E80-\u2EFF\u2F00-\u2FDF\u2FF0-\u2FFF\u3000-\u303F\u31C0-\u31EF\u3200-\u32FF\u3300-\u33FF\uF900-\uFAFF\uFE30-\uFE4F\U0001F200-\U0001F2FF\U0002F800-\U0002FA1F])|(?<=[A-Za-z\uFF21-\uFF3A\uFF41-\uFF5A\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u00FF\u0100-\u017F\u0180-\u01BF\u01C4-\u024F\u2C60-\u2C7B\u2C7E\u2C7F\uA722-\uA76F\uA771-\uA787\uA78B-\uA78E\uA790-\uA7B9\uA7FA\uAB30-\uAB5A\uAB60-\uAB64\u0250-\u02AF\u1D00-\u1D25\u1D6B-\u1D77\u1D79-\u1D9A\u1E00-\u1EFFёа-яЁА-ЯәөүҗңһӘӨҮҖҢҺα-ωάέίόώήύΑ-ΩΆΈΊΌΏΉΎа-щюяіїєґА-ЩЮЯІЇЄҐѓѕјљњќѐѝЃЅЈЉЊЌЀЍ\u1200-\u137F\u0980-\u09FF\u0591-\u05F4\uFB1D-\uFB4F\u0620-\u064A\u066E-\u06D5\u06E5-\u06FF\u0750-\u077F\u08A0-\u08BD\uFB50-\uFBB1\uFBD3-\uFD3D\uFD50-\uFDC7\uFDF0-\uFDFB\uFE70-\uFEFC\U0001EE00-\U0001EEBB\u0D80-\u0DFF\u0900-\u097F\u0C80-\u0CFF\u0B80-\u0BFF\u0C00-\u0C7F\uAC00-\uD7AF\u1100-\u11FF\u3040-\u309F\u30A0-\u30FFー\u4E00-\u62FF\u6300-\u77FF\u7800-\u8CFF\u8D00-\u9FFF\u3400-\u4DBF\U00020000-\U000215FF\U00021600-\U000230FF\U00023100-\U000245FF\U00024600-\U000260FF\U00026100-\U000275FF\U00027600-\U000290FF\U00029100-\U0002A6DF\U0002A700-\U0002B73F\U0002B740-\U0002B81F\U0002B820-\U0002CEAF\U0002CEB0-\U0002EBEF\u2E80-\u2EFF\u2F00-\u2FDF\u2FF0-\u2FFF\u3000-\u303F\u31C0-\u31EF\u3200-\u32FF\u3300-\u33FF\uF900-\uFAFF\uFE30-\uFE4F\U0001F200-\U0001F2FF\U0002F800-\U0002FA1F]),(?=[A-Za-z\uFF21-\uFF3A\uFF41-\uFF5A\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u00FF\u0100-\u017F\u0180-\u01BF\u01C4-\u024F\u2C60-\u2C7B\u2C7E\u2C7F\uA722-\uA76F\uA771-\uA787\uA78B-\uA78E\uA790-\uA7B9\uA7FA\uAB30-\uAB5A\uAB60-\uAB64\u0250-\u02AF\u1D00-\u1D25\u1D6B-\u1D77\u1D79-\u1D9A\u1E00-\u1EFFёа-яЁА-ЯәөүҗңһӘӨҮҖҢҺα-ωάέίόώήύΑ-ΩΆΈΊΌΏΉΎа-щюяіїєґА-ЩЮЯІЇЄҐѓѕјљњќѐѝЃЅЈЉЊЌЀЍ\u1200-\u137F\u0980-\u09FF\u0591-\u05F4\uFB1D-\uFB4F\u0620-\u064A\u066E-\u06D5\u06E5-\u06FF\u0750-\u077F\u08A0-\u08BD\uFB50-\uFBB1\uFBD3-\uFD3D\uFD50-\uFDC7\uFDF0-\uFDFB\uFE70-\uFEFC\U0001EE00-\U0001EEBB\u0D80-\u0DFF\u0900-\u097F\u0C80-\u0CFF\u0B80-\u0BFF\u0C00-\u0C7F\uAC00-\uD7AF\u1100-\u11FF\u3040-\u309F\u30A0-\u30FFー\u4E00-\u62FF\u6300-\u77FF\u7800-\u8CFF\u8D00-\u9FFF\u3400-\u4DBF\U00020000-\U000215FF\U00021600-\U000230FF\U00023100-\U000245FF\U00024600-\U000260FF\U00026100-\U000275FF\U00027600-\U000290FF\U00029100-\U0002A6DF\U0002A700-\U0002B73F\U0002B740-\U0002B81F\U0002B820-\U0002CEAF\U0002CEB0-\U0002EBEF\u2E80-\u2EFF\u2F00-\u2FDF\u2FF0-\u2FFF\u3000-\u303F\u31C0-\u31EF\u3200-\u32FF\u3300-\u33FF\uF900-\uFAFF\uFE30-\uFE4F\U0001F200-\U0001F2FF\U0002F800-\U0002FA1F])|(?<=[0-9A-Za-z\uFF21-\uFF3A\uFF41-\uFF5A\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u00FF\u0100-\u017F\u0180-\u01BF\u01C4-\u024F\u2C60-\u2C7B\u2C7E\u2C7F\uA722-\uA76F\uA771-\uA787\uA78B-\uA78E\uA790-\uA7B9\uA7FA\uAB30-\uAB5A\uAB60-\uAB64\u0250-\u02AF\u1D00-\u1D25\u1D6B-\u1D77\u1D79-\u1D9A\u1E00-\u1EFFёа-яЁА-ЯәөүҗңһӘӨҮҖҢҺα-ωάέίόώήύΑ-ΩΆΈΊΌΏΉΎа-щюяіїєґА-ЩЮЯІЇЄҐѓѕјљњќѐѝЃЅЈЉЊЌЀЍ\u1200-\u137F\u0980-\u09FF\u0591-\u05F4\uFB1D-\uFB4F\u0620-\u064A\u066E-\u06D5\u06E5-\u06FF\u0750-\u077F\u08A0-\u08BD\uFB50-\uFBB1\uFBD3-\uFD3D\uFD50-\uFDC7\uFDF0-\uFDFB\uFE70-\uFEFC\U0001EE00-\U0001EEBB\u0D80-\u0DFF\u0900-\u097F\u0C80-\u0CFF\u0B80-\u0BFF\u0C00-\u0C7F\uAC00-\uD7AF\u1100-\u11FF\u3040-\u309F\u30A0-\u30FFー\u4E00-\u62FF\u6300-\u77FF\u7800-\u8CFF\u8D00-\u9FFF\u3400-\u4DBF\U00020000-\U000215FF\U00021600-\U000230FF\U00023100-\U000245FF\U00024600-\U000260FF\U00026100-\U000275FF\U00027600-\U000290FF\U00029100-\U0002A6DF\U0002A700-\U0002B73F\U0002B740-\U0002B81F\U0002B820-\U0002CEAF\U0002CEB0-\U0002EBEF\u2E80-\u2EFF\u2F00-\u2FDF\u2FF0-\u2FFF\u3000-\u303F\u31C0-\u31EF\u3200-\u32FF\u3300-\u33FF\uF900-\uFAFF\uFE30-\uFE4F\U0001F200-\U0001F2FF\U0002F800-\U0002FA1F])\/(?=[0-9A-Za-z\uFF21-\uFF3A\uFF41-\uFF5A\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u00FF\u0100-\u017F\u0180-\u01BF\u01C4-\u024F\u2C60-\u2C7B\u2C7E\u2C7F\uA722-\uA76F\uA771-\uA787\uA78B-\uA78E\uA790-\uA7B9\uA7FA\uAB30-\uAB5A\uAB60-\uAB64\u0250-\u02AF\u1D00-\u1D25\u1D6B-\u1D77\u1D79-\u1D9A\u1E00-\u1EFFёа-яЁА-ЯәөүҗңһӘӨҮҖҢҺα-ωάέίόώήύΑ-ΩΆΈΊΌΏΉΎа-щюяіїєґА-ЩЮЯІЇЄҐѓѕјљњќѐѝЃЅЈЉЊЌЀЍ\u1200-\u137F\u0980-\u09FF\u0591-\u05F4\uFB1D-\uFB4F\u0620-\u064A\u066E-\u06D5\u06E5-\u06FF\u0750-\u077F\u08A0-\u08BD\uFB50-\uFBB1\uFBD3-\uFD3D\uFD50-\uFDC7\uFDF0-\uFDFB\uFE70-\uFEFC\U0001EE00-\U0001EEBB\u0D80-\u0DFF\u0900-\u097F\u0C80-\u0CFF\u0B80-\u0BFF\u0C00-\u0C7F\uAC00-\uD7AF\u1100-\u11FF\u3040-\u309F\u30A0-\u30FFー\u4E00-\u62FF\u6300-\u77FF\u7800-\u8CFF\u8D00-\u9FFF\u3400-\u4DBF\U00020000-\U000215FF\U00021600-\U000230FF\U00023100-\U000245FF\U00024600-\U000260FF\U00026100-\U000275FF\U00027600-\U000290FF\U00029100-\U0002A6DF\U0002A700-\U0002B73F\U0002B740-\U0002B81F\U0002B820-\U0002CEAF\U0002CEB0-\U0002EBEF\u2E80-\u2EFF\u2F00-\u2FDF\u2FF0-\u2FFF\u3000-\u303F\u31C0-\u31EF\u3200-\u32FF\u3300-\u33FF\uF900-\uFAFF\uFE30-\uFE4F\U0001F200-\U0001F2FF\U0002F800-\U0002FA1F])|(?<=[A-Za-z\uFF21-\uFF3A\uFF41-\uFF5A\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u00FF\u0100-\u017F\u0180-\u01BF\u01C4-\u024F\u2C60-\u2C7B\u2C7E\u2C7F\uA722-\uA76F\uA771-\uA787\uA78B-\uA78E\uA790-\uA7B9\uA7FA\uAB30-\uAB5A\uAB60-\uAB64\u0250-\u02AF\u1D00-\u1D25\u1D6B-\u1D77\u1D79-\u1D9A\u1E00-\u1EFFёа-яЁА-ЯәөүҗңһӘӨҮҖҢҺα-ωάέίόώήύΑ-ΩΆΈΊΌΏΉΎа-щюяіїєґА-ЩЮЯІЇЄҐѓѕјљњќѐѝЃЅЈЉЊЌЀЍ\u1200-\u137F\u0980-\u09FF\u0591-\u05F4\uFB1D-\uFB4F\u0620-\u064A\u066E-\u06D5\u06E5-\u06FF\u0750-\u077F\u08A0-\u08BD\uFB50-\uFBB1\uFBD3-\uFD3D\uFD50-\uFDC7\uFDF0-\uFDFB\uFE70-\uFEFC\U0001EE00-\U0001EEBB\u0D80-\u0DFF\u0900-\u097F\u0C80-\u0CFF\u0B80-\u0BFF\u0C00-\u0C7F\uAC00-\uD7AF\u1100-\u11FF\u3040-\u309F\u30A0-\u30FFー\u4E00-\u62FF\u6300-\u77FF\u7800-\u8CFF\u8D00-\u9FFF\u3400-\u4DBF\U00020000-\U000215FF\U00021600-\U000230FF\U00023100-\U000245FF\U00024600-\U000260FF\U00026100-\U000275FF\U00027600-\U000290FF\U00029100-\U0002A6DF\U0002A700-\U0002B73F\U0002B740-\U0002B81F\U0002B820-\U0002CEAF\U0002CEB0-\U0002EBEF\u2E80-\u2EFF\u2F00-\u2FDF\u2FF0-\u2FFF\u3000-\u303F\u31C0-\u31EF\u3200-\u32FF\u3300-\u33FF\uF900-\uFAFF\uFE30-\uFE4F\U0001F200-\U0001F2FF\U0002F800-\U0002FA1F])([\"”“`‘´’‚,„»«「」『』()〔〕【】《》〈〉〈〉⟦⟧\)\]\(\[])(?=[A-Za-z\uFF21-\uFF3A\uFF41-\uFF5A\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u00FF\u0100-\u017F\u0180-\u01BF\u01C4-\u024F\u2C60-\u2C7B\u2C7E\u2C7F\uA722-\uA76F\uA771-\uA787\uA78B-\uA78E\uA790-\uA7B9\uA7FA\uAB30-\uAB5A\uAB60-\uAB64\u0250-\u02AF\u1D00-\u1D25\u1D6B-\u1D77\u1D79-\u1D9A\u1E00-\u1EFFёа-яЁА-ЯәөүҗңһӘӨҮҖҢҺα-ωάέίόώήύΑ-ΩΆΈΊΌΏΉΎа-щюяіїєґА-ЩЮЯІЇЄҐѓѕјљњќѐѝЃЅЈЉЊЌЀЍ\u1200-\u137F\u0980-\u09FF\u0591-\u05F4\uFB1D-\uFB4F\u0620-\u064A\u066E-\u06D5\u06E5-\u06FF\u0750-\u077F\u08A0-\u08BD\uFB50-\uFBB1\uFBD3-\uFD3D\uFD50-\uFDC7\uFDF0-\uFDFB\uFE70-\uFEFC\U0001EE00-\U0001EEBB\u0D80-\u0DFF\u0900-\u097F\u0C80-\u0CFF\u0B80-\u0BFF\u0C00-\u0C7F\uAC00-\uD7AF\u1100-\u11FF\u3040-\u309F\u30A0-\u30FFー\u4E00-\u62FF\u6300-\u77FF\u7800-\u8CFF\u8D00-\u9FFF\u3400-\u4DBF\U00020000-\U000215FF\U00021600-\U000230FF\U00023100-\U000245FF\U00024600-\U000260FF\U00026100-\U000275FF\U00027600-\U000290FF\U00029100-\U0002A6DF\U0002A700-\U0002B73F\U0002B740-\U0002B81F\U0002B820-\U0002CEAF\U0002CEB0-\U0002EBEF\u2E80-\u2EFF\u2F00-\u2FDF\u2FF0-\u2FFF\u3000-\u303F\u31C0-\u31EF\u3200-\u32FF\u3300-\u33FF\uF900-\uFAFF\uFE30-\uFE4F\U0001F200-\U0001F2FF\U0002F800-\U0002FA1F])|(?<=[A-Za-z\uFF21-\uFF3A\uFF41-\uFF5A\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u00FF\u0100-\u017F\u0180-\u01BF\u01C4-\u024F\u2C60-\u2C7B\u2C7E\u2C7F\uA722-\uA76F\uA771-\uA787\uA78B-\uA78E\uA790-\uA7B9\uA7FA\uAB30-\uAB5A\uAB60-\uAB64\u0250-\u02AF\u1D00-\u1D25\u1D6B-\u1D77\u1D79-\u1D9A\u1E00-\u1EFFёа-яЁА-ЯәөүҗңһӘӨҮҖҢҺα-ωάέίόώήύΑ-ΩΆΈΊΌΏΉΎа-щюяіїєґА-ЩЮЯІЇЄҐѓѕјљњќѐѝЃЅЈЉЊЌЀЍ\u1200-\u137F\u0980-\u09FF\u0591-\u05F4\uFB1D-\uFB4F\u0620-\u064A\u066E-\u06D5\u06E5-\u06FF\u0750-\u077F\u08A0-\u08BD\uFB50-\uFBB1\uFBD3-\uFD3D\uFD50-\uFDC7\uFDF0-\uFDFB\uFE70-\uFEFC\U0001EE00-\U0001EEBB\u0D80-\u0DFF\u0900-\u097F\u0C80-\u0CFF\u0B80-\u0BFF\u0C00-\u0C7F\uAC00-\uD7AF\u1100-\u11FF\u3040-\u309F\u30A0-\u30FFー\u4E00-\u62FF\u6300-\u77FF\u7800-\u8CFF\u8D00-\u9FFF\u3400-\u4DBF\U00020000-\U000215FF\U00021600-\U000230FF\U00023100-\U000245FF\U00024600-\U000260FF\U00026100-\U000275FF\U00027600-\U000290FF\U00029100-\U0002A6DF\U0002A700-\U0002B73F\U0002B740-\U0002B81F\U0002B820-\U0002CEAF\U0002CEB0-\U0002EBEF\u2E80-\u2EFF\u2F00-\u2FDF\u2FF0-\u2FFF\u3000-\u303F\u31C0-\u31EF\u3200-\u32FF\u3300-\u33FF\uF900-\uFAFF\uFE30-\uFE4F\U0001F200-\U0001F2FF\U0002F800-\U0002FA1F])--(?=[A-Za-z\uFF21-\uFF3A\uFF41-\uFF5A\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u00FF\u0100-\u017F\u0180-\u01BF\u01C4-\u024F\u2C60-\u2C7B\u2C7E\u2C7F\uA722-\uA76F\uA771-\uA787\uA78B-\uA78E\uA790-\uA7B9\uA7FA\uAB30-\uAB5A\uAB60-\uAB64\u0250-\u02AF\u1D00-\u1D25\u1D6B-\u1D77\u1D79-\u1D9A\u1E00-\u1EFFёа-яЁА-ЯәөүҗңһӘӨҮҖҢҺα-ωάέίόώήύΑ-ΩΆΈΊΌΏΉΎа-щюяіїєґА-ЩЮЯІЇЄҐѓѕјљњќѐѝЃЅЈЉЊЌЀЍ\u1200-\u137F\u0980-\u09FF\u0591-\u05F4\uFB1D-\uFB4F\u0620-\u064A\u066E-\u06D5\u06E5-\u06FF\u0750-\u077F\u08A0-\u08BD\uFB50-\uFBB1\uFBD3-\uFD3D\uFD50-\uFDC7\uFDF0-\uFDFB\uFE70-\uFEFC\U0001EE00-\U0001EEBB\u0D80-\u0DFF\u0900-\u097F\u0C80-\u0CFF\u0B80-\u0BFF\u0C00-\u0C7F\uAC00-\uD7AF\u1100-\u11FF\u3040-\u309F\u30A0-\u30FFー\u4E00-\u62FF\u6300-\u77FF\u7800-\u8CFF\u8D00-\u9FFF\u3400-\u4DBF\U00020000-\U000215FF\U00021600-\U000230FF\U00023100-\U000245FF\U00024600-\U000260FF\U00026100-\U000275FF\U00027600-\U000290FF\U00029100-\U0002A6DF\U0002A700-\U0002B73F\U0002B740-\U0002B81F\U0002B820-\U0002CEAF\U0002CEB0-\U0002EBEF\u2E80-\u2EFF\u2F00-\u2FDF\u2FF0-\u2FFF\u3000-\u303F\u31C0-\u31EF\u3200-\u32FF\u3300-\u33FF\uF900-\uFAFF\uFE30-\uFE4F\U0001F200-\U0001F2FF\U0002F800-\U0002FA1F])|(?<=[0-9])-(?=[0-9])token_matchurl_match (?u)^(?:(?:[\w\+\-\.]{2,})://)?(?:\S+(?::\S*)?@)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[A-Za-z0-9\u00a1-\uffff][A-Za-z0-9\u00a1-\uffff_-]{0,62})?[A-Za-z0-9\u00a1-\uffff]\.)+(?:[a-z\uFF41-\uFF5A\u00DF-\u00F6\u00F8-\u00FF\u0101\u0103\u0105\u0107\u0109\u010B\u010D\u010F\u0111\u0113\u0115\u0117\u0119\u011B\u011D\u011F\u0121\u0123\u0125\u0127\u0129\u012B\u012D\u012F\u0131\u0133\u0135\u0137\u0138\u013A\u013C\u013E\u0140\u0142\u0144\u0146\u0148\u0149\u014B\u014D\u014F\u0151\u0153\u0155\u0157\u0159\u015B\u015D\u015F\u0161\u0163\u0165\u0167\u0169\u016B\u016D\u016F\u0171\u0173\u0175\u0177\u017A\u017C\u017E\u017F\u0180\u0183\u0185\u0188\u018C\u018D\u0192\u0195\u0199-\u019B\u019E\u01A1\u01A3\u01A5\u01A8\u01AA\u01AB\u01AD\u01B0\u01B4\u01B6\u01B9\u01BA\u01BD-\u01BF\u01C6\u01C9\u01CC\u01CE\u01D0\u01D2\u01D4\u01D6\u01D8\u01DA\u01DC\u01DD\u01DF\u01E1\u01E3\u01E5\u01E7\u01E9\u01EB\u01ED\u01EF\u01F0\u01F3\u01F5\u01F9\u01FB\u01FD\u01FF\u0201\u0203\u0205\u0207\u0209\u020B\u020D\u020F\u0211\u0213\u0215\u0217\u0219\u021B\u021D\u021F\u0221\u0223\u0225\u0227\u0229\u022B\u022D\u022F\u0231\u0233-\u0239\u023C\u023F\u0240\u0242\u0247\u0249\u024B\u024D\u024F\u2C61\u2C65\u2C66\u2C68\u2C6A\u2C6C\u2C71\u2C73\u2C74\u2C76-\u2C7B\uA723\uA725\uA727\uA729\uA72B\uA72D\uA72F-\uA731\uA733\uA735\uA737\uA739\uA73B\uA73D\uA73F\uA741\uA743\uA745\uA747\uA749\uA74B\uA74D\uA74F\uA751\uA753\uA755\uA757\uA759\uA75B\uA75D\uA75F\uA761\uA763\uA765\uA767\uA769\uA76B\uA76D\uA76F\uA771-\uA778\uA77A\uA77C\uA77F\uA781\uA783\uA785\uA787\uA78C\uA78E\uA791\uA793-\uA795\uA797\uA799\uA79B\uA79D\uA79F\uA7A1\uA7A3\uA7A5\uA7A7\uA7A9\uA7AF\uA7B5\uA7B7\uA7B9\uA7FA\uAB30-\uAB5A\uAB60-\uAB64\u0250-\u02AF\u1D00-\u1D25\u1D6B-\u1D77\u1D79-\u1D9A\u1E01\u1E03\u1E05\u1E07\u1E09\u1E0B\u1E0D\u1E0F\u1E11\u1E13\u1E15\u1E17\u1E19\u1E1B\u1E1D\u1E1F\u1E21\u1E23\u1E25\u1E27\u1E29\u1E2B\u1E2D\u1E2F\u1E31\u1E33\u1E35\u1E37\u1E39\u1E3B\u1E3D\u1E3F\u1E41\u1E43\u1E45\u1E47\u1E49\u1E4B\u1E4D\u1E4F\u1E51\u1E53\u1E55\u1E57\u1E59\u1E5B\u1E5D\u1E5F\u1E61\u1E63\u1E65\u1E67\u1E69\u1E6B\u1E6D\u1E6F\u1E71\u1E73\u1E75\u1E77\u1E79\u1E7B\u1E7D\u1E7F\u1E81\u1E83\u1E85\u1E87\u1E89\u1E8B\u1E8D\u1E8F\u1E91\u1E93\u1E95-\u1E9D\u1E9F\u1EA1\u1EA3\u1EA5\u1EA7\u1EA9\u1EAB\u1EAD\u1EAF\u1EB1\u1EB3\u1EB5\u1EB7\u1EB9\u1EBB\u1EBD\u1EBF\u1EC1\u1EC3\u1EC5\u1EC7\u1EC9\u1ECB\u1ECD\u1ECF\u1ED1\u1ED3\u1ED5\u1ED7\u1ED9\u1EDB\u1EDD\u1EDF\u1EE1\u1EE3\u1EE5\u1EE7\u1EE9\u1EEB\u1EED\u1EEF\u1EF1\u1EF3\u1EF5\u1EF7\u1EF9\u1EFB\u1EFD\u1EFFёа-яәөүҗңһα-ωάέίόώήύа-щюяіїєґѓѕјљњќѐѝ\u1200-\u137F\u0980-\u09FF\u0591-\u05F4\uFB1D-\uFB4F\u0620-\u064A\u066E-\u06D5\u06E5-\u06FF\u0750-\u077F\u08A0-\u08BD\uFB50-\uFBB1\uFBD3-\uFD3D\uFD50-\uFDC7\uFDF0-\uFDFB\uFE70-\uFEFC\U0001EE00-\U0001EEBB\u0D80-\u0DFF\u0900-\u097F\u0C80-\u0CFF\u0B80-\u0BFF\u0C00-\u0C7F\uAC00-\uD7AF\u1100-\u11FF\u3040-\u309F\u30A0-\u30FFー\u4E00-\u62FF\u6300-\u77FF\u7800-\u8CFF\u8D00-\u9FFF\u3400-\u4DBF\U00020000-\U000215FF\U00021600-\U000230FF\U00023100-\U000245FF\U00024600-\U000260FF\U00026100-\U000275FF\U00027600-\U000290FF\U00029100-\U0002A6DF\U0002A700-\U0002B73F\U0002B740-\U0002B81F\U0002B820-\U0002CEAF\U0002CEB0-\U0002EBEF\u2E80-\u2EFF\u2F00-\u2FDF\u2FF0-\u2FFF\u3000-\u303F\u31C0-\u31EF\u3200-\u32FF\u3300-\u33FF\uF900-\uFAFF\uFE30-\uFE4F\U0001F200-\U0001F2FF\U0002F800-\U0002FA1F]{2,63}))(?::\d{2,5})?(?:[/?#]\S*)?$exceptions A +A + A 'A'''A'''SA'SC's'nA'nCein'neA'neCeine'nemA'nemCeinem'nenA'nenCeinen'sA'sC's(*_*)A(*_*)(-8A(-8(-:A(-:(-;A(-;(-_-)A(-_-)(._.)A(._.)(:A(:(;A(;(=A(=(>_<)A(>_<)(^_^)A(^_^)(o:A(o:(¬_¬)A(¬_¬)(ಠ_ಠ)A(ಠ_ಠ)(╯°□°)╯︵┻━┻A(╯°□°)╯︵┻━┻)-:A)-:):A):-_-A-_--__-A-__-._.A._.0.0A0.00.oA0.o0_0A0_00_oA0_o8)A8)8-)A8-)8-DA8-D8DA8D:'(A:'(:')A:'):'-(A:'-(:'-)A:'-):(A:(:((A:((:(((A:(((:()A:():)A:):))A:)):)))A:))):*A:*:-(A:-(:-((A:-((:-(((A:-(((:-)A:-):-))A:-)):-)))A:-))):-*A:-*:-/A:-/:-0A:-0:-3A:-3:->A:->:-DA:-D:-OA:-O:-PA:-P:-XA:-X:-]A:-]:-oA:-o:-pA:-p:-xA:-x:-|A:-|:-}A:-}:/A:/:0A:0:1A:1:3A:3:>A:>:DA:D:OA:O:PA:P:XA:X:]A:]:oA:o:o)A:o):pA:p:xA:x:|A:|:}A:}:’(A:’(:’)A:’):’-(A:’-(:’-)A:’-);)A;);-)A;-);-DA;-D;DA;D;_;A;_;<.A=(A=(=)A=)=/A=/=3A=3=DA=D=[A=[=]A=]=|A=|>..<>.>A>.>>:(A>:(>:oA>:o><(((*>A><(((*>@_@A@_@A.C.AA.C.A.D.AA.D.A.G.AA.G.Abb.AAbb.CAbbildungAbk.AAbk.CAbkürzungAbs.AAbs.Abt.AAbt.CAbteilungApr.AApr.CAprilAug.AAug.CAugustB.A.AB.A.B.Sc.AB.Sc.Bd.ABd.CBandBetr.ABetr.CBetreffBf.ABf.CBahnhofBhf.ABhf.CBahnhofBiol.ABiol.Bsp.ABsp.CBeispielC++AC++CDU/CSUACDU/CSUChr.AChr.Cie.ACie.Co.ACo.D.C.AD.C.Dez.ADez.CDezemberDi.ADi.CDienstagDipl.ADipl.Dipl.-Ing.ADipl.-Ing.Do.ADo.CDonnerstagDr.ADr.Fa.AFa.CFirmaFam.AFam.CFamilieFeb.AFeb.CFebruarFr.AFr.CFrauFrl.AFrl.CFräuleinG.m.b.H.AG.m.b.H.Gebr.AGebr.Hbf.AHbf.CHauptbahnhofHg.AHg.Hr.AHr.CHerrHrn.AHrn.CHerrnHrsg.AHrsg.I.AI.II.AII.III.AIII.IV.AIV.Inc.AInc.Ing.AIng.Jan.AJan.CJanuarJh.AJh.CJahrhundertJhd.AJhd.CJahrhundertJr.AJr.Jul.AJul.CJuliJun.AJun.CJuniK.O.AK.O.L'AL'L.A.AL.A.L’AL’M.A.AM.A.M.Sc.AM.Sc.Mi.AMi.CMittwochMio.AMio.CMillionMo.AMo.CMontagMr.AMr.Mrd.AMrd.CMilliardeMrz.AMrz.CMärzMwSt.AMwSt.CMehrwertsteuerMär.AMär.CMärzN.Y.AN.Y.N.Y.C.AN.Y.C.Nov.ANov.CNovemberNr.ANr.CNummerO.K.AO.K.O.OAO.OO.oAO.oO_OAO_OO_oAO_oOkt.AOkt.COktoberOrig.AOrig.COriginalP.S.AP.S.Pkt.APkt.CPunktProf.AProf.CProfessorR.I.P.AR.I.P.Red.ARed.CRedaktionS'AS'C'sSa.ASa.CSamstagSep.ASep.CSeptemberSept.ASept.CSeptemberSo.ASo.CSonntagSt.ASt.Std.AStd.CStundeStr.AStr.CStraßeS’AS’C'sTel.ATel.CTelefonTsd.ATsd.CTausendU.S.AU.S.U.S.A.AU.S.A.U.S.S.AU.S.S.Univ.AUniv.CUniversitätV.VAV.VV_VAV_VVol.AVol.XDAXDXDDAXDD[-:A[-:[:A[:[=A[=\")A\")\nA\n\tA\t]=A]=^_^A^_^^__^A^__^^___^A^___^``A``a.Aa.a.D.Aa.D.a.M.Aa.M.a.Z.Aa.Z.abzgl.Aabzgl.Cabzüglichadv.Aadv.al.Aal.allg.Aallg.Callgemeinauf'mAaufA'mCdemauf’mAaufA’mCdemb.Ab.betr.Abetr.biol.Abiol.bspw.Abspw.Cbeispielsweisebzgl.Abzgl.Cbezüglichbzw.Abzw.Cbeziehungsweisec.Ac.c/oAc/oca.Aca.co.Aco.d'Ad'd.Ad.d.h.Ad.h.dgl.Adgl.Cdergleichendu'sAduA'sCesdu’sAduA’sCesd’Ad’e.Ae.e.V.Ae.V.e.g.Ae.g.ebd.Aebd.Cebendaehem.Aehem.eigtl.Aeigtl.Ceigentlichengl.Aengl.Cenglischentspr.Aentspr.er'sAerA'sCeserm.Aerm.er’sAerA’sCesetc.Aetc.ev.Aev.evtl.Aevtl.Ceventuellf.Af.frz.Afrz.Cfranzösischg.Ag.geb.Ageb.gegr.Agegr.Cgegründetgem.Agem.ggf.Aggf.Cgegebenenfallsggfs.Aggfs.Cgegebenenfallsggü.Aggü.Cgegenüberh.Ah.h.c.Ah.c.hinter'mAhinterA'mCdemhinter’mAhinterA’mCdemhrsg.Ahrsg.i.Ai.i.A.Ai.A.i.G.Ai.G.i.O.Ai.O.i.Tr.Ai.Tr.i.V.Ai.V.i.d.R.Ai.d.R.i.e.Ai.e.ich'sAichA'sCesich’sAichA’sCesihr'sAihrA'sCesihr’sAihrA’sCesincl.Aincl.Cinklusiveinkl.Ainkl.Cinklusiveinsb.Ainsb.Cinsbesonderej.Aj.jr.Ajr.jun.Ajun.jur.Ajur.k.Ak.kath.Akath.Ckatholischl.Al.lat.Alat.lt.Alt.Clautm.Am.m.E.Am.E.m.M.Am.M.max.Amax.Cmaximalmin.Amin.Cminimalmind.Amind.Cmindestensmtl.Amtl.Cmonatlichn.An.n.Chr.An.Chr.nat.Anat.o.Ao.o.0Ao.0o.OAo.Oo.a.Ao.a.o.g.Ao.g.o.k.Ao.k.o.oAo.oo.ä.Ao.ä.o_0Ao_0o_OAo_Oo_oAo_oorig.Aorig.Coriginalp.Ap.p.a.Ap.a.p.s.Ap.s.pers.Apers.phil.Aphil.q.Aq.q.e.d.Aq.e.d.r.Ar.rer.Arer.röm.Aröm.Crömischs'As'C'ss.As.s.o.As.o.sen.Asen.sie'sAsieA'sCessie’sAsieA’sCessog.Asog.std.Astd.stellv.Astellv.s’As’C'st.At.tägl.Atägl.Ctäglichu.Au.u.U.Au.U.u.a.Au.a.u.s.w.Au.s.w.u.v.m.Au.v.m.unter'mAunterA'mCdemunter’mAunterA’mCdemusf.Ausf.usw.Ausw.uvm.Auvm.v.Av.v.Chr.Av.Chr.v.a.Av.a.v.l.n.r.Av.l.n.r.v.vAv.vv_vAv_vvgl.Avgl.Cvergleichevllt.Avllt.Cvielleichtvlt.Avlt.Cvielleichtvor'mAvorA'mCdemvor’mAvorA’mCdemvs.Avs.w.Aw.wir'sAwirA'sCeswir’sAwirA’sCeswiss.Awiss.x.Ax.xDAxDxDDAxDDy.Ay.z.Az.z.B.Az.B.z.Bsp.Az.Bsp.z.T.Az.T.z.Z.Az.Z.z.Zt.Az.Zt.z.b.Az.b.zzgl.Azzgl. A C ¯\(ツ)/¯A¯\(ツ)/¯°C.A°ACA.°F.A°AFA.°K.A°AKA.°c.A°AcA.°f.A°AfA.°k.A°AkA.ä.Aä.ö.Aö.österr.Aösterr.Cösterreichischü.Aü.über'mAüberA'mCdemüber’mAüberA’mCdemಠ_ಠAಠ_ಠಠ︵ಠAಠ︵ಠ—A—’A’’SA’SC's’nA’nCein’neA’neCeine’nemA’nemCeinem’nenA’nenCeinen’sA’sC's’’A’’faster_heuristics \ No newline at end of file diff --git a/project/backend/spacy-service/spacy_training/output/model-backup/vocab/key2row b/project/backend/spacy-service/spacy_training/output/model-backup/vocab/key2row new file mode 100644 index 0000000..5416677 --- /dev/null +++ b/project/backend/spacy-service/spacy_training/output/model-backup/vocab/key2row @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/project/backend/spacy-service/spacy_training/output/model-backup/vocab/lookups.bin b/project/backend/spacy-service/spacy_training/output/model-backup/vocab/lookups.bin new file mode 100644 index 0000000..5416677 --- /dev/null +++ b/project/backend/spacy-service/spacy_training/output/model-backup/vocab/lookups.bin @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/project/backend/spacy-service/spacy_training/output/model-backup/vocab/strings.json b/project/backend/spacy-service/spacy_training/output/model-backup/vocab/strings.json new file mode 100644 index 0000000..fe74a3c --- /dev/null +++ b/project/backend/spacy-service/spacy_training/output/model-backup/vocab/strings.json @@ -0,0 +1,3407 @@ +[ + "\t", + "\n", + " ", + " ", + "!", + "\"", + "$", + "%", + "&", + "'", + "''", + "'-(", + "'-)", + "'S", + "'X", + "'m", + "'n", + "'ne", + "'nem", + "'nen", + "'s", + "'x", + "'xx", + "'xxx", + "(", + "(((", + "(*>", + "(*_*)", + "(-8", + "(-:", + "(-;", + "(-_-)", + "(-d", + "(._.)", + "(:", + "(;", + "(=", + "(>_<)", + "(^_^)", + "(o:", + "(x:", + "(x_x)", + "(\u00ac_\u00ac)", + "(\u0ca0_\u0ca0)", + "(\u256f\u00b0\u25a1\u00b0\uff09\u256f\ufe35\u253b\u2501\u253b", + ")", + ")))", + ")-:", + ")/\u00af", + "):", + "*", + "+", + "+/D", + "+AU", + ",", + ",00", + ",03", + ",10", + ",12", + ",25", + ",40", + ",43", + ",50", + ",80", + ",91", + "-", + "-((", + "-))", + "-0", + "-3", + "-8", + "-D", + "-O", + "-P", + "-X", + "-_-", + "-__-", + "-d", + "-in", + "-o", + "-p", + "-x", + "-|", + ".", + ".00", + ".25", + ".5x", + ".7x", + ".80", + ".93", + ".A.", + ".B.", + ".C.", + ".D.", + ".E.", + ".G.", + ".H.", + ".K.", + ".M.", + ".O.", + ".P.", + ".R.", + ".S.", + ".Sc", + ".T.", + ".U.", + ".V.", + ".Y.", + ".Z.", + "._.", + ".a.", + ".b.", + ".c.", + ".d.", + ".e.", + ".g.", + ".h.", + ".k.", + ".m.", + ".o.", + ".r.", + ".s.", + ".w.", + ".\u00e4.", + "/", + "/080%/212%/491", + "/2,12", + "/3", + "/AuM", + "/Core+", + "/FK", + "/XX", + "/XxX", + "/Xxxx+", + "/aum", + "/core+", + "/d", + "/d,dd", + "/ddd%/ddd%/ddd", + "/fk", + "0", + "0%+", + "0,0", + "0,03", + "0,1", + "0,2", + "0,6", + "0,625", + "0,80", + "0.0", + "0.9", + "0.93", + "0.o", + "000", + "01", + "012", + "014", + "015", + "016", + "017", + "018", + "020", + "021", + "022", + "023", + "024", + "025", + "026", + "032", + "033", + "034", + "036", + "0_0", + "0_o", + "1", + "1,1", + "1,4", + "1,40", + "1,6", + "1.", + "1.000", + "1.1", + "1.127.916", + "1.2", + "1.25", + "1.5x", + "1.7x", + "1.80", + "10", + "10.9", + "100", + "12", + "12,0", + "13", + "13,0", + "14", + "15", + "150", + "16", + "16,0", + "17", + "18", + "18,0", + "186", + "19,0", + "19,00", + "19,7", + "2", + "2,0", + "2.", + "2.3", + "20", + "20,0", + "200", + "200.000", + "2000", + "2012", + "2014", + "2015", + "2016", + "2017", + "2018", + "2020", + "2021", + "2022", + "2023", + "2024", + "2025", + "2026", + "2032", + "2033", + "2034", + "21,4", + "21,43", + "21,6", + "23", + "24", + "24-month", + "25", + "25.000", + "250", + "26,4", + "262", + "28", + "284", + "3", + "3,0", + "3,3", + "3,8", + "3.", + "3.321", + "30", + "300", + "31.12.2023", + "31.12.2036", + "314", + "32", + "321", + "33", + "333", + "336", + "34", + "345", + "35", + "37.5", + "38", + "4", + "4,0", + "4,000", + "4,3", + "4,5", + "4,6", + "4,7", + "4,8", + "4,9", + "4,91", + "40", + "400", + "43", + "44", + "45", + "491", + "5", + "5%+", + "5,0", + "5,00", + "5,1", + "5,10", + "5,25", + "5,3", + "5,4", + "5,5", + "5,50", + "5,7", + "5.0", + "50", + "500", + "52", + "56", + "5Mio.\u20ac", + "5mio.\u20ac", + "6", + "6,0", + "6,4", + "6,5", + "6.00", + "6.5", + "60", + "625", + "65", + "67", + "7", + "7,1", + "7,2", + "7,5", + "7,5%+", + "7,50", + "7,50%+", + "7.5", + "75", + "8", + "8)", + "8,0", + "8,00", + "8,1", + "8,2", + "8,5", + "8-", + "8-)", + "8-D", + "8-d", + "80", + "800", + "84,0", + "85", + "8D", + "8d", + "9", + "9,0", + "9,00", + "9,7", + "9.8", + "916", + ":", + ":'(", + ":')", + ":'-(", + ":'-)", + ":(", + ":((", + ":(((", + ":()", + ":)", + ":))", + ":)))", + ":*", + ":-(", + ":-((", + ":-(((", + ":-)", + ":-))", + ":-)))", + ":-*", + ":-/", + ":-0", + ":-3", + ":->", + ":-D", + ":-O", + ":-P", + ":-X", + ":-]", + ":-d", + ":-o", + ":-p", + ":-x", + ":-|", + ":-}", + ":/", + ":0", + ":1", + ":3", + ":>", + ":D", + ":O", + ":P", + ":X", + ":]", + ":d", + ":o", + ":o)", + ":p", + ":x", + ":x)", + ":|", + ":}", + ":\u2019(", + ":\u2019)", + ":\u2019-(", + ":\u2019-)", + ";", + ";)", + ";-)", + ";-D", + ";-X", + ";-d", + ";D", + ";X", + ";_;", + ";d", + "<", + "<.<", + "", + "", + "=", + "=(", + "=)", + "=/", + "=3", + "=D", + "=X", + "=[", + "=]", + "=d", + "=|", + ">", + ">.<", + ">.>", + ">:(", + ">:o", + ">:x", + "><(((*>", + "?", + "@", + "@_@", + "A", + "A.", + "A.C.", + "A.D.", + "A.G.", + "ACCOR", + "ACH", + "AGB", + "AIF", + "AIN", + "ALT", + "ANY", + "AUSSCH\u00dcTTUNGSRENDITE", + "AUT", + "Ab", + "Abb", + "Abb.", + "Abbildung", + "Abdeckung", + "Abk", + "Abk.", + "Abk\u00fcrzung", + "Ablauf", + "Abs", + "Abs.", + "Abt", + "Abt.", + "Abteilung", + "Access", + "Add", + "Agreements", + "Aktive", + "Aktueller", + "AlF", + "Allgemeine", + "Allocation", + "Allokation", + "Allokationsprofil", + "Alternative", + "Amsterdam", + "Andere", + "Anfrage", + "Angestrebter", + "Ankauf", + "Ankaufs-", + "Ankaufsphase", + "Ankaufspreis+", + "Ankaufszeitpunkt", + "Ankaufszeitraum", + "Ankermieter", + "Anlageausschuss", + "Anlagebedingungen", + "Anlagegrenzen", + "Anlagehorizont", + "Anlagestrategie", + "Anlagestrategien", + "Anlagesusschuss", + "Anlagevehikels", + "Anleger", + "Annahmen", + "Ansprechpartners", + "Antagevehikels", + "Anteilseigner", + "Anzahl", + "Apr", + "Apr.", + "April", + "ArTt", + "Arat", + "Area", + "Art", + "Artikel", + "Asset", + "Assets", + "AuM", + "Aufbau", + "Auflage", + "Aufl\u00f6sung", + "Aufnahme", + "Auftakt", + "Aufwertung", + "Aug", + "Aug.", + "August", + "Auschittungsrendite", + "Auschu\u0308ttungsrendite", + "Ausschuttung", + "Ausschu\u0308ttung", + "Ausschu\u0308ttungsintervalle", + "Ausschu\u0308ttungsrandite", + "Ausschu\u0308ttungsrendite", + "Aussch\u00fcttungsintervalle", + "Aussch\u00fcttungsrandite", + "Aussch\u00fcttungsrendite", + "Aussch\u00fcttungsrendites", + "B", + "B.", + "B.A.", + "B.Sc", + "B.Sc.", + "BE", + "BEE", + "BELGIUM", + "BENELUX", + "Bahnhof", + "Band", + "Baumanagementgebahr", + "Bd", + "Bd.", + "Beispiel", + "Benefits", + "Benelux", + "Berlin", + "Bestandsentwicklung", + "Bestandsentwicklungen", + "Betr", + "Betr.", + "Betreff", + "Bev\u00f6lkerungsprognose", + "Bf", + "Bf.", + "Bhf", + "Bhf.", + "Bildungswesen", + "Biol", + "Biol.", + "Brussels", + "Bruttofondsverm\u00f6gens", + "Bruttoverkaufswert", + "Bsp", + "Bsp.", + "Business", + "C", + "C++", + "C.", + "CBD", + "CDU", + "CDU/CSU", + "CH", + "CLF", + "CLV", + "COR", + "CORE", + "CSU", + "CSp", + "Cash", + "Cash-Flow-Stabilit\u00e4t", + "Cash-flow", + "Chr", + "Chr.", + "Cie", + "Cie.", + "Cities", + "Class", + "Closed", + "Closings", + "Club", + "Co", + "Co.", + "CoC", + "Considering", + "Core", + "Core+", + "Core+/D", + "Core+/Value", + "Country", + "D", + "D+AU", + "D+AUT", + "D.", + "D.C.", + "DACH", + "DE", + "DOM", + "DY", + "Darlehen", + "Denmark", + "Deutsche", + "Deutsches", + "Deutschland", + "Deutschlands", + "Dez", + "Dez.", + "Dezember", + "Di", + "Di.", + "Die", + "Dienstag", + "Dienstleistungen", + "Different", + "Dipl", + "Dipl.", + "Dipl.-Ing", + "Dipl.-Ing.", + "Dis", + "Do", + "Do.", + "Donnerstag", + "Dr", + "Dr.", + "Drawbacks", + "Durchschnitt", + "Durchschnittlich", + "D\u00e4nemark", + "E", + "E-Mail", + "E.", + "EAN", + "ECLF", + "EM", + "ERD", + "ESFCG", + "ESG-", + "ESG-Klassifizierung", + "EU-Offenlegungsverordnung", + "EUR", + "EUROPEAN", + "EWE", + "Eigenkapital", + "Einmalige", + "Einw", + "Einwohner", + "Einzelinvestment", + "Einzugsgebiet", + "Emerging", + "Entsch\u00e4digung", + "Erbbaurechte", + "Erwartete", + "Estate", + "Euro", + "Europ", + "Europa", + "Europe", + "European", + "Eurozone", + "Evergreen", + "Exit", + "Exit-NOI", + "Exitrendite", + "Expected", + "Experience", + "Expertise", + "F", + "F.", + "FDR", + "FR", + "FRANCE", + "FUND", + "Fa", + "Fa.", + "Faktor", + "Fam", + "Fam.", + "Familie", + "Feb", + "Feb.", + "Februar", + "Fee", + "Finanzierung", + "Finanzierungskonditionen", + "Finland", + "Finnland", + "Firma", + "First", + "Fl\u00e4che", + "Focus", + "Fokus", + "Folie", + "Fond", + "Fonds", + "Fondsebene", + "Fondsstrukturenv", + "Fondstyp", + "Fondsvolumen", + "Forward-Deals", + "Fr", + "Fr.", + "France", + "Frankreich", + "Frau", + "Fremdkapital", + "Fremdkapitalanteil", + "French", + "Frl", + "Frl.", + "Fr\u00e4ulein", + "Fund", + "Fu\u0308hrende", + "Fu\u0308hrender", + "G", + "G.", + "G.m.b", + "G.m.b.H.", + "GAL", + "GEDis", + "GERD", + "GERMANY", + "GRRE", + "Gateway", + "Geared", + "Gebr", + "Gebr.", + "Gebu\u0308hren", + "Gebu\u0308hrenstruktur", + "Geb\u00fchren", + "Geografische", + "Geographic", + "Geographischer", + "Geplante", + "Geplantes", + "German", + "Germany", + "Gesamtrendite", + "GmbH", + "Gross", + "Gro\u00dfst\u00e4dte", + "H", + "H.", + "HHGK", + "Haltedauer", + "Halten", + "Halten-Strategie", + "Hamburg", + "Handel", + "Hauptbahnhof", + "Hauptstadtregionen", + "Hbf", + "Hbf.", + "Heimfall", + "Heirs", + "Helsinki", + "Henderson", + "Herr", + "Herrn", + "Hg", + "Hg.", + "Hotel", + "Hotels", + "Hr", + "Hr.", + "Hrn", + "Hrn.", + "Hrsg", + "Hrsg.", + "Hurdle", + "I", + "I.", + "ICF", + "ICS", + "IDE", + "II", + "II.", + "III", + "III.", + "INK", + "INREV", + "IRR", + "IRR6.5", + "IT", + "IUM", + "IV", + "IV.", + "Iberia", + "Im", + "Immobilien", + "Immobilien-", + "Immobilien-Investmentmanager", + "Immobilien-Spezial-AlF", + "Immobilien-Spezialfonds", + "Immobilienwerte", + "Inc", + "Inc.", + "Individualmandat", + "Industrial", + "Informationen", + "Infrastrukturquote", + "Ing", + "Ing.", + "Initial", + "Institutional", + "IntReal", + "Interner", + "Invastitionsfokus", + "Investftionsvolumen", + "Investing", + "Investitionen", + "Investitions-annahmen", + "Investitionsphase", + "Investment", + "Investmentmanagers", + "Investmentphase", + "Investmentzeitraum", + "Investoren", + "Investtionszeltraum", + "Investtionszeltraum,10", + "Investtonszeltraum", + "Ireland", + "Irland", + "It", + "Italien", + "Italy", + "J", + "Ja", + "Jahr", + "Jahre", + "Jahren", + "Jahrhundert", + "Jan", + "Jan.", + "Januar", + "Jh", + "Jh.", + "Jhd", + "Jhd.", + "Jr", + "Jr.", + "Jul", + "Jul.", + "Juli", + "Jun", + "Jun.", + "Juni", + "K", + "K.", + "K.O.", + "KAGB", + "KENNZAHL", + "KINGDOM", + "KVG", + "Kapitalstruktur", + "Kapitalzusagen", + "Kaufen", + "Kaufpreis", + "Keine", + "Kernvolkswirtschaften", + "Key", + "Kindertagesst\u00e4tte", + "Klassifikation", + "Klassifizierung", + "Kontinentaleuropaische", + "Kosten", + "K\u00f6nigreich", + "L", + "L'", + "L.A.", + "LAUFZEIT", + "LAUFZEIT2", + "LOGISTICS", + "LPs", + "LT", + "LTO", + "LTV", + "LTV-Ziel", + "LTY", + "LU", + "LUX", + "Laborimmobilien", + "Lagefokussierung", + "Langfristiges", + "Laufzeit", + "Laufzelt", + "Leerstand", + "Levallois", + "Lidl", + "Light", + "Limited", + "Lisbon", + "Loan-to-Value", + "Local", + "Logistics", + "Logistik", + "Logistikimmobilien", + "London", + "Lux-RAIF", + "Lux-based", + "Luxembourg", + "L\u00c4NDERALLOKATION", + "L\u00e4nder", + "L\u00e4nderallokation", + "L\u00e4ndern", + "L\u2019", + "M", + "M.", + "M.A.", + "M.Sc", + "M.Sc.", + "MANAGMENTGEB\u00dcHREN", + "MGallery", + "Madrid", + "Manage", + "Management", + "Manager", + "Manager-defined", + "Marktu\u0308blich", + "Max", + "Maxhu\u0308tte-Haidhof", + "Maximaler", + "Medizin", + "Mehrwertsteuer", + "Metropolregianen", + "Metropolregionen", + "Mi", + "Mi.", + "Mietanteil", + "Miete", + "Milliarde", + "Million", + "Min-commitmentper", + "Mindestanlage", + "Mindestens", + "Mindestzeichnung", + "Mio", + "Mio.", + "Mitglied", + "Mitgliedschaft", + "Mittwoch", + "Mo", + "Mo.", + "Monate", + "Montag", + "Mr", + "Mr.", + "Mrd", + "Mrd.", + "Mrz", + "Mrz.", + "MwSt", + "MwSt.", + "M\u00e4r", + "M\u00e4r.", + "M\u00e4rz", + "M\u00f6glich", + "N", + "N.Y.", + "N.Y.C.", + "NAV", + "NCE", + "NDS", + "NETHERLANDS", + "NL", + "NOI", + "NORDICS", + "NORWAY", + "Nachvermietungsstrategie", + "Name", + "Navigate", + "Netherlands", + "Niederlande", + "Nordic", + "Nordics", + "Norway", + "Norwegen", + "Nov", + "Nov.", + "November", + "Nr", + "Nr.", + "Nummer", + "Nuremberg", + "O", + "O.", + "O.K.", + "O.O", + "O.o", + "OPCI", + "ORE", + "O_O", + "O_o", + "Objective", + "Objekt", + "Objekt-", + "Objektbaujahre", + "Objekte", + "Objektebene", + "Objekten", + "Objekterwerb", + "Objektpipeline", + "Objektportfolios", + "Of", + "Offen", + "Offener", + "Offenlegungsverordnung", + "Office", + "Offices", + "Okt", + "Okt.", + "Oktober", + "OpCo", + "Open-end", + "Open-ended", + "Orig", + "Orig.", + "Original", + "Other", + "Our", + "P", + "P-Logistik", + "P.S.", + "PCI", + "PORTUGAL", + "Parformanceabh\u00e4ngige", + "Paris", + "Parks", + "Partnership", + "Performance-Fee", + "Performanceziel", + "Pkt", + "Pkt.", + "Plus", + "Poland", + "Portfolio", + "Portugal", + "Potential", + "Premium", + "Prime", + "Process", + "Prof", + "Prof.", + "Professor", + "Prognose", + "Prognostiderte", + "Prognostizierte", + "Projektentwicklungen", + "Projektentwicklungsrisiken", + "PropCo", + "Pt", + "Punkt", + "Q", + "Qin", + "Quota", + "Quote", + "R", + "R.", + "R.I.P.", + "RE", + "RENDITE", + "REV", + "REWE", + "RISIKOPROFIL", + "ROOT", + "RRE", + "Rabatt", + "Rate", + "Real", + "Rechtsform", + "Red", + "Red.", + "Redaktion", + "Region", + "Regionen", + "Rendite-", + "Rendite-Risiko-Profil", + "Renovierungen", + "Rents", + "Residential", + "Retail", + "Retailinvestitionsvolumen", + "Return", + "Rewe", + "Risiko-Rendite-Bandbreite", + "Risikoprofil", + "Risk", + "Rotterdam", + "S", + "S'", + "SCS", + "SCSp", + "SEKTORENALLOKATION", + "SFDR", + "SG-", + "SICAV-RAIF", + "SP", + "SPAIN", + "SRI", + "Sa", + "Sa.", + "Sale", + "Samstag", + "Sc.", + "Schule", + "Schweden", + "Sector", + "Sektor", + "Sektoraler", + "Sep", + "Sep.", + "Sept", + "Sept.", + "September", + "Since", + "Sitz", + "Size", + "Skandinavien", + "So", + "So.", + "Solvency", + "Sonntag", + "Spain", + "Spanien", + "Spezial-AIF", + "Spezial-AlF", + "Spezial-Sonderverm\u00f6gen", + "St", + "St.", + "Stabilisierung", + "Stabilisierungs-", + "Standort", + "Standortaufwertungsstrategie", + "Standorte", + "Status", + "Std", + "Std.", + "Steuern", + "Stil", + "Str", + "Str.", + "Strategie", + "Strategien", + "Stra\u00dfe", + "Strong", + "Structure", + "Struktur", + "Strukturierungsgebu\u0308hr", + "Strukturierungsgeb\u00fchr", + "Stunde", + "St\u00e4dten", + "Sweden", + "S\u2019", + "T", + "T.", + "TED", + "TEST", + "TEST3", + "TEST323", + "TEST33", + "TEST34", + "TEST345", + "TEST35", + "TEST36", + "TEST37", + "TEST4", + "TEST44", + "TEST45", + "TEST5", + "TEST65", + "TEST67", + "TEST88", + "TEST99", + "Tag", + "Target", + "Target-IRR", + "Targeting", + "Targets", + "Targetvehiclesize", + "Tausend", + "Teflimmobilfe)-", + "Tel", + "Tel.", + "Telefon", + "Telefonnummer", + "Tenant", + "Term", + "The", + "There", + "To", + "Tr", + "Tr.", + "Tsd", + "Tsd.", + "U", + "U.", + "U.S.", + "U.S.A.", + "U.S.S.", + "UK", + "UND", + "UNITED", + "USt", + "Univ", + "Univ.", + "Universit\u00e4t", + "Unternehmensimmobilien", + "V", + "V.", + "V.V", + "V_V", + "Value", + "Value-Add", + "Value-add", + "Vehicle", + "Vehikelstruktur", + "Verbesserungen", + "Verbund", + "Vereinigtes", + "Vergu\u0308tung", + "Verg\u00fctung", + "Verkaufs", + "Verkaufs-", + "Verkehrswertes", + "Verl\u00e4ngerungsoption", + "Vermietbare", + "Vol", + "Vol.", + "Vorlauf", + "W", + "WALT", + "WAY", + "WORLDWIDE", + "Wertstabile", + "Wholesale", + "Why", + "Wohngemeinschaften", + "Wohnimmobilien", + "X'", + "X++", + "X+XX", + "X+XXX", + "X-Xxxx", + "X-Xxxxx", + "X.", + "X.X", + "X.X.", + "X.X.X.", + "X.Xx", + "X.Xx.", + "X.x", + "X.x.x", + "X.x.x.X.", + "XD", + "XDD", + "XX", + "XX-Xxxxx", + "XX.", + "XXX", + "XXX-", + "XXX-Xxxx", + "XXX-Xxxxx", + "XXX.", + "XXX/XXX", + "XXXX", + "XXXX-XXXX", + "XXXd.d", + "XXXx", + "XXXxx", + "XXx", + "XXxxxx", + "X_X", + "X_x", + "Xx", + "Xx.", + "XxX", + "XxXx", + "XxXx.", + "Xxx", + "Xxx-XXXX", + "Xxx-xxxx", + "Xxx.", + "XxxX", + "XxxXxxx", + "Xxxx", + "Xxxx+", + "Xxxx+/X", + "Xxxx+/Xxxxx", + "Xxxx-", + "Xxxx-XXX", + "Xxxx-Xxxx-Xxxxx", + "Xxxx-Xxxxx-XXX", + "Xxxx-xx-Xxxxx", + "Xxxx-xxx", + "Xxxx-xxxx", + "Xxxx.", + "Xxxx.-Xxx", + "Xxxx.-Xxx.", + "XxxxXx", + "Xxxxx", + "Xxxxx)-", + "Xxxxx)/Xxxx", + "Xxxxx+", + "Xxxxx,dd", + "Xxxxx-", + "Xxxxx-XXX", + "Xxxxx-XxX", + "Xxxxx-Xxx", + "Xxxxx-Xxxxx", + "Xxxxx-Xxxxx-XxX", + "Xxxxx-Xxxxx-Xxxxx", + "Xxxxx-xxx", + "Xxxxx-xxxx", + "Xxxxx\u0308xx", + "Xxxxx\u0308xxx-Xxxxx", + "Xxxxx\u0308xxxx", + "Xxxx\u0308xxxx", + "Xx\u0308xxxx", + "X\u2019", + "Y", + "Year", + "YoY", + "Z", + "Z.", + "ZIELAUSSCH\u00dcTTUNG", + "ZIELRENDITE", + "ZZGER 33", + "Zeichnungen", + "Ziel-LTY", + "Ziel-Netto-IRR", + "Zielallokation", + "Zielanlagestrategie", + "Zielausschu\u0308ttung", + "Zielmarkts", + "Zielm\u00e4rkte", + "Zielobjekte", + "Zielobjektgr\u00f6\u00dfe", + "Zielregionfen)/Jand", + "Zielrendite", + "Zielrenditen", + "Zielsektoren", + "Zielvolumen", + "Ziirraiaein", + "Zins", + "Zins-", + "Zinsfu\u00df", + "Zinss\u00e4tze", + "Zt", + "Zt.", + "[", + "[-:", + "[:", + "[=", + "\\", + "\\\")", + "\\n", + "\\t", + "\\x", + "]", + "]=", + "^", + "^_^", + "^__^", + "^___^", + "_*)", + "_-)", + "_.)", + "_<)", + "_^)", + "__-", + "__^", + "_\u00ac)", + "_\u0ca0)", + "`", + "``", + "a", + "a.", + "a.D.", + "a.M.", + "a.Z.", + "a.c.", + "a.d.", + "a.g.", + "a.m.", + "a.z.", + "a34", + "ab", + "abb", + "abb.", + "abdeckung", + "abk", + "abk.", + "ablauf", + "abs", + "abs.", + "abt", + "abt.", + "abzgl", + "abzgl.", + "abz\u00fcglich", + "access", + "accor", + "ace", + "ach", + "ack", + "acquire", + "across", + "act", + "active", + "add", + "adsada34", + "adv", + "adv.", + "advantage", + "ae", + "aft", + "age", + "agreements", + "aha", + "ahe", + "ahl", + "ahr", + "ail", + "aiming", + "ain", + "ake", + "akjd", + "akjsdd", + "akt", + "aktive", + "aktueller", + "al", + "al.", + "ald", + "ale", + "all", + "allg", + "allg.", + "allgemein", + "allgemeine", + "allocation", + "allokation", + "allokationsprofil", + "als", + "also", + "alternative", + "aly", + "am.", + "ambulant", + "ame", + "amsterdam", + "an", + "an.", + "anchored", + "and", + "andere", + "anfrage", + "angemessene", + "angestrebt", + "angestrebter", + "ankauf", + "ankaufs-", + "ankaufsphase", + "ankaufspreis+", + "ankaufszeitpunkt", + "ankaufszeitraum", + "ankermieter", + "anlageausschuss", + "anlagebedingungen", + "anlagegrenzen", + "anlagehorizont", + "anlagestrategie", + "anlagestrategien", + "anlagesusschuss", + "anlagevehikels", + "anleger", + "ann", + "annahmen", + "annual", + "annum", + "ans", + "ansprechpartners", + "ant", + "antagevehikels", + "anteilseigner", + "any", + "anzahl", + "appealing", + "apr", + "apr.", + "arat", + "are", + "area", + "ark", + "ars", + "art", + "artikel", + "artt", + "ary", + "as", + "asd", + "asd34", + "asdasd", + "asdasd34", + "asdasda34", + "asddsf34", + "asdsdkaj", + "ase", + "ash", + "ass", + "asset", + "assetor", + "assets", + "ast", + "at", + "at.", + "ate", + "ath", + "att", + "attractive", + "auch", + "auf", + "aufbau", + "auflage", + "aufl\u00f6sung", + "aufnahme", + "auftakt", + "aufwertung", + "auf\u2019m", + "aug", + "aug.", + "aum", + "aus", + "auschittungsrendite", + "auschu\u0308ttungsrendite", + "ausgew\u00e4hlte", + "ausschlie\u00dflich", + "ausschuttung", + "ausschu\u0308ttung", + "ausschu\u0308ttungsintervalle", + "ausschu\u0308ttungsrandite", + "ausschu\u0308ttungsrendite", + "aussch\u00fcttungsintervalle", + "aussch\u00fcttungsrandite", + "aussch\u00fcttungsrendite", + "aussch\u00fcttungsrendites", + "ave", + "ax.", + "b", + "b.", + "b.a.", + "b.sc", + "b.sc.", + "b34", + "bahnhof", + "bal", + "balanced", + "basis", + "bau", + "baumanagementgebahr", + "bb.", + "bd", + "bd.", + "be", + "bee", + "bei", + "beim", + "beispielsweise", + "belgium", + "benefits", + "benelux", + "ber", + "berechnet", + "berlin", + "bestandsentwicklung", + "bestandsentwicklungen", + "betr", + "betr.", + "betreute", + "betr\u00e4gt", + "bev\u00f6lkerungsprognose", + "beziehungsweise", + "bez\u00fcglich", + "bf", + "bf.", + "bhf", + "bhf.", + "bildungswesen", + "billion", + "biol", + "biol.", + "bis", + "bk.", + "bon", + "borrowing", + "both", + "bps", + "br.", + "brands", + "broad", + "brussels", + "bruttofondsverm\u00f6gens", + "bruttoverkaufswert", + "bs.", + "bsp", + "bsp.", + "bspw", + "bspw.", + "bt.", + "build", + "buildings", + "bundesweit", + "business", + "but", + "buyers", + "bzgl", + "bzgl.", + "bzw", + "bzw.", + "c", + "c++", + "c.", + "c/o", + "ca", + "ca.", + "cal", + "can", + "capability", + "capital", + "capped", + "carbon", + "cash", + "cash-flow", + "cash-flow-stabilit\u00e4t", + "cbd", + "cdu", + "cdu/csu", + "ce>", + "ced", + "ces", + "cey", + "ch", + "characteristic", + "che", + "chr", + "chr.", + "cht", + "cie", + "cie.", + "cities", + "city", + "cks", + "cl.", + "class", + "cle", + "closed", + "closing", + "closings", + "club", + "clv", + "co", + "co.", + "coc", + "collective", + "combines", + "commercial", + "commitment", + "common", + "competition", + "considered", + "considering", + "construction", + "contract", + "contracts", + "core", + "core+", + "core+/d", + "core+/value", + "core-plus", + "could", + "country", + "creation", + "csu", + "cts", + "currency", + "current", + "cus", + "d", + "d'", + "d)", + "d+au", + "d+aut", + "d,d", + "d,d%+", + "d,dd", + "d,dd%+", + "d,ddd", + "d-", + "d-)", + "d-X", + "d.", + "d.c.", + "d.d", + "d.dd", + "d.ddd", + "d.ddd.ddd", + "d.dx", + "d.h", + "d.h.", + "d.x", + "d21", + "d23", + "d34", + "dX", + "dXxx.\u20ac", + "d_d", + "d_x", + "dach", + "dam", + "darge", + "darlehen", + "das", + "dat", + "dd", + "dd,d", + "dd,dd", + "dd-xxxx", + "dd.d", + "dd.dd.dddd", + "dd.ddd", + "ddd", + "ddd.ddd", + "dddd", + "de", + "deal", + "ded", + "deep", + "defined", + "del", + "delivering", + "dem", + "demonstrated", + "den", + "denmark", + "der", + "dergleichen", + "des", + "destinations", + "deutsche", + "deutsches", + "deutschland", + "deutschlands", + "development", + "dez", + "dez.", + "dezember", + "dfb", + "dfdvg", + "dfg", + "dfs", + "dgl", + "dgl.", + "dgregerg45", + "di", + "di.", + "dic", + "die", + "dienstleistungen", + "different", + "dipl", + "dipl.", + "dipl.-ing", + "dipl.-ing.", + "discretionary", + "distributions", + "diversification", + "diversified", + "diversity", + "divested", + "dividend", + "dle", + "do", + "do.", + "domicile", + "domiciled", + "don", + "down", + "dr", + "dr.", + "drawbacks", + "drf", + "driven", + "dte", + "du", + "dual", + "durchschnitt", + "durchschnittlich", + "du\u2019s", + "dv.", + "dvg", + "dy", + "d\u00e4nemark", + "d\u2019", + "e", + "e)-", + "e-mail", + "e.", + "e.V.", + "e.d", + "e.g", + "e.g.", + "e.v.", + "eal", + "ean", + "ear", + "eat", + "eb.", + "ebd", + "ebd.", + "ebenda", + "ebr", + "ebt", + "eclf", + "economic", + "ed.", + "een", + "eep", + "ees", + "efn", + "efw", + "egr", + "egt", + "egy", + "ehe", + "ehem", + "ehem.", + "eigenkapital", + "eigentlich", + "eigtl", + "eigtl.", + "eil", + "eim", + "ein", + "eine", + "einem", + "einen", + "einer", + "eines", + "eingezahlte", + "einmalige", + "eins", + "einw", + "einwohner", + "einzelinvestment", + "einzeln", + "einzugsgebiet", + "eir", + "eis", + "eit", + "ekt", + "el.", + "eld", + "eln", + "els", + "elt", + "ely", + "em", + "em.", + "emerging", + "en-", + "en.", + "end", + "ended", + "ene", + "engl", + "engl.", + "englisch", + "enhance", + "enhancing", + "enn", + "ens", + "ent", + "entscheidet", + "entsch\u00e4digung", + "entspr", + "entspr.", + "env", + "eons", + "ep.", + "ept", + "equity", + "er", + "er.", + "erb", + "erbbaurechte", + "ere", + "erfolgten", + "erg", + "erm", + "erm.", + "ern", + "err", + "ers", + "ersten", + "ert", + "erwartete", + "ery", + "er\u2019s", + "es", + "esg-", + "esg-klassifizierung", + "ess", + "est", + "estate", + "etc", + "etc.", + "ete", + "etr", + "ets", + "eturn", + "eu-offenlegungsverordnung", + "eur", + "euro", + "europ", + "europa", + "europe", + "european", + "eurozone", + "ev", + "ev.", + "eventuell", + "evergreen", + "evtl", + "evtl.", + "ewe", + "ewfewfw45", + "excluding", + "exit", + "exit-noi", + "exitrendite", + "expected", + "experience", + "experienced", + "expertise", + "exposure", + "extensive", + "externe", + "extract", + "ez.", + "e\u2019s", + "f", + "f.", + "f34", + "fa", + "fa.", + "faktor", + "fam", + "fam.", + "favour", + "fdf", + "feb", + "feb.", + "fee", + "fees", + "fen", + "festen", + "festgelegt", + "festgelegter", + "fewfw", + "ff", + "fff", + "fhn", + "fierce", + "fil", + "financially", + "finanzierung", + "finanzierungskonditionen", + "finland", + "finnland", + "first", + "flagship", + "flow", + "flow-oriented", + "fl\u00e4che", + "focus", + "focused", + "focuses", + "fokus", + "folie", + "fond", + "fonds", + "fondsebene", + "fondsstrukturenv", + "fondstyp", + "fondsvolumen", + "for", + "form", + "forward-deals", + "fr", + "fr.", + "france", + "frankreich", + "franz\u00f6sisch", + "fremdkapital", + "fremdkapitalanteil", + "french", + "frl", + "frl.", + "frz", + "frz.", + "fs-", + "fs.", + "fsd", + "fund", + "funds", + "fu\u00df", + "fu\u0308hrende", + "fu\u0308hrender", + "fu\u0308r", + "fwf", + "fwkefn", + "f\u00fcr", + "f\u2019m", + "g", + "g.", + "g.m.b", + "g.m.b.h.", + "g45", + "gagshh", + "gal", + "gateway", + "geared", + "geb", + "geb.", + "gebr", + "gebr.", + "gebu\u0308hren", + "gebu\u0308hrenstruktur", + "geb\u00fchren", + "ged", + "gedis", + "gegebenenfalls", + "gegen\u00fcber", + "gegr", + "gegr.", + "gegr\u00fcndet", + "gem", + "gem.", + "gem\u00e4\u00df", + "gen", + "genuine", + "geografische", + "geographic", + "geographies", + "geographischer", + "geplante", + "geplantes", + "gepr\u00fcft", + "ger", + "gerd", + "german", + "germany", + "ges", + "gesamtrendite", + "gestellt", + "get", + "gf.", + "gfs", + "ggf", + "ggf.", + "ggfs", + "ggfs.", + "gg\u00fc", + "gg\u00fc.", + "ghashgd", + "ght", + "gic", + "gie", + "gl.", + "global", + "globale", + "gmbh", + "goal", + "good", + "gr.", + "great", + "green", + "grocery", + "gross", + "gro\u00dfst\u00e4dte", + "grre", + "gs-", + "gtl", + "guarantee", + "gzu", + "g\u00fc.", + "h", + "h.", + "h.c", + "h.c.", + "haltedauer", + "halten", + "halten-strategie", + "hamburg", + "handel", + "has", + "hat", + "hauptstadtregionen", + "have", + "hbf", + "hbf.", + "hd.", + "hed", + "hedging", + "heimfall", + "heirs", + "helsinki", + "hem", + "hen", + "henderson", + "her", + "here", + "hes", + "hf.", + "hg", + "hg.", + "hgd", + "hgfff", + "hgghhwgb34", + "hgjefn", + "hic", + "hiewjk", + "high", + "high-quality", + "hih", + "hil", + "hinter", + "hinter\u2019m", + "hip", + "his", + "hjfbjbf", + "hjk45", + "hme", + "hof", + "hotel", + "hotels", + "hr", + "hr.", + "hre", + "hrn", + "hrn.", + "hrsg", + "hrsg.", + "hte", + "hts", + "hurdle", + "h\u2019s", + "i", + "i.", + "i.A.", + "i.G.", + "i.O.", + "i.Tr.", + "i.V.", + "i.a.", + "i.d", + "i.d.R.", + "i.d.r.", + "i.e", + "i.e.", + "i.g.", + "i.o.", + "i.tr.", + "i.v.", + "ial", + "iberia", + "ice", + "icf", + "ich", + "ich\u2019s", + "ics", + "ide", + "idk", + "idl", + "ie.", + "ied", + "iel", + "ien", + "ies", + "iet", + "ife", + "ig.", + "ige", + "igh", + "ihr", + "ihr\u2019s", + "ii", + "ii.", + "iii", + "iii.", + "ijaefhn", + "il.", + "ild", + "ile", + "illustration", + "im", + "ime", + "immobilien", + "immobilien-", + "immobilien-investmentmanager", + "immobilien-spezial-alf", + "immobilien-spezialfonds", + "immobilienwerte", + "improve", + "improvement", + "in", + "in.", + "inc", + "inc.", + "inception", + "incl", + "incl.", + "including", + "income", + "income-generating", + "increasing", + "ind", + "individual", + "individualmandat", + "industrial", + "ine", + "informationen", + "infrastrukturquote", + "ing", + "ing.", + "initial", + "initiatives", + "ink", + "inkl", + "inkl.", + "inklusive", + "inrev", + "ins", + "insb", + "insb.", + "insbesondere", + "institutional", + "institutionelle", + "interesting", + "internal", + "interner", + "intreal", + "invastitionsfokus", + "invest", + "investftionsvolumen", + "investiert", + "investierte", + "investing", + "investitionen", + "investitions-annahmen", + "investitionsphase", + "investment", + "investmentmanagers", + "investmentphase", + "investments", + "investmentzeitraum", + "investor", + "investoren", + "investors", + "investtionszeltraum", + "investtionszeltraum,10", + "investtonszeltraum", + "inw", + "io.", + "iod", + "iol", + "ion", + "ios", + "ipl", + "ips", + "ird", + "ire", + "ireland", + "irland", + "irr", + "irr6.5", + "irs", + "is", + "is+", + "ise", + "isk", + "iss", + "ist", + "it", + "italien", + "italy", + "ite", + "ith", + "its", + "itt", + "ity", + "itz", + "ium", + "iv", + "iv.", + "ive", + "ize", + "j", + "j.", + "ja", + "jahr", + "jahre", + "jahren", + "jak", + "jan", + "jan.", + "jbf", + "je", + "jedes", + "jeweiliges", + "jh", + "jh.", + "jhasdb", + "jhd", + "jhd.", + "jiandw", + "jor", + "jr", + "jr.", + "jsvjoso", + "jul", + "jul.", + "jun", + "jun.", + "jur", + "jur.", + "juuqw", + "jwaidk", + "j\u00e4hrlich", + "j\u00e4hrliche", + "k", + "k.", + "k.o.", + "k45", + "kagb", + "kaj", + "kann", + "kapitalstruktur", + "kapitalzusagen", + "kath", + "kath.", + "katholisch", + "kaufen", + "kaufpreis", + "keine", + "kel", + "ken", + "kernvolkswirtschaften", + "ket", + "key", + "kindertagesst\u00e4tte", + "kingdom", + "kjd", + "kjjand", + "kl.", + "klassifikation", + "klassifizierung", + "kontinentaleuropaische", + "kosten", + "kt-", + "kt.", + "kte", + "kts", + "kus", + "kvg", + "k\u00f6nigreich", + "l", + "l'", + "l.", + "l.a.", + "laborimmobilien", + "lagefokussierung", + "langfristig", + "langfristiges", + "largest", + "lat", + "lat.", + "laufzeit", + "laufzelt", + "laut", + "le.g", + "leases", + "least", + "leave", + "led", + "leerstand", + "ler", + "less", + "levallois", + "level", + "leverage", + "leveraged", + "leveraging", + "lg.", + "lic", + "lidl", + "lie", + "life", + "lifetime", + "light", + "limited", + "lin", + "lio", + "liquid", + "liquidity", + "lisbon", + "listed", + "lit", + "ll", + "lle", + "llg", + "lls", + "llt", + "llv", + "lly", + "loan-to-value", + "local", + "locations", + "lock-in", + "logistics", + "logistik", + "logistikimmobilien", + "london", + "long-term", + "low", + "lps", + "lso", + "lt", + "lt.", + "lte", + "lto", + "ltv", + "ltv-ziel", + "lu", + "lub", + "lue", + "lus", + "lux", + "lux-based", + "lux-raif", + "luxembourg", + "lv.", + "l\u00e4nder", + "l\u00e4nderallokation", + "l\u00e4ndern", + "l\u2019", + "m", + "m.", + "m.E.", + "m.M.", + "m.a.", + "m.b", + "m.e.", + "m.m.", + "m.sc", + "m.sc.", + "madrid", + "main", + "major", + "make", + "mal", + "man", + "manage", + "management", + "manager", + "manager-defined", + "mandate", + "mandates", + "market", + "markets", + "marktu\u0308blich", + "max", + "max.", + "maxhu\u0308tte-haidhof", + "maximal", + "maximaler", + "mbH", + "means", + "medizin", + "medizinnahe", + "men", + "mer", + "metropolregianen", + "metropolregionen", + "mgallery", + "mi", + "mi.", + "mic", + "mietanteil", + "miete", + "million", + "min", + "min-commitmentper", + "min.", + "mind", + "mind.", + "mindestanlage", + "mindestens", + "mindestzeichnung", + "minimal", + "minor", + "mio", + "mio.", + "mit", + "mitglied", + "mitgliedschaft", + "mo", + "mo.", + "mon", + "monate", + "monatlich", + "months", + "mr", + "mr.", + "mrd", + "mrd.", + "mrz", + "mrz.", + "mtl", + "mtl.", + "multiple", + "must", + "mwst", + "mwst.", + "m\u00e4r", + "m\u00e4r.", + "m\u00e4\u00df", + "m\u00f6glich", + "n", + "n.", + "n.Chr.", + "n.chr.", + "n.r", + "n.y.", + "n.y.c.", + "nach", + "nachhaltig", + "nachvermietungsstrategie", + "nal", + "name", + "nat", + "nat.", + "nav", + "navigate", + "nc.", + "nce", + "nch", + "ncl", + "ncy", + "nd.", + "nde", + "nds", + "ndw", + "ne", + "necessity", + "ned", + "nem", + "nen", + "ner", + "nes", + "net", + "netherlands", + "netto", + "neu", + "new", + "ng.", + "nge", + "ngl", + "ngs", + "niederlande", + "niv", + "nki", + "nkl", + "nkt", + "nl", + "no", + "noi", + "non-discretionary", + "nor", + "nordic", + "nordics", + "norway", + "norwegen", + "nov", + "nov.", + "nr", + "nr.", + "ns-", + "nsb", + "nse", + "nte", + "nth", + "nts", + "nuremberg", + "o", + "o.", + "o.0", + "o.O", + "o.a", + "o.a.", + "o.g", + "o.g.", + "o.k", + "o.k.", + "o.o", + "o.\u00e4", + "o.\u00e4.", + "o.\u20ac", + "o_0", + "o_O", + "o_o", + "oad", + "oal", + "objective", + "objectives", + "objekt", + "objekt-", + "objektbaujahre", + "objekte", + "objektebene", + "objekten", + "objekterwerb", + "objektpipeline", + "objektportfolios", + "oder", + "of", + "of.", + "ofQin", + "offen", + "offene", + "offener", + "offenlegungsverordnung", + "offers", + "office", + "offices", + "ofinvestors", + "ofqin", + "og.", + "ois", + "okt", + "okt.", + "ol.", + "oll", + "ome", + "on", + "ond", + "one", + "ong", + "ons", + "ont", + "ood", + "oom", + "opa", + "opci", + "opco", + "ope", + "open", + "open-end", + "open-ended", + "operators", + "opportunities", + "or", + "ord", + "order", + "ore", + "orig", + "orig.", + "original", + "orm", + "ors", + "ort", + "ose", + "oso", + "oss", + "ota", + "ote", + "oth", + "other", + "our", + "out", + "outside", + "ov.", + "ove", + "over", + "own", + "p", + "p-logistik", + "p.", + "p.a", + "p.a.", + "p.s", + "p.s.", + "pCo", + "pan-European", + "pan-european", + "parformanceabh\u00e4ngige", + "paris", + "parks", + "partners", + "partnership", + "pattern", + "ped", + "pen", + "per", + "performance-fee", + "performanceziel", + "period", + "perpetual", + "pers", + "pers.", + "phil", + "phil.", + "pid", + "pkt", + "pkt.", + "pl.", + "planned", + "ple", + "plus", + "poland", + "pon", + "portfolio", + "portfolios", + "portugal", + "potential", + "pp\u00f6", + "pr.", + "premium", + "preservation", + "pricey", + "pricing", + "prime", + "pro", + "process", + "prof", + "prof.", + "profile", + "prognose", + "prognostiderte", + "prognostizierte", + "program", + "projects", + "projektentwicklungen", + "projektentwicklungsrisiken", + "propco", + "properties", + "proprietary", + "provide", + "providing", + "pt", + "pt.", + "public", + "pursue", + "pw.", + "q", + "q.", + "q.e.d", + "q.e.d.", + "qsdsdwhj", + "quality", + "quarterly", + "quota", + "quote", + "qwhj", + "r", + "r.", + "r.i.p.", + "rTt", + "rabatt", + "ram", + "range", + "rapid", + "rat", + "rate", + "rce", + "rd", + "rd.", + "re", + "re+", + "rea", + "real", + "realisiert", + "recent", + "rechtsform", + "record", + "recovery", + "red", + "red.", + "redemption", + "reflecting", + "region", + "regionen", + "reinvestment", + "relationships", + "remains", + "ren", + "rendite-", + "rendite-risiko-profil", + "renegotiation", + "renovierungen", + "rent", + "rents", + "rer", + "rer.", + "residential", + "residentials", + "resilient", + "respective", + "retail", + "retailinvestitionsvolumen", + "return", + "returns", + "reversion", + "rewe", + "rge", + "ria", + "rid", + "rig", + "right", + "rights", + "ris", + "risiko-rendite-bandbreite", + "risikoprofil", + "risk", + "rks", + "rl.", + "rly", + "rm.", + "rms", + "rn.", + "rne", + "rns", + "rof", + "rolling", + "room", + "rop", + "rotterdam", + "rr.", + "rs.", + "rsg", + "rst", + "rte", + "rz.", + "r\u00f6m", + "r\u00f6m.", + "r\u00f6misch", + "r\u2019m", + "r\u2019s", + "s", + "s'", + "s.", + "s.o", + "s.o.", + "s.w", + "s12", + "sa", + "sa.", + "sadas", + "sale", + "samkd23", + "sb.", + "schule", + "schweden", + "scope", + "scs", + "scsp", + "sd.", + "sdad23", + "sdb", + "sdd", + "sdf", + "sdfasd21", + "sdfs", + "sdsdfsd", + "sdvf34", + "sector", + "sectors", + "sed", + "seeking", + "sefwf", + "segment", + "sektor", + "sektoraler", + "selection", + "sen", + "sen.", + "sense", + "sep", + "sep.", + "sept", + "sept.", + "ser", + "ses", + "set", + "sf.", + "sfdfb", + "sfdr", + "sfdsfdf", + "sg.", + "shh", + "short-term", + "sicav-raif", + "sich", + "sie", + "siehe", + "sie\u2019s", + "since", + "sind", + "sis", + "sitz", + "size", + "skandinavien", + "small", + "so", + "so.", + "sobald", + "sofern", + "sog", + "sog.", + "solely", + "solvency", + "some", + "son", + "sp", + "sp.", + "space", + "spain", + "spanien", + "spezial-aif", + "spezial-alf", + "spezial-sonderverm\u00f6gen", + "split", + "spr", + "spw", + "sri", + "ss.", + "st", + "st.", + "stabiler", + "stabilisieren", + "stabilisierung", + "stabilisierungs-", + "standort", + "standortaufwertungsstrategie", + "standorte", + "status", + "std", + "std.", + "stellv", + "stellv.", + "steuern", + "stil", + "str", + "str.", + "strategic", + "strategie", + "strategien", + "strategies", + "strategy", + "strong", + "structure", + "struktur", + "strukturierungsgebu\u0308hr", + "strukturierungsgeb\u00fchr", + "style", + "st\u00e4dten", + "sue", + "sw.", + "sweden", + "s\u2019", + "t", + "t.", + "tactical", + "tag", + "tal", + "target", + "target-irr", + "targeted", + "targeting", + "targets", + "targetvehiclesize", + "tc.", + "td.", + "te-", + "ted", + "tee", + "teflimmobilfe)-", + "tel", + "tel.", + "telefonnummer", + "ten", + "tenant", + "ter", + "term", + "terms", + "tes", + "test", + "testdvfk", + "tet", + "tfzdrf", + "th.", + "that", + "the", + "their", + "there", + "this", + "through", + "throughout", + "ths", + "tic", + "tig", + "tik", + "til", + "time", + "tinental", + "tl.", + "to", + "top", + "tor", + "total", + "tr", + "tr.", + "track", + "try", + "tsd", + "tsd.", + "tte", + "tto", + "tue", + "tur", + "tus", + "typ", + "type", + "tze", + "tzl", + "t\u00e4gl", + "t\u00e4gl.", + "t\u00e4glich", + "t\u00e4t", + "u", + "u.", + "u.U.", + "u.a", + "u.a.", + "u.s.", + "u.s.a.", + "u.s.s.", + "u.s.w", + "u.s.w.", + "u.u.", + "u.v.m", + "u.v.m.", + "ual", + "uch", + "uer", + "ufs", + "ug.", + "ugh", + "uid", + "uk", + "ul.", + "uld", + "ule", + "um", + "ume", + "umliegende", + "un.", + "unbegrenzte", + "und", + "under", + "undertaking", + "ung", + "united", + "univ", + "univ.", + "unless", + "unter", + "unternehmensimmobilien", + "unterstellt", + "unter\u2019m", + "upon", + "upscale", + "upside", + "uqw", + "ur.", + "ure", + "urg", + "urn", + "uro", + "urs", + "usf", + "usf.", + "uss", + "ust", + "usw", + "usw.", + "ute", + "uvm", + "uvm.", + "u\u0308ber", + "u\u0308berschritten", + "u\u0308r", + "u\u2019s", + "v", + "v.", + "v.Chr.", + "v.a", + "v.a.", + "v.chr.", + "v.l.n.r", + "v.l.n.r.", + "v.m", + "v.v", + "v_v", + "value", + "value-add", + "value-added", + "var", + "vehicle", + "vehikelstruktur", + "vel", + "ven", + "ver", + "verbesserungen", + "verbund", + "vereinigtes", + "vergleiche", + "vergu\u0308tung", + "verg\u00fctung", + "verkaufs", + "verkaufs-", + "verkehrswertes", + "verl\u00e4ngerungsoption", + "vermietbare", + "vermietet", + "very", + "ves", + "vfk", + "vgl", + "vgl.", + "vielleicht", + "vllt", + "vllt.", + "vlt", + "vlt.", + "vm.", + "vol", + "vol.", + "voll", + "volume", + "vom", + "von", + "vor", + "vorhanden", + "vorlauf", + "vor\u2019m", + "vs", + "vs.", + "vtl", + "w", + "w.", + "w45", + "wSt", + "walls", + "walt", + "way", + "wdds12", + "wefwefw", + "well-established", + "well-mitigated", + "wenn", + "werden", + "wertstabile", + "wfw", + "whj", + "wholesale", + "why", + "wir", + "wird", + "wir\u2019s", + "wiss", + "wiss.", + "with", + "wjk", + "wohngemeinschaften", + "wohnimmobilien", + "worldwide", + "x", + "x'", + "x.", + "x.X", + "x.X.", + "x.Xx.", + "x.Xxx.", + "x.d", + "x.x", + "x.x.", + "x.x.X.", + "x.x.x", + "x.x.x.", + "x.x.x.x", + "x.x.x.x.", + "x/x", + "xD", + "xDD", + "xX", + "xXX", + "x_X", + "x_d", + "x_x", + "xd", + "xdd", + "xemoours", + "xit", + "xx", + "xx.", + "xx.x", + "xxXxx", + "xxx", + "xxx-Xxxxx", + "xxx-xxxx", + "xxx.", + "xxxdd", + "xxxx", + "xxxx+", + "xxxx-xx", + "xxxx-xxx", + "xxxx-xxxx", + "xxxx.", + "xxxxdd", + "xxxx\u2019x", + "xxx\u2019x", + "xx\u0308x", + "xx\u2019x", + "x\u0308xxx", + "x\u0308xxxx", + "x\u2019", + "x\ufe35x", + "y", + "y.", + "year", + "years", + "yield", + "yle", + "yoy", + "ype", + "yrs", + "z", + "z.", + "z.B.", + "z.Bsp.", + "z.T.", + "z.Z.", + "z.Zt.", + "z.b", + "z.b.", + "z.bsp.", + "z.t.", + "z.z.", + "z.zt.", + "zeichnungen", + "zen", + "zgl", + "zgwgzu", + "zgzdgzhg", + "zhg", + "ziel-lty", + "ziel-netto-irr", + "zielallokation", + "zielanlagestrategie", + "zielausschu\u0308ttung", + "zielmarkts", + "zielm\u00e4rkte", + "zielobjekte", + "zielobjektgr\u00f6\u00dfe", + "zielregionfen)/jand", + "zielrendite", + "zielrenditen", + "zielsektoren", + "zielvolumen", + "ziirraiaein", + "zin", + "zins", + "zins-", + "zinsfu\u00df", + "zinss\u00e4tze", + "zt", + "zte", + "ztue", + "zu", + "zum", + "zusatzl", + "zw.", + "zwischen", + "zzgl", + "zzgl.", + "{", + "|", + "}", + "\u00a0", + "\u00a2", + "\u00a9", + "\u00ab", + "\u00ac", + "\u00ac_\u00ac", + "\u00ae", + "\u00af", + "\u00af\\(x)/\u00af", + "\u00af\\(\u30c4)/\u00af", + "\u00b0", + "\u00b0C.", + "\u00b0F.", + "\u00b0K.", + "\u00b0X.", + "\u00b0c.", + "\u00b0f.", + "\u00b0k.", + "\u00b0x.", + "\u00c4", + "\u00c4rzteh\u00e4user", + "\u00c4rzteh\u00e4usern", + "\u00dc", + "\u00dcbersicht", + "\u00e4", + "\u00e4.", + "\u00e4gl", + "\u00e4gt", + "\u00e4r.", + "\u00e4rzteh\u00e4user", + "\u00e4rzteh\u00e4usern", + "\u00e9", + "\u00f6", + "\u00f6.", + "\u00f6m.", + "\u00f6sterr", + "\u00f6sterr.", + "\u00f6sterreichisch", + "\u00f6\u00dfe", + "\u00fc", + "\u00fc.", + "\u00fcber", + "\u00fcbersicht", + "\u00fcber\u2019m", + "\u00fcft", + "\u00fchr", + "\u0308hr", + "\u0ca0", + "\u0ca0_\u0ca0", + "\u0ca0\ufe35\u0ca0", + "\u2014", + "\u2018", + "\u2019", + "\u2019-(", + "\u2019-)", + "\u2019S", + "\u2019X", + "\u2019m", + "\u2019n", + "\u2019ne", + "\u2019nem", + "\u2019nen", + "\u2019s", + "\u2019x", + "\u2019xx", + "\u2019xxx", + "\u2019\u2019", + "\u201a", + "\u201c", + "\u201d", + "\u20ac", + "\u2501", + "\u253b", + "\u253b\u2501\u253b", + "\u256f", + "\u25a1", + "\ufe35", + "\uff09" +] \ No newline at end of file diff --git a/project/backend/spacy-service/spacy_training/output/model-backup/vocab/vectors b/project/backend/spacy-service/spacy_training/output/model-backup/vocab/vectors new file mode 100644 index 0000000..ebadaa5 Binary files /dev/null and b/project/backend/spacy-service/spacy_training/output/model-backup/vocab/vectors differ diff --git a/project/backend/spacy-service/spacy_training/output/model-backup/vocab/vectors.cfg b/project/backend/spacy-service/spacy_training/output/model-backup/vocab/vectors.cfg new file mode 100644 index 0000000..32c800a --- /dev/null +++ b/project/backend/spacy-service/spacy_training/output/model-backup/vocab/vectors.cfg @@ -0,0 +1,3 @@ +{ + "mode":"default" +} \ No newline at end of file diff --git a/project/backend/spacy-service/spacy_training/output/model-last/config.cfg b/project/backend/spacy-service/spacy_training/output/model-last/config.cfg index 1cf80c4..be02f9c 100644 --- a/project/backend/spacy-service/spacy_training/output/model-last/config.cfg +++ b/project/backend/spacy-service/spacy_training/output/model-last/config.cfg @@ -1,21 +1,21 @@ [paths] -train = "./data/train.spacy" -dev = "./data/train.spacy" +train = null +dev = null vectors = null init_tok2vec = null [system] -gpu_allocator = null seed = 0 +gpu_allocator = null [nlp] lang = "de" -pipeline = ["tok2vec","ner"] -batch_size = 1000 +pipeline = ["ner"] disabled = [] before_creation = null after_creation = null after_pipeline_creation = null +batch_size = 1000 tokenizer = {"@tokenizers":"spacy.Tokenizer.v1"} vectors = {"@vectors":"spacy.Vectors.v1"} @@ -38,51 +38,34 @@ use_upper = true nO = null [components.ner.model.tok2vec] -@architectures = "spacy.Tok2VecListener.v1" -width = ${components.tok2vec.model.encode.width} -upstream = "*" - -[components.tok2vec] -factory = "tok2vec" - -[components.tok2vec.model] -@architectures = "spacy.Tok2Vec.v2" - -[components.tok2vec.model.embed] -@architectures = "spacy.MultiHashEmbed.v2" -width = ${components.tok2vec.model.encode.width} -attrs = ["NORM","PREFIX","SUFFIX","SHAPE"] -rows = [5000,1000,2500,2500] -include_static_vectors = false - -[components.tok2vec.model.encode] -@architectures = "spacy.MaxoutWindowEncoder.v2" +@architectures = "spacy.HashEmbedCNN.v2" +pretrained_vectors = null width = 96 depth = 4 +embed_size = 2000 window_size = 1 maxout_pieces = 3 +subword_features = true [corpora] [corpora.dev] @readers = "spacy.Corpus.v1" path = ${paths.dev} -max_length = 0 gold_preproc = false +max_length = 0 limit = 0 augmenter = null [corpora.train] @readers = "spacy.Corpus.v1" path = ${paths.train} -max_length = 0 gold_preproc = false +max_length = 0 limit = 0 augmenter = null [training] -dev_corpus = "corpora.dev" -train_corpus = "corpora.train" seed = ${system.seed} gpu_allocator = ${system.gpu_allocator} dropout = 0.1 @@ -93,6 +76,8 @@ max_steps = 20000 eval_frequency = 200 frozen_components = [] annotating_components = [] +dev_corpus = "corpora.dev" +train_corpus = "corpora.train" before_to_disk = null before_update = null diff --git a/project/backend/spacy-service/spacy_training/output/model-last/meta.json b/project/backend/spacy-service/spacy_training/output/model-last/meta.json index 64f070d..8a188d0 100644 --- a/project/backend/spacy-service/spacy_training/output/model-last/meta.json +++ b/project/backend/spacy-service/spacy_training/output/model-last/meta.json @@ -17,11 +17,9 @@ "mode":"default" }, "labels":{ - "tok2vec":[ - - ], "ner":[ "AUSSCH\u00dcTTUNGSRENDITE", + "KENNZAHL", "LAUFZEIT", "L\u00c4NDERALLOKATION", "MANAGMENTGEB\u00dcHREN", @@ -33,68 +31,12 @@ ] }, "pipeline":[ - "tok2vec", "ner" ], "components":[ - "tok2vec", "ner" ], "disabled":[ - ], - "performance":{ - "ents_f":0.9608938547, - "ents_p":1.0, - "ents_r":0.9247311828, - "ents_per_type":{ - "RISIKOPROFIL":{ - "p":1.0, - "r":1.0, - "f":1.0 - }, - "AUSSCH\u00dcTTUNGSRENDITE":{ - "p":1.0, - "r":0.5925925926, - "f":0.7441860465 - }, - "LAUFZEIT":{ - "p":1.0, - "r":1.0, - "f":1.0 - }, - "RENDITE":{ - "p":1.0, - "r":1.0, - "f":1.0 - }, - "L\u00c4NDERALLOKATION":{ - "p":1.0, - "r":0.8965517241, - "f":0.9454545455 - }, - "ZIELRENDITE":{ - "p":1.0, - "r":1.0, - "f":1.0 - }, - "ZIELAUSSCH\u00dcTTUNG":{ - "p":1.0, - "r":1.0, - "f":1.0 - }, - "MANAGMENTGEB\u00dcHREN":{ - "p":1.0, - "r":1.0, - "f":1.0 - }, - "SEKTORENALLOKATION":{ - "p":1.0, - "r":1.0, - "f":1.0 - } - }, - "tok2vec_loss":33.6051129291, - "ner_loss":740.5764770508 - } + ] } \ No newline at end of file diff --git a/project/backend/spacy-service/spacy_training/output/model-last/ner/model b/project/backend/spacy-service/spacy_training/output/model-last/ner/model index 3e88595..a8ad3a1 100644 Binary files a/project/backend/spacy-service/spacy_training/output/model-last/ner/model and b/project/backend/spacy-service/spacy_training/output/model-last/ner/model differ diff --git a/project/backend/spacy-service/spacy_training/output/model-last/ner/moves b/project/backend/spacy-service/spacy_training/output/model-last/ner/moves index b76b203..48f4d53 100644 --- a/project/backend/spacy-service/spacy_training/output/model-last/ner/moves +++ b/project/backend/spacy-service/spacy_training/output/model-last/ner/moves @@ -1 +1 @@ -movesL{"0":{},"1":{"RISIKOPROFIL":161,"L\u00c4NDERALLOKATION":161,"RENDITE":91,"AUSSCH\u00dcTTUNGSRENDITE":68,"LAUFZEIT":38,"ZIELRENDITE":12,"SEKTORENALLOKATION":12,"MANAGMENTGEB\u00dcHREN":8,"ZIELAUSSCH\u00dcTTUNG":2},"2":{"RISIKOPROFIL":161,"L\u00c4NDERALLOKATION":161,"RENDITE":91,"AUSSCH\u00dcTTUNGSRENDITE":68,"LAUFZEIT":38,"ZIELRENDITE":12,"SEKTORENALLOKATION":12,"MANAGMENTGEB\u00dcHREN":8,"ZIELAUSSCH\u00dcTTUNG":2},"3":{"RISIKOPROFIL":161,"L\u00c4NDERALLOKATION":161,"RENDITE":91,"AUSSCH\u00dcTTUNGSRENDITE":68,"LAUFZEIT":38,"ZIELRENDITE":12,"SEKTORENALLOKATION":12,"MANAGMENTGEB\u00dcHREN":8,"ZIELAUSSCH\u00dcTTUNG":2},"4":{"RISIKOPROFIL":161,"L\u00c4NDERALLOKATION":161,"RENDITE":91,"AUSSCH\u00dcTTUNGSRENDITE":68,"LAUFZEIT":38,"ZIELRENDITE":12,"SEKTORENALLOKATION":12,"MANAGMENTGEB\u00dcHREN":8,"ZIELAUSSCH\u00dcTTUNG":2,"":1},"5":{"":1}}cfgneg_key \ No newline at end of file +moves{"0":{},"1":{"KENNZAHL":-1,"RISIKOPROFIL":-2,"AUSSCH\u00dcTTUNGSRENDITE":-3,"LAUFZEIT":-4,"RENDITE":-5,"L\u00c4NDERALLOKATION":-6,"ZIELRENDITE":-7,"ZIELAUSSCH\u00dcTTUNG":-8,"MANAGMENTGEB\u00dcHREN":-9,"SEKTORENALLOKATION":-10},"2":{"KENNZAHL":-1,"RISIKOPROFIL":-2,"AUSSCH\u00dcTTUNGSRENDITE":-3,"LAUFZEIT":-4,"RENDITE":-5,"L\u00c4NDERALLOKATION":-6,"ZIELRENDITE":-7,"ZIELAUSSCH\u00dcTTUNG":-8,"MANAGMENTGEB\u00dcHREN":-9,"SEKTORENALLOKATION":-10},"3":{"KENNZAHL":-1,"RISIKOPROFIL":-2,"AUSSCH\u00dcTTUNGSRENDITE":-3,"LAUFZEIT":-4,"RENDITE":-5,"L\u00c4NDERALLOKATION":-6,"ZIELRENDITE":-7,"ZIELAUSSCH\u00dcTTUNG":-8,"MANAGMENTGEB\u00dcHREN":-9,"SEKTORENALLOKATION":-10},"4":{"":1,"KENNZAHL":-1,"RISIKOPROFIL":-2,"AUSSCH\u00dcTTUNGSRENDITE":-3,"LAUFZEIT":-4,"RENDITE":-5,"L\u00c4NDERALLOKATION":-6,"ZIELRENDITE":-7,"ZIELAUSSCH\u00dcTTUNG":-8,"MANAGMENTGEB\u00dcHREN":-9,"SEKTORENALLOKATION":-10},"5":{"":1}}cfgneg_key \ No newline at end of file diff --git a/project/backend/spacy-service/spacy_training/output/model-last/vocab/strings.json b/project/backend/spacy-service/spacy_training/output/model-last/vocab/strings.json index 7c963aa..e3bd2c8 100644 --- a/project/backend/spacy-service/spacy_training/output/model-last/vocab/strings.json +++ b/project/backend/spacy-service/spacy_training/output/model-last/vocab/strings.json @@ -52,9 +52,7 @@ "*", "+", "+/D", - "+/d", "+AU", - "+au", ",", ",00", ",03", @@ -129,21 +127,15 @@ "/080%/212%/491", "/2,12", "/3", - "/AuM", "/Core+", "/FK", "/XX", - "/XxX", "/Xxxx+", - "/aum", "/core+", "/d", "/d,dd", "/ddd%/ddd%/ddd", "/fk", - "/xx", - "/xxx", - "/xxxx+", "0", "0%+", "0,0", @@ -281,7 +273,6 @@ "45", "491", "5", - "5%+", "5,0", "5,00", "5,1", @@ -311,7 +302,6 @@ "7", "7,1", "7,5", - "7,5%+", "7,50", "7,50%+", "7.5", @@ -328,8 +318,6 @@ "8-D", "8-d", "80", - "800", - "84,0", "85", "8D", "8d", @@ -469,7 +457,6 @@ "Abteilung", "Access", "Add", - "Agreements", "Aktive", "Aktueller", "AlF", @@ -477,7 +464,6 @@ "Allocation", "Allokation", "Allokationsprofil", - "Alternative", "Amsterdam", "Andere", "Anfrage", @@ -513,7 +499,6 @@ "Artikel", "Asset", "Assets", - "AuM", "Aufbau", "Auflage", "Aufl\u00f6sung", @@ -583,10 +568,7 @@ "COR", "CORE", "CSU", - "CSp", - "Cash", "Cash-Flow-Stabilit\u00e4t", - "Cash-flow", "Chr", "Chr.", "Cie", @@ -648,7 +630,6 @@ "E.", "EAN", "ECLF", - "EIT", "EM", "ERD", "ESG-", @@ -683,7 +664,6 @@ "F", "F.", "FDR", - "FIL", "FR", "FRANCE", "FUND", @@ -794,11 +774,9 @@ "III.", "INK", "INREV", - "ION", "IRR", "IRR6.5", "IT", - "ITE", "IUM", "IV", "IV.", @@ -824,7 +802,6 @@ "Interner", "Invastitionsfokus", "Investftionsvolumen", - "Investing", "Investitionen", "Investitions-annahmen", "Investitionsphase", @@ -834,7 +811,6 @@ "Investmentzeitraum", "Investoren", "Investtionszeltraum", - "Investtionszeltraum,10", "Investtonszeltraum", "Ireland", "Irland", @@ -866,6 +842,7 @@ "K.", "K.O.", "KAGB", + "KENNZAHL", "KINGDOM", "KVG", "Kapitalstruktur", @@ -905,7 +882,6 @@ "Light", "Limited", "Lisbon", - "Loan-to-Value", "Local", "Logistics", "Logistik", @@ -1056,12 +1032,10 @@ "Prof", "Prof.", "Professor", - "Prognose", "Prognostiderte", "Prognostizierte", "Projektentwicklungen", "Projektentwicklungsrisiken", - "PropCo", "Pt", "Punkt", "Q", @@ -1072,7 +1046,6 @@ "R.", "R.I.P.", "RE", - "REN", "RENDITE", "REV", "REWE", @@ -1104,7 +1077,6 @@ "S", "S'", "SCS", - "SCSp", "SEKTORENALLOKATION", "SFDR", "SG-", @@ -1197,7 +1169,6 @@ "U.S.S.", "UK", "UND", - "UNG", "UNITED", "USt", "Univ", @@ -1264,7 +1235,6 @@ "XXXX", "XXXX-XXXX", "XXXd.d", - "XXXx", "XXXxx", "XXx", "XXxxxx", @@ -1289,18 +1259,15 @@ "Xxxx-XXX", "Xxxx-Xxxx-Xxxxx", "Xxxx-Xxxxx-XXX", - "Xxxx-xx-Xxxxx", "Xxxx-xxx", "Xxxx-xxxx", "Xxxx.", "Xxxx.-Xxx", "Xxxx.-Xxx.", - "XxxxXx", "Xxxxx", "Xxxxx)-", "Xxxxx)/Xxxx", "Xxxxx+", - "Xxxxx,dd", "Xxxxx-", "Xxxxx-XXX", "Xxxxx-XxX", @@ -1381,6 +1348,7 @@ "a.g.", "a.m.", "a.z.", + "a34", "ab", "abb", "abb.", @@ -1410,14 +1378,11 @@ "advantage", "ae", "aft", - "agb", "age", - "agreements", "aha", "ahe", "ahl", "ahr", - "aif", "ail", "aiming", "ain", @@ -1429,7 +1394,6 @@ "al.", "ald", "ale", - "alf", "all", "allg", "allg.", @@ -1440,8 +1404,6 @@ "allokationsprofil", "als", "also", - "alt", - "alternative", "aly", "am.", "ambulant", @@ -1497,7 +1459,6 @@ "ary", "as", "ase", - "ash", "ass", "asset", "assetor", @@ -1535,7 +1496,6 @@ "aussch\u00fcttungsrandite", "aussch\u00fcttungsrendite", "aussch\u00fcttungsrendites", - "aut", "ave", "ax.", "b", @@ -1544,7 +1504,6 @@ "b.sc", "b.sc.", "bahnhof", - "bal", "balanced", "basis", "bau", @@ -1586,7 +1545,6 @@ "both", "bps", "br.", - "brands", "broad", "brussels", "bruttofondsverm\u00f6gens", @@ -1619,8 +1577,6 @@ "capital", "capped", "carbon", - "cash", - "cash-flow", "cash-flow-stabilit\u00e4t", "cbd", "cdu", @@ -1643,7 +1599,6 @@ "cl.", "class", "cle", - "clf", "closed", "closing", "closings", @@ -1663,7 +1618,6 @@ "construction", "contract", "contracts", - "cor", "core", "core+", "core+/d", @@ -1672,7 +1626,6 @@ "could", "country", "creation", - "csp", "csu", "cts", "currency", @@ -1684,7 +1637,6 @@ "d+au", "d+aut", "d,d", - "d,d%+", "d,dd", "d,dd%+", "d,ddd", @@ -1710,6 +1662,7 @@ "darge", "darlehen", "das", + "dasda34", "dat", "dd", "dd,d", @@ -1735,7 +1688,6 @@ "der", "dergleichen", "des", - "destinations", "deutsche", "deutsches", "deutschland", @@ -1756,7 +1708,6 @@ "dipl.", "dipl.-ing", "dipl.-ing.", - "dis", "discretionary", "distributions", "diversification", @@ -1767,8 +1718,6 @@ "dle", "do", "do.", - "dom", - "domicile", "domiciled", "don", "down", @@ -1783,7 +1732,6 @@ "durchschnittlich", "du\u2019s", "dv.", - "dxxx.\u20ac", "dy", "d\u00e4nemark", "d\u2019", @@ -1847,7 +1795,6 @@ "eln", "els", "elt", - "ely", "em", "em.", "emerging", @@ -1877,7 +1824,6 @@ "er.", "erb", "erbbaurechte", - "erd", "ere", "erfolgten", "erg", @@ -1902,7 +1848,6 @@ "ete", "etr", "ets", - "eturn", "eu-offenlegungsverordnung", "eur", "euro", @@ -1940,7 +1885,6 @@ "fam", "fam.", "favour", - "fdr", "feb", "feb.", "fee", @@ -1952,7 +1896,6 @@ "ff", "fierce", "fil", - "financially", "finanzierung", "finanzierungskonditionen", "finland", @@ -1960,7 +1903,6 @@ "first", "flagship", "flow", - "flow-oriented", "fl\u00e4che", "focus", "focused", @@ -2051,7 +1993,6 @@ "gic", "gie", "gl.", - "global", "globale", "gmbh", "goal", @@ -2231,7 +2172,6 @@ "investoren", "investors", "investtionszeltraum", - "investtionszeltraum,10", "investtonszeltraum", "inw", "io.", @@ -2374,8 +2314,6 @@ "lls", "llt", "llv", - "lly", - "loan-to-value", "local", "locations", "lock-in", @@ -2383,7 +2321,6 @@ "logistik", "logistikimmobilien", "london", - "long-term", "low", "lps", "lso", @@ -2393,7 +2330,6 @@ "lto", "ltv", "ltv-ziel", - "lty", "lu", "lub", "lue", @@ -2427,7 +2363,6 @@ "management", "manager", "manager-defined", - "managmentgeb\u00fchren", "mandate", "mandates", "market", @@ -2439,7 +2374,6 @@ "maximal", "maximaler", "mbH", - "mbh", "means", "medizin", "medizinnahe", @@ -2659,11 +2593,7 @@ "parformanceabh\u00e4ngige", "paris", "parks", - "partners", "partnership", - "pattern", - "pci", - "pco", "ped", "pen", "per", @@ -2694,18 +2624,15 @@ "pricey", "pricing", "prime", - "pro", "prof", "prof.", "profile", - "prognose", "prognostiderte", "prognostizierte", "program", "projects", "projektentwicklungen", "projektentwicklungsrisiken", - "propco", "properties", "proprietary", "provide", @@ -2719,7 +2646,6 @@ "q.", "q.e.d", "q.e.d.", - "qin", "quality", "quarterly", "quota", @@ -2756,7 +2682,6 @@ "relationships", "remains", "ren", - "rendite", "rendite-", "rendite-risiko-profil", "renegotiation", @@ -2773,7 +2698,6 @@ "retailinvestitionsvolumen", "return", "returns", - "rev", "reversion", "rewe", "rge", @@ -2800,12 +2724,10 @@ "rop", "rotterdam", "rr.", - "rre", "rs.", "rsg", "rst", "rte", - "rtt", "rz.", "r\u00f6m", "r\u00f6m.", @@ -2826,7 +2748,6 @@ "schweden", "scope", "scs", - "scsp", "sd.", "sector", "sectors", @@ -2835,7 +2756,6 @@ "segment", "sektor", "sektoraler", - "sektorenallokation", "selection", "sen", "sen.", @@ -2849,7 +2769,6 @@ "set", "sf.", "sfdr", - "sg-", "sg.", "short-term", "sicav-raif", @@ -2870,7 +2789,6 @@ "sofern", "sog", "sog.", - "solely", "solvency", "some", "son", @@ -3128,9 +3046,6 @@ "worldwide", "x", "x'", - "x+xx", - "x+xxx", - "x-xxxx", "x.", "x.X", "x.X.", @@ -3157,38 +3072,23 @@ "xemoours", "xit", "xx", - "xx-xxxx", "xx.", "xx.x", "xxXxx", "xxx", - "xxx-", "xxx-Xxxxx", "xxx-xxxx", "xxx.", - "xxxd.d", "xxxx", - "xxxx)-", - "xxxx)/xxxx", "xxxx+", - "xxxx+/x", - "xxxx+/xxxx", - "xxxx,dd", - "xxxx-", "xxxx-xx", - "xxxx-xx-xxxx", "xxxx-xxx", "xxxx-xxxx", - "xxxx-xxxx-xxx", - "xxxx-xxxx-xxxx", "xxxx.", - "xxxx\u0308xx", - "xxxx\u0308xxx-xxxx", - "xxxx\u0308xxxx", + "xxxxdd", "xxxx\u2019x", "xxx\u2019x", "xx\u0308x", - "xx\u0308xxxx", "xx\u2019x", "x\u0308xxx", "x\u0308xxxx", @@ -3224,7 +3124,6 @@ "zielallokation", "zielanlagestrategie", "zielausschu\u0308ttung", - "zielaussch\u00fcttung", "zielmarkts", "zielm\u00e4rkte", "zielobjekte", diff --git a/project/backend/spacy-service/spacy_training/test2.json b/project/backend/spacy-service/spacy_training/test2.json new file mode 100644 index 0000000..2c9a164 --- /dev/null +++ b/project/backend/spacy-service/spacy_training/test2.json @@ -0,0 +1,122 @@ +[ + { + "text": "Core", + "entities": [ + [ + 0, + 4, + "RISIKOPROFIL" + ] + ] + }, + { + "text": "Core+", + "entities": [ + [ + 0, + 5, + "RISIKOPROFIL" + ] + ] + }, + { + "text": "Core/Core+", + "entities": [ + [ + 0, + 10, + "RISIKOPROFIL" + ] + ] + }, + { + "text": "Value Add", + "entities": [ + [ + 0, + 9, + "RISIKOPROFIL" + ] + ] + }, + { + "text": "Core/Value Add", + "entities": [ + [ + 0, + 14, + "RISIKOPROFIL" + ] + ] + }, + { + "text": "Core+/Value Add", + "entities": [ + [ + 0, + 15, + "RISIKOPROFIL" + ] + ] + }, + { + "text": "Core/Core+/Value Add", + "entities": [ + [ + 0, + 20, + "RISIKOPROFIL" + ] + ] + }, + { + "text": "The RE portfolio of the fund is a good illustration of Fond expertise in European core/core+ investments .", + "entities": [ + [ + 82, + 92, + "RISIKOPROFIL" + ] + ] + }, + { + "text": "Risk level: Core/Core+", + "entities": [ + [ + 12, + 22, + "RISIKOPROFIL" + ] + ] + }, + { + "text": "Different risk profile (core, core+, value-added)", + "entities": [ + [ + 24, + 48, + "RISIKOPROFIL" + ] + ] + }, + { + "text": "Core/Core+ with OpCo premium", + "entities": [ + [ + 0, + 10, + "RISIKOPROFIL" + ] + ] + }, + { + "text": "Core /Core+ Assets, well-established = Key Gateway Cities in Europe le.g. hotels in the market with minor asset London, Paris, Amsterdam, Berlin] management initiatives", + "entities": [ + [ + 0, + 11, + "RISIKOPROFIL" + ] + ] + } +] \ No newline at end of file diff --git a/project/backend/spacy-service/spacy_training/training_data.py b/project/backend/spacy-service/spacy_training/training_data.py deleted file mode 100644 index a7f58f4..0000000 --- a/project/backend/spacy-service/spacy_training/training_data.py +++ /dev/null @@ -1,563 +0,0 @@ -TRAINING_DATA = [ - ( - "Core", - {"entities": [[0, 4, "RISIKOPROFIL"]]}, - ), - ( - "Core+", - {"entities": [[0, 5, "RISIKOPROFIL"]]}, - ), - ( - "Core/Core+", - {"entities": [[0, 10, "RISIKOPROFIL"]]}, - ), - ( - "Value Add", - {"entities": [[0, 9, "RISIKOPROFIL"]]}, - ), - ( - "Core/Value Add", - {"entities": [[0, 14, "RISIKOPROFIL"]]}, - ), - ( - "Core+/Value Add", - {"entities": [[0, 15, "RISIKOPROFIL"]]}, - ), - ( - "Core/Core+/Value Add", - {"entities": [[0, 20, "RISIKOPROFIL"]]}, - ), - ( - "The RE portfolio of the fund is a good illustration of Fond expertise in European core/core+ investments .", - {"entities": [[82, 92, "RISIKOPROFIL"]]}, - ), - ( - "Risk level: Core/Core+", - {"entities": [[12, 22, "RISIKOPROFIL"]]}, - ), - ( - "Different risk profile (core, core+, value-added)", - {"entities": [[24, 48, "RISIKOPROFIL"]]}, - ), - ( - "Core/Core+ with OpCo premium", - {"entities": [[0, 10, "RISIKOPROFIL"]]}, - ), - ( - "Core /Core+ Assets, well-established = Key Gateway Cities in Europe le.g. hotels in the market with minor asset London, Paris, Amsterdam, Berlin] management initiatives", - {"entities": [[0, 11, "RISIKOPROFIL"]]}, - ), - ( - "Risikoprofil: Core, Core +", - {"entities": [[14, 26, "RISIKOPROFIL"]]}, - ), - ( - "Name des Fonds Name des Investmentmanagers Allgemeine Informationen Name des Ansprechpartners Telefonnummer des Ansprechpartners E-Mail des Ansprechpartners Art des Anlagevehikels Struktur des Anlagevehikels Sitz des Anlagevehikels Struktur des Antagevehikels vom Manager festgelegter Stil Rechtsform Jahr des ersten Closings Laufzeit Geplantes Jahr der Auflösung Ziel-Netto-IRR / Gesamtrendite* Zielvolumen des Anlagevehikels Ziel-LTY ‚Aktueller LTV Ziirraiaein Maximaler LTV Zielregionfen)/Jand Zielsektoren Zielanlagestrategie INREV Fonds Offen Deutschland Core, Core + Offener Immobilien-Spezialfonds 2022 10 - 12 Jahre 2032 - 2034 7,50%+ 250 Mio. € 20% 0% 20% Führende Metropolregionen Deutschlands und ausgewählte Standorte >50T Einw. Wohnimmobilien Wertstabile Wohnimmobilien (mit Bestandsentwicklungen)", - {"entities": [[560, 572, "RISIKOPROFIL"]]}, - ), - ( - "Core/Core+ strategy, with tactical exposure to development projects aiming at enhancing the quality of the portfolio over time", - {"entities": [[0, 10, "RISIKOPROFIL"]]}, - ), - ( - "Strategie - Übersicht Risikoprofil Core+ Halten-Strategie Kaufen — Halten (langfristig) — Exit 1. Nachvermietungsstrategie Anlagestrategien 2. Standortaufwertungsstrategie 3. Strategie der Aufwertung der Immobilien Niederlande (max. 35 %) Länderallokation Frankreich (max. 35 %) (in % vom Zielvolumen) Skandinavien (Schweden, Dänemark) (max. 35 %) Deutschland (<= 10 %)", - {"entities": [[35, 40, "RISIKOPROFIL"]]}, - ), - ( - "Core and Core+", - {"entities": [[0, 14, "RISIKOPROFIL"]]}, - ), - ( - "core, core+, value-added", - {"entities": [[0, 24, "RISIKOPROFIL"]]}, - ), - ( - "Manage to Core: max 20%", - {"entities": [[10, 14, "RISIKOPROFIL"]]}, - ), - ( - "Benefits of the core/ core+ segment", - {"entities": [[16, 27, "RISIKOPROFIL"]]}, - ), - ( - "Drawbacks of the core/ core+ segment", - {"entities": [[17, 28, "RISIKOPROFIL"]]}, - ), - ( - "Why a Core / Core + investment program?", - {"entities": [[6, 19, "RISIKOPROFIL"]]}, - ), - ( - "Different risk profile (core, core+, value-added)", - {"entities": [[24, 48, "RISIKOPROFIL"]]}, - ), - ( - "INK MGallery Hotel Area: Amsterdam Core Tenant: Closed in 2018", - {"entities": [[35, 39, "RISIKOPROFIL"]]}, - ), - ( - "A strategy targeting high quality Core and Core+ buildings, with defined SRI objectives, in order to extract value through an active asset management.", - {"entities": [[34, 48, "RISIKOPROFIL"]]}, - ), - ( - "Navigate the diversity of the Core/Core+ investment opportunities in European Prime Cities", - {"entities": [[30, 40, "RISIKOPROFIL"]]}, - ), - ( - "GEDis an open-ended Lux-based fund providing an attractive core/core+ real estate exposure, leveraging GRRE expertise in European RE markets. It offers diversification in terms of pan-European geographies and sectors: Offices, Retail and Hotels.", - {"entities": [[59, 69, "RISIKOPROFIL"]]}, - ), - ( - "Core assets leave less room for active asset management value creation", - {"entities": [[0, 4, "RISIKOPROFIL"]]}, - ), - ( - "capital preservation is defined here as a characteristic of core/core+ investments. There is no guarantee of capital.", - {"entities": [[60, 70, "RISIKOPROFIL"]]}, - ), - ( - "Country / city BELGIUM Brussels BELGIUM Brussels SPAIN Madrid FRANCE Levallois FRANCE Paris 14 BELGIUM Brussels NETHERLANDS Rotterdam NETHERLANDS Rotterdam Sector Offices Offices Offices Offices Offices Offices Offices Logistics Risk Core", - {"entities": [[234, 238, "RISIKOPROFIL"]]}, - ), - ( - "GERD(a balanced pan-European open ended retail fund — under the form of a French collective undertaking for Real Estate investments “OPCI”) is the flagship ofQin France and combines RE and listed assets (respective targets of 60% and 40%) with max. 40% leverage. The RE portfolio of the fund is a good illustration Of expertise in European core/core+ investments.", - {"entities": [[340, 350, "RISIKOPROFIL"]]}, - ), - ( - "Prime office assets in Prime markets are very pricey unless rent reversion is real. Risk premium remains attractive on a leveraged basis. Manage to core or build to core can make sense as a LT investor in main cities. Residential is also attractive", - {"entities": [[148, 152, "RISIKOPROFIL"]]}, - ), - ( - "Paris region is a deep and liquid market. Rents have some potential to improve. Considering current low yield and fierce competition, office right outside CBD for Core + assets can be considered. Manage to core strategies could make sense.", - {"entities": [[163, 169, "RISIKOPROFIL"]]}, - ), - ( - "Lisbon is a small market but it experienced a rapid economic recovery in recent years and is interesting for Core Offices, quality Retail assetor Hotel walls with top operators. Limited liquidity of this market means investment must be small", - {"entities": [[109, 113, "RISIKOPROFIL"]]}, - ), - ( - "4,0 %", - {"entities": [[0, 5, "AUSSCHÜTTUNGSRENDITE"]]}, - ), - ( - "Prognostizierte jährliche Ausschüttung von 4,0%", - {"entities": [[44, 48, "AUSSCHÜTTUNGSRENDITE"]]}, - ), - ( - "20% über einer @ Ausschüttungsrendite von 4,0%", - {"entities": [[44, 48, "AUSSCHÜTTUNGSRENDITE"]]}, - ), - ( - "Prognostizierte Ausschüttungsrandite* Mindestanlage Mitgliedschaft Im Anlagesusschuss Ankaufs- / Verkaufs- / Verkaufs(Teflimmobilfe)- / Baumanagementgebahr (inkl. USt.) Parformanceabhängige Vergütung Einmalige Strukturierungsgebühr Laufzeit / Investtionszeltraum Ausschüttungsintervalle Deutsche Metropolregianen und umliegende Regionen mit Städten >50T Einwohner Artikel 8 Wohnimmobilien Deutschland ‚Aktive Bestandsentwicklung Offener Spezial-AlF mit festen Anlagebedingungen rd. 200 Mio. € / max. 20% rd. 250 Mio. € 7,5 % (nach Kosten & Gebühren, vor Steuern) 8 4,0 % {nach Kosten & Gebühren, var Steuern}", - {"entities": [[570, 575, "AUSSCHÜTTUNGSRENDITE"]]}, - ), - ( - "5,00-5,25 % Ausschüttungsrendite", - {"entities": [[0, 11, "AUSSCHÜTTUNGSRENDITE"]]}, - ), - ( - "Zielrendite 5,00-5,25 % Ausschüttungsrendite", - {"entities": [[12, 23, "AUSSCHÜTTUNGSRENDITE"]]}, - ), - ( - "Auschüttungsrendite 4,9% 5,3%", - {"entities": [[21, 25, "AUSSCHÜTTUNGSRENDITE"]]}, - ), - ( - "Auschüttungsrendite 4,9% 5,3%", - {"entities": [[26, 30, "AUSSCHÜTTUNGSRENDITE"]]}, - ), - ( - "Auschittungsrendite 3,8% 5,7%", - {"entities": [[20, 24, "AUSSCHÜTTUNGSRENDITE"]]}, - ), - ( - "Auschittungsrendite 3,8% 5,7%", - {"entities": [[25, 29, "AUSSCHÜTTUNGSRENDITE"]]}, - ), - ( - "Auschüttungsrendite 4,5% 4,6%", - {"entities": [[21, 25, "AUSSCHÜTTUNGSRENDITE"]]}, - ), - ( - "Auschüttungsrendite 4,5% 4,6%", - {"entities": [[26, 30, "AUSSCHÜTTUNGSRENDITE"]]}, - ), - ( - "Auschüttungsrendite 5,0% 4,7%", - {"entities": [[26, 30, "AUSSCHÜTTUNGSRENDITE"]]}, - ), - ( - "Auschüttungsrendite 5,0% 4,7%", - {"entities": [[21, 25, "AUSSCHÜTTUNGSRENDITE"]]}, - ), - ( - "Auschüttungsrendite “eons a Nuremberg aha 5,0 % 4,8 %", - {"entities": [[43, 48, "AUSSCHÜTTUNGSRENDITE"]]}, - ), - ( - "Auschüttungsrendite “eons a Nuremberg aha 5,0 % 4,8 %", - {"entities": [[49, 54, "AUSSCHÜTTUNGSRENDITE"]]}, - ), - ( - "3-4% dividend yield", - {"entities": [[0, 4, "AUSSCHÜTTUNGSRENDITE"]]}, - ), - ( - "Zielmärkte Klassifizierung SFDR Invastitionsfokus Rendite- / Risikoprofil Rechtsform Eigenkapital /FK Quote Investftionsvolumen Prognostizierte Gesamtrendite {IRR)* Prognostizierte Ausschüttungsrandite* Mindestanlage Mitgliedschaft Im Anlagesusschuss Ankaufs- / Verkaufs- / Verkaufs(Teflimmobilfe)- / Baumanagementgebahr (inkl. USt.) Parformanceabhängige Vergütung Einmalige Strukturierungsgebühr Deutsche Metropolregianen und umliegende Regionen mit Städten >50T Einwohner Artikel 8 Wohnimmobilien Deutschland ‚Aktive Bestandsentwicklung Offener Spezial-AlF mit festen Anlagebedingungen rd. 200 Mio. € / max. 20% rd. 250 Mio. € 7,5 % (nach Kosten & Gebühren, vor Steuern) 8 4,0 % {nach Kosten & Gebühren, var Steuern} 5Mio.€ Ab 10 Mio. € 1,40 % / 0,80 % /2,12% / 4,91 % Laufzeit / Investtionszeltraum Ausschüttungsintervalle 20 % über einer @ Ausschüttungsrendite von 4,0 % 0,1% der bis zum 31.12.2023 erfolgten Kapitalzusagen (max. 200.000 &) 10 bis 12 Jahre / bis zu 24 Monate angestrebt Mindestens jährlich", - {"entities": [[945, 960, "LAUFZEIT"]]}, - ), - ( - "Laufzeit / Investtionszeltraum,10 bis 12 Jahre / bis zu 24 Monate angestrebt Ausschüttungsintervalle,Mindestens jährlich", - {"entities": [[31, 46, "LAUFZEIT"]]}, - ), - ( - "10-12 Jahre Laufzeit bei einem LTV von bis zu 20%", - {"entities": [[0, 11, "LAUFZEIT"]]}, - ), - ( - "vom Manager festgelegter Stil Rechtsform Jahr des ersten Closings Laufzeit Geplantes Jahr der Auflösung Ziel-Netto-IRR / Gesamtrendite* Zielvolumen des Anlagevehikels Ziel-LTY‚Aktueller LTV Zielsektoren Zielanlagestrategie Fonds Offen Deutschland Core, Core + Offener Immobilien-Spezialfonds 2022 10 - 12 Jahre", - {"entities": [[297, 310, "LAUFZEIT"], [247, 259, "RISIKOPROFIL"]]}, - ), - ( - "Allgemeine Annahmen Ankaufsphase Haltedauer Zielobjektgröße Finanzierung Investitions-annahmen Zielrendite 24 Monate Investmentzeitraum 10 Jahre (+) EUR 20-75 Mio. Keine externe Finanzierung zum Auftakt (ausschließlich Darlehen der Anteilseigner). Die Finanzierung wird nach der Ankaufsphase und Stabilisierung der Zinssätze neu geprüft. Angestrebter LTV zwischen 25-40 % Investitionen für Renovierungen und ESG- Verbesserungen werden für jedes Objekt einzeln festgelegt. 5,00-5,25 % Ausschüttungsrendites", - {"entities": [[136, 148, "LAUFZEIT"], [472, 483, "AUSSCHÜTTUNGSRENDITE"]]}, - ), - ( - "Zielrendite 5,00-5,25 % Ausschüttungsrendite 1) Ankauf von Objekten an Tag eins mit 100% Eigenkapital. Die Strategie unterstellt die Aufnahme von Fremdkapital, sobald sich die Zins- und Finanzierungskonditionen nachhaltig stabilisieren. Strategie - Übersicht Risikoprofil Core+", - {"entities": [[12, 23, "AUSSCHÜTTUNGSRENDITE"], [272, 277, "RISIKOPROFIL"]]}, - ), - ( - "Vehicle lifetime / investment period Open-ended fund", - {"entities": [[37, 52, "LAUFZEIT"]]}, - ), - ( - "Vehicle / domicile Alternative Investment Fund / Luxembourg (e.g. SCSp SICAV-RAIF) Investment strategy eturn pro Real Estate (PropCo + OpCo) Investing in upscale hotels with long-term management contracts in major European destinations Core/Core+ with OpCo premium Management Agreements solely with financially strong and experienced partners/ global brands Cash flow-oriented Cash-flow pattern Target equity /AuM € 400m equity / € 800m AuM (50% Loan-to-Value) Vehicle lifetime / investment period Open-ended fund", - {"entities": [[498, 513, "LAUFZEIT"], [236, 245, "RISIKOPROFIL"]]}, - ), - ( - "Vehicle type (Lux-RAIF) (net of fees) IRR6.5% ACCOR Vehicle structure Open-ended Targetvehiclesize € 400m (equity) Manager-defined Core/Core+ with | style OpCo Premium darge CLV. 50% Pt H | LTO N WORLDWIDE Year of first closing 2020 Target no. ofinvestors 1-5 Fund life (yrs} Open-ended Min-commitmentper —¢ 400m", - {"entities": [[131, 141, "RISIKOPROFIL"], [70, 80, "LAUFZEIT"]]}, - ), - ( - "Fund term: Open-ended", - {"entities": [[11, 21, "LAUFZEIT"]]}, - ), - ( - "Abdeckung der Risiko-Rendite-Bandbreite (Core, Core+, Value-Add)", - {"entities": [[41, 63, "RISIKOPROFIL"]]}, - ), - ( - "5,1% - 8,5% IRR!", - {"entities": [[0, 11, "RENDITE"]]}, - ), - ( - "Retailinvestitionsvolumen nach Ländern (2024) Vereinigtes Königreich, 26,4% Deutschland, 19,0% Andere, 19,7% Italien, 8,2% Irland, 3,3% N | Frankreich, Spanien, 8,1%", - {"entities": [[46, 75, "LÄNDERALLOKATION"], [76, 94, "LÄNDERALLOKATION"], [95, 108, "LÄNDERALLOKATION"], [109, 122, "LÄNDERALLOKATION"], [123, 135, "LÄNDERALLOKATION"]]}, - ), - ( - "Erwartete IRR 5 (je nach Objekt- ‘A(E) 6.00% - 8,00%", - {"entities": [[39, 52, "RENDITE"]]}, - ), - ( - "Zielmarkts Deutsche Metropolregianen und umliegende Regionen mit Städten >50T Einwohner Klassifizierung SFDR Artikel 8 Invastitionsfokus Wohnimmobilien Deutschland Rendite- / Risikoprofil ‚Aktive Bestandsentwicklung Rechtsform Offener Spezial-AlF mit festen Anlagebedingungen Eigenkapital /FK Quote rd. 200 Mio. € / max. 20% Investftionsvolumen rd. 250 Mio. € Prognostiderte Gesamtrendite {IRR)* 7,5 % (nach Kosten & Gebühren, vor Steuern) Prognostizierte Ausschüttungsrandite* @ 4,0 % {nach Kosten & Gebühren, var Steuern} Mindestanlage 5Mio.€ Mitgliedschaft Im Anlagesusschuss Ab 10 Mio. € Ankaufs- / Verkaufs- / Verkaufs(Teflimmobilfe)- / Baumanagementgebahr (inkl. USt) 1,40 %/080%/212%/491% Parformanceabhängige Vergütung 20 % über einer ® Ausschüttungsrendite von 4,0% Einmalige Strukturierungsgebühr 0,1% der bis zum 31.12.2023 erfolgten Kapitalzusagen (max. 200.000 €) Laufzelt / Investtonszeltraum 10 bis 12 Jahre / bis zu 24 Monate angestrebt Ausschüttungsintervalle Mindestens jährlich", - {"entities": [[396, 401, "RENDITE"], [482, 487, "AUSSCHÜTTUNGSRENDITE"], [914, 929, "LAUFZEIT"]]}, - ), - ( - "= Prognostizierte jährliche Ausschüttung von @ 4,0%* = Prognostizierte Gesamtrendite (IRR) von 7,5%*", - {"entities": [[48, 52, "AUSSCHÜTTUNGSRENDITE"], [96, 100, "RENDITE"]]}, - ), - ( - "Prognose: 7,5%+ IRR auf Fondsebene", - {"entities": [[10, 14, "RENDITE"]]}, - ), - ( - "= Prognostizierte jährliche Ausschüttung* von 84,0% = Prognostizierte Gesamtrendite (IRR}* von 7,5%", - {"entities": [[96, 100, "RENDITE"], [49, 53, "AUSSCHÜTTUNGSRENDITE"]]}, - ), - ( - "= Lagefokussierung: Metropolregionen Deutschlands = Finanzierung: max. 20% LTV = Risikoprofil: Core, Core +", - {"entities": [[95, 107, "RISIKOPROFIL"]]}, - ), - ( - "Performance-Fee: 20% über einer @ Ausschüttungsrendite von 4,0%", - {"entities": [[61, 65, "AUSSCHÜTTUNGSRENDITE"]]}, - ), - ( - "Fondstyp Offener Spezial-AIF nach KAGB mit festen Anlagebedingungen ESG-Klassifizierung Fonds gemäß Artikel 8 EU-Offenlegungsverordnung KVG IntReal GmbH, Hamburg Anlagestrategie Aufbau eines Objektportfolios aus Ärztehäusern, die langfristig vermietet sind Ärztehäuser, Laborimmobilien, im Verbund mit Ärztehäusern auch ambulant Zielobjekte betreute Wohngemeinschaften; Mietanteil Medizin und medizinnahe Dienstleistungen/Handel > 65 % (Objektebene) WALT >5 Jahre bei Ankauf Objektbaujahre Ab 2000 Anlagegrenzen Einzelinvestment 8-30 Mio. EUR Anzahl Objekte 10-20 Deutschland bundesweit; jeweiliges Einzugsgebiet > 25.000 Einwohner mit Regionen stabiler Bevölkerungsprognose Risikoprofil Core / Core +", - {"entities": [[689, 702, "RISIKOPROFIL"]]}, - ), - ( - "Fondsvolumen 300 Mio. EUR Zielrendite (IRR) > 6,0 % p. a. Ausschuttung >5,0 % p. a. Ankaufszeitraum 2024-2026 Laufzeit 31.12.2036 Mindestanlage 10 Mio. EUR Anlageausschuss Ja, entscheidet u. a. über Objekterwerb (Mitglied kann ab 20 Mio. EUR gestellt werden) Gebührenstruktur Marktüblich (auf Anfrage) Projektentwicklungen keine Forward-Deals Möglich, maximal 18 Monate Vorlauf; keine Projektentwicklungsrisiken beim Fonds Erbbaurechte Möglich, sofern Laufzeit > 60 Jahre und angemessene Entschädigung bei Ablauf und Heimfall Status Objektpipeline vorhanden: siehe Folie 16 ff.", - {"entities": [[44, 57, "RENDITE"], [71, 83, "AUSSCHÜTTUNGSRENDITE"], [120, 130, "LAUFZEIT"]]}, - ), - ( - "Niederlande (max. 35 %) Länderallokation Frankreich (max. 35 %) (in % vom Zielvolumen) Skandinavien (Schweden, Dänemark) (max. 35 %) Deutschland (<= 10 %)", - {"entities": [[0, 23, "LÄNDERALLOKATION"], [41, 63, "LÄNDERALLOKATION"], [87, 132, "LÄNDERALLOKATION"], [133, 154, "LÄNDERALLOKATION"]]}, - ), - ( - "Führender Immobilien-Investmentmanager in den Nordics für globale ll institutionelle Investoren in Value Add und Core Strategien", - {"entities": [[101, 119, "RISIKOPROFIL"]]}, - ), - ( - "Core und Core+ Fonds", - {"entities": [[0, 14, "RISIKOPROFIL"]]}, - ), - ( - "Risikoprofil Core / Core+", - {"entities": [[13, 25, "RISIKOPROFIL"]]}, - ), - ( - "Durchschnittlich geplante jährliche Ausschüttung von 4,5-5,5% auf das investierte Eigenkapital an die Anleger Geplante Gesamtrendite von 5-6% (IRR) auf das eingezahlte Eigenkapital", - {"entities": [[54, 62, "AUSSCHÜTTUNGSRENDITE"], [138, 142, "RENDITE"]]}, - ), - ( - "Geografische Zielallokation nach Investitionsphase des Fonds: 1) Schweden 20-60% Allokation Länder 2) Finnland 20-60% 3) Norwegen 10-40% 4) Dänemark 10-40%", - {"entities": [[65, 80, "LÄNDERALLOKATION"], [102, 117, "LÄNDERALLOKATION"], [121, 136, "LÄNDERALLOKATION"], [140, 155, "LÄNDERALLOKATION"]]}, - ), - ( - "Deutsches Spezial-Sondervermögen mit festen Anlagebedingungen ($284 KAGB) Immobilien- oder Infrastrukturquote (nach Solvency II) Core / Core+ Euro Hauptstadtregionen und andere Großstädte in den Nordics €500 Mio. 4,5-5,5% 15 Jahre; Fonds hat unbegrenzte Laufzeit; Investmentphase 4 Jahre Maximaler Fremdkapitalanteil 50% (LTV-Ziel bei Ankauf), Langfristiges LTV-Ziel auf Fondsebene ist 45% 0,625% p. a. des Bruttofondsvermögens Zeichnungen ab € 30 Mio. - 0,03 % Rabatt Zeichnungen ab € 50 Mio. - zusatzl. 0,03 % Rabatt 1,1% des Verkehrswertes 0,6% der Bruttoverkaufswert 10% wenn Hurdle Rate 5,0 % p. a. (IRR netto) überschritten wird (nach 15 Jahren berechnet) Ja", - {"entities": [[129, 141, "RISIKOPROFIL"], [213, 221, "ZIELRENDITE"], [242, 262, "LAUFZEIT"]]}, - ), - ( - "Standort Helsinki, Finnland Sektor Bildungswesen, Schule& Kindertagesstätte Vermietbare Fläche 3.321 m? Leerstand bei Ankauf 0% / 0% Ankaufspreis+ Investitionen €21,4 Mio. + €0,2 Mio Eigenkapital €21,6 Mio. Ankaufs- / Stabilisierungs- / Exitrendite 5,0%/ 5,5%/ 5,0% NOI zum Ankaufszeitpunkt / Exit-NOI €1.1m/ €1.2m Zielrenditen (netto für LPs) 5,4% IRR/ 1.5x EM / DY 4,3% Ankauf / Exit Dezember 2023/ Dezember 2033", - {"entities": [[345, 349, "ZIELRENDITE"]]}, - ), - ( - "Evergreen/offene Fondsstrukturenv Core / Core+ Strategien", - {"entities": [[34, 46, "RISIKOPROFIL"]]}, - ), - ( - "BEE Henderson German 2012 Logistik Core/D/Art. 8 € 336 Mio. 12 (voll investiert) 13,0 % p.a.", - {"entities": [[35, 39, "RISIKOPROFIL"], [81, 87, "RENDITE"]]}, - ), - ( - "ICF German Logistics 2014 Logistik Core/D/Art. 8 € 400 Mio. 16 (voll investiert) 12,0 % p.a.", - {"entities": [[35, 39, "RISIKOPROFIL"], [81, 87, "RENDITE"]]}, - ), - ( - "Individualmandat 2015 Logistik Core / D+AU/ ArTt. 6 € 200 Mio. 8 (realisiert) 8,0 % p.a.", - {"entities": [[31, 35, "RISIKOPROFIL"], [78, 83, "RENDITE"]]}, - ), - ( - "European Logistics Partnership” 2017 Logistik Value-Add / Europ/a - € 1.000 Mio. 28 (realisiert) 20,0 % p.a.", - {"entities": [[46, 55, "RISIKOPROFIL"], [97, 103, "RENDITE"]]}, - ), - ( - "European Core Logistics Fund (ECLF 1) 2021 Logistik Core / Euro/p Arat. 8 € 314 Mio. 12 (voll investiert) 7,50 % p.a.", - {"entities": [[9, 13, "RISIKOPROFIL"], [106, 112, "RENDITE"]]}, - ), - ( - "P-Logistik Europa Fonds (ECLF 2) 2022 Logistik Core / Euro/p Arat. 8 € 150 Mio.? A (voll investiert) 6,5 % p.a.?", - {"entities": [[47, 51, "RISIKOPROFIL"], [101, 106, "RENDITE"]]}, - ), - ( - "First Business Parks 2015 Light Industrial Value Add / D+AUT € 100 Mio. 6 (realisiert) 16,0 % p.a.", - {"entities": [[43, 52, "RISIKOPROFIL"], [87, 93, "RENDITE"]]}, - ), - ( - "Unternehmensimmobilien Club 1 2016 Light Industrial Core+/D € 186 Mio. 9 (voll investiert) 13,0 % p.a.", - {"entities": [[91, 97, "RENDITE"]]}, - ), - ( - "Unternehmensimmobilien Club 1 2016 Light Industrial Core+/D € 186 Mio. 9 (voll investiert) 13,0 % p.a.", - {"entities": [[52, 57, "RISIKOPROFIL"], [91, 97, "RENDITE"]]}, - ), - ( - "Unternehmensimmobilien Club 2 2021 Light Industrial Core+/D € 262 Mio. 12 (voll investiert) 9,00 % p.a.", - {"entities": [[52, 57, "RISIKOPROFIL"], [92, 98, "RENDITE"]]}, - ), - ( - "Individualmandat 2022 Light Industrial Value-Add / Nordics € 100 Mio. 5 (voll investiert) 18,0 % p.a.", - {"entities": [[39, 48, "RISIKOPROFIL"], [90, 96, "RENDITE"]]}, - ), - ( - "EUROPEAN CORE LOGISTICS FUND 3", - {"entities": [[9, 13, "RISIKOPROFIL"]]}, - ), - ( - "Core Investitionen", - {"entities": [[0, 4, "RISIKOPROFIL"]]}, - ), - ( - "8 % IRR", - {"entities": [[0, 3, "RENDITE"]]}, - ), - ( - "Rendite-Risiko-Profil Core ° Geographischer Fokus Kontinentaleuropaische Kernvolkswirtschaften nach Allokationsprofil * Sektoraler Fokus Logistikimmobilien nach Allokationsprofil Kapitalstruktur ° Eigenkapital € 250 Mio. ° Fremdkapital 50 % angestrebt, max. 60 % der Immobilienwerte (Objektebene) °e Mindestzeichnung € 10 Mio. Vehikelstruktur ° Rechtsform Immobilien-Spezial-AlF mit festen Anlagebedingungen nach 3 284 KAGB ° Klassifikation Artikel 8 Offenlegungsverordnung ¢ Anlagehorizont 10 Jahre mit Verlängerungsoption um 2 Jahre! ° Geplante Auflage 01 2025 Performanceziel? ° Ausschüttung 6,0 % p.a. (Durchschnitt 10 Jahre Haltedauer) ° Interner Zinsfuß (IRR) 8,0 % p.a. (10 Jahre Haltedauer, Target-IRR)", - {"entities": [[22, 26, "RISIKOPROFIL"], [596, 601, "AUSSCHÜTTUNGSRENDITE"], [667, 672, "RENDITE"]]}, - ), - ( - "Core/Core+, mit Cash-Flow-Stabilität", - {"entities": [[0, 10, "RISIKOPROFIL"]]}, - ), - ( - "Zielausschüttung: min. 5,10%", - {"entities": [[24, 29, "ZIELAUSSCHÜTTUNG"]]}, - ), - ( - "Zielrendite (IRR): min. 5,50%", - {"entities": [[24, 29, "ZIELRENDITE"]]}, - ), - ( - "Rewe & Lidl Maxhütte-Haidhof é ae: 6 s Bahnhof Ankermieter REWE & Lidl er WALT 20 und 17 Jahre Miete p.a. 1.127.916 € Kaufpreis 21,43 Mio. € Faktor 19,00 x LTV / Zins 80% / 4,0% Ausschüttung 5,7 % IRR 7,1%", - {"entities": [[193, 198, "AUSSCHÜTTUNGSRENDITE"], [203, 207, "ZIELRENDITE"]]}, - ), - ( - "Real Estate Prime Europe Access the Core of European Prime Cities with a green SRI fund including a genuine low carbon commitment", - {"entities": [[36, 40, "RISIKOPROFIL"]]}, - ), - ( - "(FR, UK, DE, BE, NL, LU, Nordics, Allocation SP, IT, CH)", - {"entities": [[1, 32, "LÄNDERALLOKATION"], [45, 55, "LÄNDERALLOKATION"]]}, - ), - ( - "IRR: 6% - 7%", - {"entities": [[5, 12, "RENDITE"]]}, - ), - ( - "Europe | Germany 67 Value Add", - {"entities": [[9, 16, "LÄNDERALLOKATION"], [20, 29, "RISIKOPROFIL"]]}, - ), - ( - "Germany, Norway 336 Core Plus", - {"entities": [[0, 7, "LÄNDERALLOKATION"], [20, 29, "RISIKOPROFIL"]]}, - ), - ( - "UK", - {"entities": [[0, 2, "LÄNDERALLOKATION"]]}, - ), - ( - "NORWAY", - {"entities": [[0, 6, "LÄNDERALLOKATION"]]}, - ), - ( - "9.8% IRR", - {"entities": [[0, 4, "RENDITE"]]}, - ), - ( - "Investment volume down 52% to €2.3 billion, with 4,000 100 14% value-add and core-plus increasing YoY", - {"entities": [[63, 86, "RISIKOPROFIL"]]}, - ), - ( - "Geared Gross IRR‘ seeking a range of 16-18% per annum", - {"entities": [[37, 43, "RENDITE"]]}, - ), - ( - "Open-ended fund 24 months, incl. rolling reinvestment Sale of individual assets with respective management contracts or geared leases IRR: >6.5% | CoC: >5.0%", - {"entities": [[0, 10, "LAUFZEIT"], [139, 144, "RENDITE"]]}, - ), - ( - "Our investment strategy focuses on investing in upscale hotels in European prime locations, including DACH, Italy, Spain, Portugal, France, UK, Denmark, Benelux,and Poland.", - {"entities": [[102, 171, "LÄNDERALLOKATION"]]}, - ), - ( - "Core+ assets with value-add potential, Emerging Gateway Cities Helsinki] Core+ with Value well-mitigated risk and great upside Potential potential through asset improvement or = Max. 20% UK & Ireland {no contract renegotiation currency risk hedging], 80% tinental E > IRR target of 6-9%", - {"entities": [[0, 5, "RISIKOPROFIL"], [282, 286, "RENDITE"]]}, - ), - ( - "10% net IRR since inception in 2018?", - {"entities": [[0, 3, "RENDITE"]]}, - ), - ( - "Eurozone: Benelux, France and Germany", - {"entities": [[10, 37, "LÄNDERALLOKATION"]]}, - ), - ( - "Open-ended, with quarterly liquidity (redemption rights, dual pricing)", - {"entities": [[0, 10, "LAUFZEIT"]]}, - ), - ( - "Class A & B (Institutional): 0.93% on NAV; Class D (Wholesale): 1.80% on NAV; Class P (Wholesale): 1.25% on NAV", - {"entities": [[29, 34, "MANAGMENTGEBÜHREN"], [64, 69, "MANAGMENTGEBÜHREN"], [99, 104, "MANAGMENTGEBÜHREN"]]}, - ), - ( - "Risk profile: favour core > © at least and core+ assets with a targeted N 2 n allocation to value add assets to enhance returns", - {"entities": [[21, 25, "RISIKOPROFIL"], [43, 48, "RISIKOPROFIL"]]}, - ), - ( - "The Netherlands (38 assets) = Germany (9 assets) 10 largest Country assets split France (8 assets)", - {"entities": [[0, 15, "LÄNDERALLOKATION"], [30, 37, "LÄNDERALLOKATION"], [81, 87, "LÄNDERALLOKATION"]]}, - ), - ( - "Expected IRR 10.9%", - {"entities": [[13, 18, "ZIELRENDITE"]]}, - ), - ( - "Structure Open-end, perpetual life, Luxembourg domiciled Initial Target Size* €2 billion 6-8% total return,", - {"entities": [[10, 18, "LAUFZEIT"], [89, 93, "RENDITE"]]}, - ), - ( - "Geographic Focus: UK, Ireland, Iberia, Nordics, Netherlands, Germany, France, Italy", - {"entities": [[18, 83, "LÄNDERALLOKATION"]]}, - ), - ( - "IRR of 13-14%", - {"entities": [[7, 13, "RENDITE"]]}, - ), - ( - "Value-add", - {"entities": [[0, 9, "RISIKOPROFIL"]]}, - ), - ( - "Geographic allocation NORDICS UNITED KINGDOM GERMANY FRANCE PORTUGAL BENELUX", - {"entities": [[22, 76, "LÄNDERALLOKATION"]]}, - ), - ( - "Strong track record delivering a 17% net IRR, 1.7x net multiple across all divested assets (both discretionary and non-discretionary mandates)", - {"entities": [[33, 36, "RENDITE"]]}, - ), - ( - "Targeting a 7-8% net annual return and a 3-4% dividend yield, reflecting a target LTV of 35% (capped at 37.5%)", - {"entities": [[12, 16, "RENDITE"]]}, - ), - ( - "Sweden Norway Denmark Finland", - {"entities": [[0, 29, "LÄNDERALLOKATION"]]}, - ), - ( - "Logistics Residential Office Other", - {"entities": [[0, 34, "SEKTORENALLOKATION"]]}, - ), - ( - "Fund Term Open-ended with an initial 24-month lock-in for new investors", - {"entities": [[10, 20, "LAUFZEIT"]]}, - ), - ( - "Management fee of 85 bps on NAV.", - {"entities": [[18, 24, "MANAGMENTGEBÜHREN"]]}, - ), - ( - "Core/Core+ strategy, with tactical exposure to development projects aiming at enhancing the quality of the portfolio over time", - {"entities": [[0, 10, "RISIKOPROFIL"]]}, - ), - ( - "Fund term: Open-ended", - {"entities": [[11, 21, "LAUFZEIT"]]}, - ), - ( - "Return targets: The fund targets a net internal rate of return (IRR) of 8% and a net annual income yield of 5% with planned quarterly distributions’.", - {"entities": [[72, 74, "RENDITE"]]}, - ), - ( - "Geographic scope: The fund has a broad mandate to invest in commercial and residential real estate across Sweden, Denmark, Finland, and Norway. 50% LTV Asset selection: Heirs to acquire high-quality, income-generating properties in major Nordic cities and enhance their value through active asset management. Portfolio construction: The goal is to build diversified portfolios that are appealing to core buyers upon exit.", - {"entities": [[106, 142, "LÄNDERALLOKATION"]]}, - ), - ( - "Experience: Since 2012, | | has demonstrated its capability to build diversified and resilient portfolios for its core-plus funds. German Real Estate Quota advantage . Local expertise: extensive local relationships and proprietary deal flow in key Nordic markets provide a strategic advantage.", - {"entities": [[114, 123, "RISIKOPROFIL"]]}, - ), - ( - "Target returns: 8% net IRR with 5% net annual income yield! * Geographic focus: Sweden, Denmark, Norway and Finland « Target leverage: 50% LTV (excluding short-term borrowing) « Sector exposure: office, logistics, public properties, retail (focused on grocery anchored and necessity driven retail) and residentials « Investment focus: high quality properties,", - {"entities": [[16, 18, "RENDITE"], [80, 115, "LÄNDERALLOKATION"], [195, 239, "SEKTORENALLOKATION"]]}, - ), - ( - "The Fund 2 xemoours common limited partnership (SCS) (SICAV-RAIF) Investment Objective To pursue investments in commercial and residential properties throughout the Nordic Region Fund Target Size €300 million (equity) Return Targets Target net IRR of 8%, target net annual income yield of 5%", - {"entities": [[251, 253, "RENDITE"]]}, - ) - -] - - - - diff --git a/project/backend/spacy-service/spacy_training/training_model.py b/project/backend/spacy-service/spacy_training/training_model.py deleted file mode 100644 index 0ac3a1a..0000000 --- a/project/backend/spacy-service/spacy_training/training_model.py +++ /dev/null @@ -1,40 +0,0 @@ -import os -from pathlib import Path - -import spacy -from spacy.cli.train import train - -from spacy.tokens import DocBin - -from tqdm import tqdm - -from training_data import TRAINING_DATA - -nlp = spacy.blank("de") - -# create a DocBin object -db = DocBin() - -for text, annot in tqdm(TRAINING_DATA): - doc = nlp.make_doc(text) - ents = [] - # add character indexes - for start, end, label in annot["entities"]: - span = doc.char_span(start, end, label=label, alignment_mode="contract") - if span is None: - print(f"Skipping entity: |{text[start:end]}| Start: {start}, End: {end}, Label: {label}") - else: - ents.append(span) - # label the text with the ents - doc.ents = ents - db.add(doc) - -# save the DocBin object -os.makedirs("./data", exist_ok=True) -db.to_disk("./data/train.spacy") - -config_path = Path("config.cfg") -output_path = Path("output") - -print("Starte Training...") -train(config_path, output_path) diff --git a/project/backend/spacy-service/spacy_training/training_running.json b/project/backend/spacy-service/spacy_training/training_running.json new file mode 100644 index 0000000..ef4cde9 --- /dev/null +++ b/project/backend/spacy-service/spacy_training/training_running.json @@ -0,0 +1 @@ +{"running": false} \ No newline at end of file diff --git a/project/backend/validate-service/app.py b/project/backend/validate-service/app.py index 693c032..ccd6b53 100644 --- a/project/backend/validate-service/app.py +++ b/project/backend/validate-service/app.py @@ -40,7 +40,9 @@ def send_to_coordinator_service(processed_data, request_id): def process_data_async(request_id, spacy_data, exxeta_data): try: - requests.post(COORDINATOR_URL + "/api/progress", json={"id": request_id, "progress": 95}) + requests.post( + COORDINATOR_URL + "/api/progress", json={"id": request_id, "progress": 95} + ) print(f"Start asynchronous processing for PitchBook: {request_id}") # Perform merge @@ -96,7 +98,6 @@ def validate(): # If both datasets are present, start asynchronous processing if spacy_data is not None and exxeta_data is not None: - # Start asynchronous processing in a separate thread processing_thread = threading.Thread( target=process_data_async, diff --git a/project/backend/validate-service/merge_logic.py b/project/backend/validate-service/merge_logic.py index 1bc404c..5f4f7b7 100644 --- a/project/backend/validate-service/merge_logic.py +++ b/project/backend/validate-service/merge_logic.py @@ -27,7 +27,6 @@ def merge_entities(spacy_data, exxeta_data): and s_entity_norm == e_entity_norm and s_page == e_page ): - merged.append( { "label": s["label"], diff --git a/project/backend/validate-service/validate_logic.py b/project/backend/validate-service/validate_logic.py index 1e90d84..416e82c 100644 --- a/project/backend/validate-service/validate_logic.py +++ b/project/backend/validate-service/validate_logic.py @@ -5,6 +5,8 @@ import os # SETTINGS = [{"id": "Rendite", "type": "number"}] COORDINATOR_URL = os.getenv("COORDINATOR_URL", "http://localhost:5000") + + def validate_entities(entities): try: response = requests.get(COORDINATOR_URL + "/api/kpi_setting/") @@ -42,7 +44,6 @@ def validate_entities(entities): result.extend(item[1]) continue - # Filter not validated, if there are valid values validated = False for entity in item[1]: @@ -61,11 +62,11 @@ def validate_entities(entities): def validate_number(entity_list, settings): filtered_kpi = {} for label, entity_list in entity_list.items(): - setting = next((s for s in settings if s["name"].upper() == label), None) if setting and setting["type"] == "number": filtered_entities = [ - entity for entity in entity_list + entity + for entity in entity_list if is_valid_number(str(entity["entity"])) ] for entity in entity_list: @@ -80,8 +81,12 @@ def validate_number(entity_list, settings): def is_valid_number(number): - pattern = r'^[0-9\-\s%,.€]+$' - return any(char.isdigit() for char in number) and not re.search(r'\d+\s\d+', number) and re.fullmatch(pattern, number) + pattern = r"^[0-9\-\s%,.€]+$" + return ( + any(char.isdigit() for char in number) + and not re.search(r"\d+\s\d+", number) + and re.fullmatch(pattern, number) + ) def delete_exxeta_unknown(entity_list): @@ -89,11 +94,16 @@ def delete_exxeta_unknown(entity_list): for label, entity_list in entity_list.items(): # Filter out entities with "nichtangegeben" or "n/a" (case-insensitive and stripped) filtered_entities = [ - entity for entity in entity_list - if str(entity["entity"]).lower().replace(" ", "") not in {"nichtangegeben", "n/a"} + entity + for entity in entity_list + if str(entity["entity"]).lower().replace(" ", "") + not in {"nichtangegeben", "n/a"} ] for entity in entity_list: - if str(entity["entity"]).lower().replace(" ", "") in {"nichtangegeben", "n/a"}: + if str(entity["entity"]).lower().replace(" ", "") in { + "nichtangegeben", + "n/a", + }: print(f"filtered out: {entity}") if filtered_entities: # Only add the label if there are entities left filtered_kpi[label] = filtered_entities @@ -115,6 +125,7 @@ def delete_duplicate_entities(entity_list): unique_entities[label] = filtered_entities return unique_entities + if __name__ == "__main__": entities = [ # {"label": "PERSON", "entity": "John Doe", "status": "validated"}, diff --git a/project/docker-compose.yml b/project/docker-compose.yml index 5c1f337..1c5a848 100644 --- a/project/docker-compose.yml +++ b/project/docker-compose.yml @@ -58,6 +58,8 @@ services: - VALIDATE_SERVICE_URL=http://validate:5000/validate ports: - 5052:5052 + volumes: + - ./backend/spacy-service/spacy_training:/app/spacy_training exxeta: build: diff --git a/project/frontend/Dockerfile b/project/frontend/Dockerfile index 69ae868..9fa6707 100644 --- a/project/frontend/Dockerfile +++ b/project/frontend/Dockerfile @@ -4,7 +4,9 @@ WORKDIR /usr/src/app # install dependencies into temp directory # this will cache them and speed up future builds COPY package.json bun.lockb ./ -RUN bun install --frozen-lockfile +#RUN bun install --frozen-lockfile +RUN bun install + COPY . . diff --git a/project/frontend/package-lock.json b/project/frontend/package-lock.json new file mode 100644 index 0000000..19d192b --- /dev/null +++ b/project/frontend/package-lock.json @@ -0,0 +1,6335 @@ +{ + "name": "frontend", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "frontend", + "dependencies": { + "@emotion/react": "^11.14.0", + "@emotion/styled": "^11.14.0", + "@fontsource/roboto": "^5.2.5", + "@mui/icons-material": "^7.1.0", + "@mui/material": "^7.1.0", + "@tanstack/react-query": "^5.66.5", + "@tanstack/react-query-devtools": "^5.66.5", + "@tanstack/react-router": "^1.114.3", + "@tanstack/react-router-devtools": "^1.114.3", + "@tanstack/router-plugin": "^1.114.3", + "file-saver": "^2.0.5", + "react": "^19.0.0", + "react-dom": "^19.0.0", + "react-material-file-upload": "^0.0.4", + "react-pdf": "^8.0.2", + "socket.io-client": "^4.8.1" + }, + "devDependencies": { + "@biomejs/biome": "1.9.4", + "@testing-library/dom": "^10.4.0", + "@testing-library/react": "^16.2.0", + "@types/file-saver": "^2.0.7", + "@types/react": "^19.0.8", + "@types/react-dom": "^19.0.3", + "@vitejs/plugin-react": "^4.3.4", + "jsdom": "^26.0.0", + "typescript": "^5.7.2", + "vite": "^6.1.0", + "vitest": "^3.0.5" + } + }, + "node_modules/@ampproject/remapping": { + "version": "2.3.0", + "license": "Apache-2.0", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@asamuzakjp/css-color": { + "version": "3.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@csstools/css-calc": "^2.1.3", + "@csstools/css-color-parser": "^3.0.9", + "@csstools/css-parser-algorithms": "^3.0.4", + "@csstools/css-tokenizer": "^3.0.3", + "lru-cache": "^10.4.3" + } + }, + "node_modules/@asamuzakjp/css-color/node_modules/lru-cache": { + "version": "10.4.3", + "dev": true, + "license": "ISC" + }, + "node_modules/@babel/code-frame": { + "version": "7.27.1", + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.27.1", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.27.3", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.27.3", + "license": "MIT", + "dependencies": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.27.1", + "@babel/generator": "^7.27.3", + "@babel/helper-compilation-targets": "^7.27.2", + "@babel/helper-module-transforms": "^7.27.3", + "@babel/helpers": "^7.27.3", + "@babel/parser": "^7.27.3", + "@babel/template": "^7.27.2", + "@babel/traverse": "^7.27.3", + "@babel/types": "^7.27.3", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/core/node_modules/convert-source-map": { + "version": "2.0.0", + "license": "MIT" + }, + "node_modules/@babel/generator": { + "version": "7.27.3", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.27.3", + "@babel/types": "^7.27.3", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.27.2", + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.27.2", + "@babel/helper-validator-option": "^7.27.1", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.27.1", + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.27.1", + "@babel/types": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.27.3", + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.27.1", + "@babel/helper-validator-identifier": "^7.27.1", + "@babel/traverse": "^7.27.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.27.1", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.27.1", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.27.1", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.27.1", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.27.3", + "license": "MIT", + "dependencies": { + "@babel/template": "^7.27.2", + "@babel/types": "^7.27.3" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.27.3", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.27.3" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.27.1", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-typescript": { + "version": "7.27.1", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-self": { + "version": "7.27.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-source": { + "version": "7.27.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/runtime": { + "version": "7.27.3", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/template": { + "version": "7.27.2", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@babel/parser": "^7.27.2", + "@babel/types": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.27.3", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@babel/generator": "^7.27.3", + "@babel/parser": "^7.27.3", + "@babel/template": "^7.27.2", + "@babel/types": "^7.27.3", + "debug": "^4.3.1", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.27.3", + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@biomejs/biome": { + "version": "1.9.4", + "dev": true, + "hasInstallScript": true, + "license": "MIT OR Apache-2.0", + "bin": { + "biome": "bin/biome" + }, + "engines": { + "node": ">=14.21.3" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/biome" + }, + "optionalDependencies": { + "@biomejs/cli-darwin-arm64": "1.9.4", + "@biomejs/cli-darwin-x64": "1.9.4", + "@biomejs/cli-linux-arm64": "1.9.4", + "@biomejs/cli-linux-arm64-musl": "1.9.4", + "@biomejs/cli-linux-x64": "1.9.4", + "@biomejs/cli-linux-x64-musl": "1.9.4", + "@biomejs/cli-win32-arm64": "1.9.4", + "@biomejs/cli-win32-x64": "1.9.4" + } + }, + "node_modules/@biomejs/cli-win32-x64": { + "version": "1.9.4", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@csstools/color-helpers": { + "version": "5.0.2", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "engines": { + "node": ">=18" + } + }, + "node_modules/@csstools/css-calc": { + "version": "2.1.4", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4" + } + }, + "node_modules/@csstools/css-color-parser": { + "version": "3.0.10", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "dependencies": { + "@csstools/color-helpers": "^5.0.2", + "@csstools/css-calc": "^2.1.4" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4" + } + }, + "node_modules/@csstools/css-parser-algorithms": { + "version": "3.0.5", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@csstools/css-tokenizer": "^3.0.4" + } + }, + "node_modules/@csstools/css-tokenizer": { + "version": "3.0.4", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@emotion/babel-plugin": { + "version": "11.13.5", + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.16.7", + "@babel/runtime": "^7.18.3", + "@emotion/hash": "^0.9.2", + "@emotion/memoize": "^0.9.0", + "@emotion/serialize": "^1.3.3", + "babel-plugin-macros": "^3.1.0", + "convert-source-map": "^1.5.0", + "escape-string-regexp": "^4.0.0", + "find-root": "^1.1.0", + "source-map": "^0.5.7", + "stylis": "4.2.0" + } + }, + "node_modules/@emotion/cache": { + "version": "11.14.0", + "license": "MIT", + "dependencies": { + "@emotion/memoize": "^0.9.0", + "@emotion/sheet": "^1.4.0", + "@emotion/utils": "^1.4.2", + "@emotion/weak-memoize": "^0.4.0", + "stylis": "4.2.0" + } + }, + "node_modules/@emotion/hash": { + "version": "0.9.2", + "license": "MIT" + }, + "node_modules/@emotion/is-prop-valid": { + "version": "1.3.1", + "license": "MIT", + "dependencies": { + "@emotion/memoize": "^0.9.0" + } + }, + "node_modules/@emotion/memoize": { + "version": "0.9.0", + "license": "MIT" + }, + "node_modules/@emotion/react": { + "version": "11.14.0", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.18.3", + "@emotion/babel-plugin": "^11.13.5", + "@emotion/cache": "^11.14.0", + "@emotion/serialize": "^1.3.3", + "@emotion/use-insertion-effect-with-fallbacks": "^1.2.0", + "@emotion/utils": "^1.4.2", + "@emotion/weak-memoize": "^0.4.0", + "hoist-non-react-statics": "^3.3.1" + }, + "peerDependencies": { + "react": ">=16.8.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@emotion/serialize": { + "version": "1.3.3", + "license": "MIT", + "dependencies": { + "@emotion/hash": "^0.9.2", + "@emotion/memoize": "^0.9.0", + "@emotion/unitless": "^0.10.0", + "@emotion/utils": "^1.4.2", + "csstype": "^3.0.2" + } + }, + "node_modules/@emotion/sheet": { + "version": "1.4.0", + "license": "MIT" + }, + "node_modules/@emotion/styled": { + "version": "11.14.0", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.18.3", + "@emotion/babel-plugin": "^11.13.5", + "@emotion/is-prop-valid": "^1.3.0", + "@emotion/serialize": "^1.3.3", + "@emotion/use-insertion-effect-with-fallbacks": "^1.2.0", + "@emotion/utils": "^1.4.2" + }, + "peerDependencies": { + "@emotion/react": "^11.0.0-rc.0", + "react": ">=16.8.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@emotion/unitless": { + "version": "0.10.0", + "license": "MIT" + }, + "node_modules/@emotion/use-insertion-effect-with-fallbacks": { + "version": "1.2.0", + "license": "MIT", + "peerDependencies": { + "react": ">=16.8.0" + } + }, + "node_modules/@emotion/utils": { + "version": "1.4.2", + "license": "MIT" + }, + "node_modules/@emotion/weak-memoize": { + "version": "0.4.0", + "license": "MIT" + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.25.5", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@fontsource/roboto": { + "version": "5.2.5", + "license": "OFL-1.1", + "funding": { + "url": "https://github.com/sponsors/ayuhito" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.8", + "license": "MIT", + "dependencies": { + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.2.1", + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.0", + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@mapbox/node-pre-gyp": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz", + "integrity": "sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==", + "optional": true, + "dependencies": { + "detect-libc": "^2.0.0", + "https-proxy-agent": "^5.0.0", + "make-dir": "^3.1.0", + "node-fetch": "^2.6.7", + "nopt": "^5.0.0", + "npmlog": "^5.0.1", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.11" + }, + "bin": { + "node-pre-gyp": "bin/node-pre-gyp" + } + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "optional": true, + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "optional": true, + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/semver": { + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "optional": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@mui/core-downloads-tracker": { + "version": "7.1.0", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + } + }, + "node_modules/@mui/icons-material": { + "version": "7.1.0", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.27.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@mui/material": "^7.1.0", + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/material": { + "version": "7.1.0", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.27.1", + "@mui/core-downloads-tracker": "^7.1.0", + "@mui/system": "^7.1.0", + "@mui/types": "^7.4.2", + "@mui/utils": "^7.1.0", + "@popperjs/core": "^2.11.8", + "@types/react-transition-group": "^4.4.12", + "clsx": "^2.1.1", + "csstype": "^3.1.3", + "prop-types": "^15.8.1", + "react-is": "^19.1.0", + "react-transition-group": "^4.4.5" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@emotion/react": "^11.5.0", + "@emotion/styled": "^11.3.0", + "@mui/material-pigment-css": "^7.1.0", + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@emotion/react": { + "optional": true + }, + "@emotion/styled": { + "optional": true + }, + "@mui/material-pigment-css": { + "optional": true + }, + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/private-theming": { + "version": "7.1.0", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.27.1", + "@mui/utils": "^7.1.0", + "prop-types": "^15.8.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/styled-engine": { + "version": "7.1.0", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.27.1", + "@emotion/cache": "^11.13.5", + "@emotion/serialize": "^1.3.3", + "@emotion/sheet": "^1.4.0", + "csstype": "^3.1.3", + "prop-types": "^15.8.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@emotion/react": "^11.4.1", + "@emotion/styled": "^11.3.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@emotion/react": { + "optional": true + }, + "@emotion/styled": { + "optional": true + } + } + }, + "node_modules/@mui/system": { + "version": "7.1.0", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.27.1", + "@mui/private-theming": "^7.1.0", + "@mui/styled-engine": "^7.1.0", + "@mui/types": "^7.4.2", + "@mui/utils": "^7.1.0", + "clsx": "^2.1.1", + "csstype": "^3.1.3", + "prop-types": "^15.8.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@emotion/react": "^11.5.0", + "@emotion/styled": "^11.3.0", + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@emotion/react": { + "optional": true + }, + "@emotion/styled": { + "optional": true + }, + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/types": { + "version": "7.4.2", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.27.1" + }, + "peerDependencies": { + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/utils": { + "version": "7.1.0", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.27.1", + "@mui/types": "^7.4.2", + "@types/prop-types": "^15.7.14", + "clsx": "^2.1.1", + "prop-types": "^15.8.1", + "react-is": "^19.1.0" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@popperjs/core": { + "version": "2.11.8", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/popperjs" + } + }, + "node_modules/@rolldown/pluginutils": { + "version": "1.0.0-beta.9", + "dev": true, + "license": "MIT" + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.41.1", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@socket.io/component-emitter": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz", + "integrity": "sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==" + }, + "node_modules/@tanstack/history": { + "version": "1.115.0", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } + }, + "node_modules/@tanstack/query-core": { + "version": "5.77.2", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } + }, + "node_modules/@tanstack/query-devtools": { + "version": "5.76.0", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } + }, + "node_modules/@tanstack/react-query": { + "version": "5.77.2", + "license": "MIT", + "dependencies": { + "@tanstack/query-core": "5.77.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "react": "^18 || ^19" + } + }, + "node_modules/@tanstack/react-query-devtools": { + "version": "5.77.2", + "license": "MIT", + "dependencies": { + "@tanstack/query-devtools": "5.76.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "@tanstack/react-query": "^5.77.2", + "react": "^18 || ^19" + } + }, + "node_modules/@tanstack/react-router": { + "version": "1.120.11", + "license": "MIT", + "dependencies": { + "@tanstack/history": "1.115.0", + "@tanstack/react-store": "^0.7.0", + "@tanstack/router-core": "1.120.10", + "jsesc": "^3.1.0", + "tiny-invariant": "^1.3.3", + "tiny-warning": "^1.0.3" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "react": ">=18.0.0 || >=19.0.0", + "react-dom": ">=18.0.0 || >=19.0.0" + } + }, + "node_modules/@tanstack/react-router-devtools": { + "version": "1.120.11", + "license": "MIT", + "dependencies": { + "@tanstack/router-devtools-core": "^1.120.10", + "solid-js": "^1.9.5" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "@tanstack/react-router": "^1.120.11", + "react": ">=18.0.0 || >=19.0.0", + "react-dom": ">=18.0.0 || >=19.0.0" + } + }, + "node_modules/@tanstack/react-store": { + "version": "0.7.0", + "license": "MIT", + "dependencies": { + "@tanstack/store": "0.7.0", + "use-sync-external-store": "^1.4.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/@tanstack/router-core": { + "version": "1.120.10", + "license": "MIT", + "dependencies": { + "@tanstack/history": "1.115.0", + "@tanstack/store": "^0.7.0", + "tiny-invariant": "^1.3.3" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } + }, + "node_modules/@tanstack/router-devtools-core": { + "version": "1.120.10", + "license": "MIT", + "dependencies": { + "clsx": "^2.1.1", + "goober": "^2.1.16" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "@tanstack/router-core": "^1.120.10", + "csstype": "^3.0.10", + "solid-js": ">=1.9.5", + "tiny-invariant": "^1.3.3" + }, + "peerDependenciesMeta": { + "csstype": { + "optional": true + } + } + }, + "node_modules/@tanstack/router-generator": { + "version": "1.120.11", + "license": "MIT", + "dependencies": { + "@tanstack/virtual-file-routes": "^1.115.0", + "prettier": "^3.5.0", + "tsx": "^4.19.2", + "zod": "^3.24.2" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "@tanstack/react-router": "^1.120.11" + }, + "peerDependenciesMeta": { + "@tanstack/react-router": { + "optional": true + } + } + }, + "node_modules/@tanstack/router-plugin": { + "version": "1.120.11", + "license": "MIT", + "dependencies": { + "@babel/core": "^7.26.8", + "@babel/plugin-syntax-jsx": "^7.25.9", + "@babel/plugin-syntax-typescript": "^7.25.9", + "@babel/template": "^7.26.8", + "@babel/traverse": "^7.26.8", + "@babel/types": "^7.26.8", + "@tanstack/router-core": "^1.120.10", + "@tanstack/router-generator": "^1.120.11", + "@tanstack/router-utils": "^1.115.0", + "@tanstack/virtual-file-routes": "^1.115.0", + "@types/babel__core": "^7.20.5", + "@types/babel__template": "^7.4.4", + "@types/babel__traverse": "^7.20.6", + "babel-dead-code-elimination": "^1.0.10", + "chokidar": "^3.6.0", + "unplugin": "^2.1.2", + "zod": "^3.24.2" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "@rsbuild/core": ">=1.0.2", + "@tanstack/react-router": "^1.120.11", + "vite": ">=5.0.0 || >=6.0.0", + "vite-plugin-solid": "^2.11.2", + "webpack": ">=5.92.0" + }, + "peerDependenciesMeta": { + "@rsbuild/core": { + "optional": true + }, + "@tanstack/react-router": { + "optional": true + }, + "vite": { + "optional": true + }, + "vite-plugin-solid": { + "optional": true + }, + "webpack": { + "optional": true + } + } + }, + "node_modules/@tanstack/router-utils": { + "version": "1.115.0", + "license": "MIT", + "dependencies": { + "@babel/generator": "^7.26.8", + "@babel/parser": "^7.26.8", + "ansis": "^3.11.0", + "diff": "^7.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } + }, + "node_modules/@tanstack/store": { + "version": "0.7.0", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } + }, + "node_modules/@tanstack/virtual-file-routes": { + "version": "1.115.0", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } + }, + "node_modules/@testing-library/dom": { + "version": "10.4.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.10.4", + "@babel/runtime": "^7.12.5", + "@types/aria-query": "^5.0.1", + "aria-query": "5.3.0", + "chalk": "^4.1.0", + "dom-accessibility-api": "^0.5.9", + "lz-string": "^1.5.0", + "pretty-format": "^27.0.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@testing-library/react": { + "version": "16.3.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.12.5" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@testing-library/dom": "^10.0.0", + "@types/react": "^18.0.0 || ^19.0.0", + "@types/react-dom": "^18.0.0 || ^19.0.0", + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@types/aria-query": { + "version": "5.0.4", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/babel__core": { + "version": "7.20.5", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.27.0", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.4", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.20.7", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.20.7" + } + }, + "node_modules/@types/estree": { + "version": "1.0.7", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/file-saver": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@types/file-saver/-/file-saver-2.0.7.tgz", + "integrity": "sha512-dNKVfHd/jk0SkR/exKGj2ggkB45MAkzvWCaqLUUgkyjITkGNzH8H+yUwr+BLJUBjZOe9w8X3wgmXhZDRg1ED6A==", + "dev": true + }, + "node_modules/@types/parse-json": { + "version": "4.0.2", + "license": "MIT" + }, + "node_modules/@types/prop-types": { + "version": "15.7.14", + "license": "MIT" + }, + "node_modules/@types/react": { + "version": "19.1.6", + "dev": true, + "license": "MIT", + "dependencies": { + "csstype": "^3.0.2" + } + }, + "node_modules/@types/react-dom": { + "version": "19.1.5", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@types/react": "^19.0.0" + } + }, + "node_modules/@types/react-transition-group": { + "version": "4.4.12", + "license": "MIT", + "peerDependencies": { + "@types/react": "*" + } + }, + "node_modules/@vitejs/plugin-react": { + "version": "4.5.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.26.10", + "@babel/plugin-transform-react-jsx-self": "^7.25.9", + "@babel/plugin-transform-react-jsx-source": "^7.25.9", + "@rolldown/pluginutils": "1.0.0-beta.9", + "@types/babel__core": "^7.20.5", + "react-refresh": "^0.17.0" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "peerDependencies": { + "vite": "^4.2.0 || ^5.0.0 || ^6.0.0" + } + }, + "node_modules/@vitest/expect": { + "version": "3.1.4", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/spy": "3.1.4", + "@vitest/utils": "3.1.4", + "chai": "^5.2.0", + "tinyrainbow": "^2.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/mocker": { + "version": "3.1.4", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/spy": "3.1.4", + "estree-walker": "^3.0.3", + "magic-string": "^0.30.17" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "msw": "^2.4.9", + "vite": "^5.0.0 || ^6.0.0" + }, + "peerDependenciesMeta": { + "msw": { + "optional": true + }, + "vite": { + "optional": true + } + } + }, + "node_modules/@vitest/pretty-format": { + "version": "3.1.4", + "dev": true, + "license": "MIT", + "dependencies": { + "tinyrainbow": "^2.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/runner": { + "version": "3.1.4", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/utils": "3.1.4", + "pathe": "^2.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/snapshot": { + "version": "3.1.4", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "3.1.4", + "magic-string": "^0.30.17", + "pathe": "^2.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/spy": { + "version": "3.1.4", + "dev": true, + "license": "MIT", + "dependencies": { + "tinyspy": "^3.0.2" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/utils": { + "version": "3.1.4", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "3.1.4", + "loupe": "^3.1.3", + "tinyrainbow": "^2.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "optional": true + }, + "node_modules/acorn": { + "version": "8.14.1", + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/agent-base": { + "version": "7.1.3", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/ansis": { + "version": "3.17.0", + "license": "ISC", + "engines": { + "node": ">=14" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "license": "ISC", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/aproba": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", + "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==", + "optional": true + }, + "node_modules/are-we-there-yet": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", + "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", + "deprecated": "This package is no longer supported.", + "optional": true, + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/aria-query": { + "version": "5.3.0", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "dequal": "^2.0.3" + } + }, + "node_modules/assertion-error": { + "version": "2.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + } + }, + "node_modules/attr-accept": { + "version": "2.2.5", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/babel-dead-code-elimination": { + "version": "1.0.10", + "license": "MIT", + "dependencies": { + "@babel/core": "^7.23.7", + "@babel/parser": "^7.23.6", + "@babel/traverse": "^7.23.7", + "@babel/types": "^7.23.6" + } + }, + "node_modules/babel-plugin-macros": { + "version": "3.1.0", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.12.5", + "cosmiconfig": "^7.0.0", + "resolve": "^1.19.0" + }, + "engines": { + "node": ">=10", + "npm": ">=6" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "optional": true + }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "optional": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.24.5", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "caniuse-lite": "^1.0.30001716", + "electron-to-chromium": "^1.5.149", + "node-releases": "^2.0.19", + "update-browserslist-db": "^1.1.3" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/cac": { + "version": "6.7.14", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001718", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/canvas": { + "version": "2.11.2", + "resolved": "https://registry.npmjs.org/canvas/-/canvas-2.11.2.tgz", + "integrity": "sha512-ItanGBMrmRV7Py2Z+Xhs7cT+FNt5K0vPL4p9EZ/UX/Mu7hFbkxSjKF2KVtPwX7UYWp7dRKnrTvReflgrItJbdw==", + "hasInstallScript": true, + "optional": true, + "dependencies": { + "@mapbox/node-pre-gyp": "^1.0.0", + "nan": "^2.17.0", + "simple-get": "^3.0.3" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/chai": { + "version": "5.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "assertion-error": "^2.0.1", + "check-error": "^2.1.1", + "deep-eql": "^5.0.1", + "loupe": "^3.1.0", + "pathval": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/check-error": { + "version": "2.1.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 16" + } + }, + "node_modules/chokidar": { + "version": "3.6.0", + "license": "MIT", + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "optional": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/clsx": { + "version": "2.1.1", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "dev": true, + "license": "MIT" + }, + "node_modules/color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "optional": true, + "bin": { + "color-support": "bin.js" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "optional": true + }, + "node_modules/console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==", + "optional": true + }, + "node_modules/convert-source-map": { + "version": "1.9.0", + "license": "MIT" + }, + "node_modules/cosmiconfig": { + "version": "7.1.0", + "license": "MIT", + "dependencies": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.2.1", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.10.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/cssstyle": { + "version": "4.3.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@asamuzakjp/css-color": "^3.1.2", + "rrweb-cssom": "^0.8.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/csstype": { + "version": "3.1.3", + "license": "MIT" + }, + "node_modules/data-urls": { + "version": "5.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "whatwg-mimetype": "^4.0.0", + "whatwg-url": "^14.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/debug": { + "version": "4.4.1", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decimal.js": { + "version": "10.5.0", + "dev": true, + "license": "MIT" + }, + "node_modules/decompress-response": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-4.2.1.tgz", + "integrity": "sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw==", + "optional": true, + "dependencies": { + "mimic-response": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/deep-eql": { + "version": "5.0.2", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", + "optional": true + }, + "node_modules/dequal": { + "version": "2.0.3", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/detect-libc": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.4.tgz", + "integrity": "sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/diff": { + "version": "7.0.0", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/dom-accessibility-api": { + "version": "0.5.16", + "dev": true, + "license": "MIT" + }, + "node_modules/dom-helpers": { + "version": "5.2.1", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.8.7", + "csstype": "^3.0.2" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.5.159", + "license": "ISC" + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "optional": true + }, + "node_modules/engine.io-client": { + "version": "6.6.3", + "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.6.3.tgz", + "integrity": "sha512-T0iLjnyNWahNyv/lcjS2y4oE358tVS/SYQNxYXGAJ9/GLgH4VCvOQ/mhTjqU88mLZCQgiG8RIegFHYCdVC+j5w==", + "dependencies": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.3.1", + "engine.io-parser": "~5.2.1", + "ws": "~8.17.1", + "xmlhttprequest-ssl": "~2.1.1" + } + }, + "node_modules/engine.io-client/node_modules/debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/engine.io-client/node_modules/ws": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", + "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/engine.io-parser": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.3.tgz", + "integrity": "sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q==", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/entities": { + "version": "6.0.0", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/error-ex": { + "version": "1.3.2", + "license": "MIT", + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/es-module-lexer": { + "version": "1.7.0", + "dev": true, + "license": "MIT" + }, + "node_modules/esbuild": { + "version": "0.25.5", + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.25.5", + "@esbuild/android-arm": "0.25.5", + "@esbuild/android-arm64": "0.25.5", + "@esbuild/android-x64": "0.25.5", + "@esbuild/darwin-arm64": "0.25.5", + "@esbuild/darwin-x64": "0.25.5", + "@esbuild/freebsd-arm64": "0.25.5", + "@esbuild/freebsd-x64": "0.25.5", + "@esbuild/linux-arm": "0.25.5", + "@esbuild/linux-arm64": "0.25.5", + "@esbuild/linux-ia32": "0.25.5", + "@esbuild/linux-loong64": "0.25.5", + "@esbuild/linux-mips64el": "0.25.5", + "@esbuild/linux-ppc64": "0.25.5", + "@esbuild/linux-riscv64": "0.25.5", + "@esbuild/linux-s390x": "0.25.5", + "@esbuild/linux-x64": "0.25.5", + "@esbuild/netbsd-arm64": "0.25.5", + "@esbuild/netbsd-x64": "0.25.5", + "@esbuild/openbsd-arm64": "0.25.5", + "@esbuild/openbsd-x64": "0.25.5", + "@esbuild/sunos-x64": "0.25.5", + "@esbuild/win32-arm64": "0.25.5", + "@esbuild/win32-ia32": "0.25.5", + "@esbuild/win32-x64": "0.25.5" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/estree-walker": { + "version": "3.0.3", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0" + } + }, + "node_modules/expect-type": { + "version": "1.2.1", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/fdir": { + "version": "6.4.5", + "dev": true, + "license": "MIT", + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/file-saver": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/file-saver/-/file-saver-2.0.5.tgz", + "integrity": "sha512-P9bmyZ3h/PRG+Nzga+rbdI4OEpNDzAVyy74uVO9ATgzLK6VtAsYybF/+TOCvrc0MO793d6+42lLyZTw7/ArVzA==" + }, + "node_modules/file-selector": { + "version": "0.4.0", + "license": "MIT", + "dependencies": { + "tslib": "^2.0.3" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-root": { + "version": "1.1.0", + "license": "MIT" + }, + "node_modules/fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "optional": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/fs-minipass/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "optional": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/fs-minipass/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "optional": true + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "optional": true + }, + "node_modules/function-bind": { + "version": "1.1.2", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gauge": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", + "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", + "deprecated": "This package is no longer supported.", + "optional": true, + "dependencies": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.2", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.1", + "object-assign": "^4.1.1", + "signal-exit": "^3.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-tsconfig": { + "version": "4.10.1", + "license": "MIT", + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "optional": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/globals": { + "version": "11.12.0", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/goober": { + "version": "2.1.16", + "license": "MIT", + "peerDependencies": { + "csstype": "^3.0.10" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==", + "optional": true + }, + "node_modules/hasown": { + "version": "2.0.2", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/hoist-non-react-statics": { + "version": "3.3.2", + "license": "BSD-3-Clause", + "dependencies": { + "react-is": "^16.7.0" + } + }, + "node_modules/hoist-non-react-statics/node_modules/react-is": { + "version": "16.13.1", + "license": "MIT" + }, + "node_modules/html-encoding-sniffer": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "whatwg-encoding": "^3.1.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/http-proxy-agent": { + "version": "7.0.2", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/https-proxy-agent": { + "version": "7.0.6", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/iconv-lite": { + "version": "0.6.3", + "dev": true, + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/import-fresh": { + "version": "3.3.1", + "license": "MIT", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "optional": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "optional": true + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "license": "MIT" + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "license": "MIT", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-core-module": { + "version": "2.16.1", + "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-potential-custom-element-name": { + "version": "1.0.1", + "dev": true, + "license": "MIT" + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "license": "MIT" + }, + "node_modules/jsdom": { + "version": "26.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "cssstyle": "^4.2.1", + "data-urls": "^5.0.0", + "decimal.js": "^10.5.0", + "html-encoding-sniffer": "^4.0.0", + "http-proxy-agent": "^7.0.2", + "https-proxy-agent": "^7.0.6", + "is-potential-custom-element-name": "^1.0.1", + "nwsapi": "^2.2.16", + "parse5": "^7.2.1", + "rrweb-cssom": "^0.8.0", + "saxes": "^6.0.0", + "symbol-tree": "^3.2.4", + "tough-cookie": "^5.1.1", + "w3c-xmlserializer": "^5.0.0", + "webidl-conversions": "^7.0.0", + "whatwg-encoding": "^3.1.1", + "whatwg-mimetype": "^4.0.0", + "whatwg-url": "^14.1.1", + "ws": "^8.18.0", + "xml-name-validator": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "canvas": "^3.0.0" + }, + "peerDependenciesMeta": { + "canvas": { + "optional": true + } + } + }, + "node_modules/jsesc": { + "version": "3.1.0", + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "license": "MIT" + }, + "node_modules/json5": { + "version": "2.2.3", + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "license": "MIT" + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "license": "MIT", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/loupe": { + "version": "3.1.3", + "dev": true, + "license": "MIT" + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "license": "ISC", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/lz-string": { + "version": "1.5.0", + "dev": true, + "license": "MIT", + "bin": { + "lz-string": "bin/bin.js" + } + }, + "node_modules/magic-string": { + "version": "0.30.17", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0" + } + }, + "node_modules/make-cancellable-promise": { + "version": "1.3.2", + "license": "MIT", + "funding": { + "url": "https://github.com/wojtekmaj/make-cancellable-promise?sponsor=1" + } + }, + "node_modules/make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "optional": true, + "dependencies": { + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/make-event-props": { + "version": "1.6.2", + "license": "MIT", + "funding": { + "url": "https://github.com/wojtekmaj/make-event-props?sponsor=1" + } + }, + "node_modules/merge-refs": { + "version": "1.3.0", + "license": "MIT", + "funding": { + "url": "https://github.com/wojtekmaj/merge-refs?sponsor=1" + }, + "peerDependencies": { + "@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/mimic-response": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-2.1.0.tgz", + "integrity": "sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==", + "optional": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "optional": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "optional": true, + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minizlib/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "optional": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minizlib/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "optional": true + }, + "node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "optional": true, + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "license": "MIT" + }, + "node_modules/nan": { + "version": "2.22.2", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.22.2.tgz", + "integrity": "sha512-DANghxFkS1plDdRsX0X9pm0Z6SJNN6gBdtXfanwoZ8hooC5gosGFSBGRYHUVPz1asKA/kMRqDRdHrluZ61SpBQ==", + "optional": true + }, + "node_modules/nanoid": { + "version": "3.3.11", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "optional": true, + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/node-fetch/node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "optional": true + }, + "node_modules/node-fetch/node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "optional": true + }, + "node_modules/node-fetch/node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "optional": true, + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/node-releases": { + "version": "2.0.19", + "license": "MIT" + }, + "node_modules/nopt": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", + "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", + "optional": true, + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/npmlog": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", + "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", + "deprecated": "This package is no longer supported.", + "optional": true, + "dependencies": { + "are-we-there-yet": "^2.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^3.0.0", + "set-blocking": "^2.0.0" + } + }, + "node_modules/nwsapi": { + "version": "2.2.20", + "dev": true, + "license": "MIT" + }, + "node_modules/object-assign": { + "version": "4.1.1", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "optional": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "license": "MIT", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-json": { + "version": "5.2.0", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parse5": { + "version": "7.3.0", + "dev": true, + "license": "MIT", + "dependencies": { + "entities": "^6.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "license": "MIT" + }, + "node_modules/path-type": { + "version": "4.0.0", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path2d-polyfill": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path2d-polyfill/-/path2d-polyfill-2.0.1.tgz", + "integrity": "sha512-ad/3bsalbbWhmBo0D6FZ4RNMwsLsPpL6gnvhuSaU5Vm7b06Kr5ubSltQQ0T7YKsiJQO+g22zJ4dJKNTXIyOXtA==", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/pathe": { + "version": "2.0.3", + "dev": true, + "license": "MIT" + }, + "node_modules/pathval": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14.16" + } + }, + "node_modules/pdfjs-dist": { + "version": "3.11.174", + "resolved": "https://registry.npmjs.org/pdfjs-dist/-/pdfjs-dist-3.11.174.tgz", + "integrity": "sha512-TdTZPf1trZ8/UFu5Cx/GXB7GZM30LT+wWUNfsi6Bq8ePLnb+woNKtDymI2mxZYBpMbonNFqKmiz684DIfnd8dA==", + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "canvas": "^2.11.2", + "path2d-polyfill": "^2.0.1" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/postcss": { + "version": "8.5.3", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.8", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/prettier": { + "version": "3.5.3", + "license": "MIT", + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/pretty-format": { + "version": "27.5.1", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/pretty-format/node_modules/react-is": { + "version": "17.0.2", + "dev": true, + "license": "MIT" + }, + "node_modules/prop-types": { + "version": "15.8.1", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + } + }, + "node_modules/prop-types/node_modules/react-is": { + "version": "16.13.1", + "license": "MIT" + }, + "node_modules/punycode": { + "version": "2.3.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/react": { + "version": "19.1.0", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "19.1.0", + "license": "MIT", + "dependencies": { + "scheduler": "^0.26.0" + }, + "peerDependencies": { + "react": "^19.1.0" + } + }, + "node_modules/react-dropzone": { + "version": "11.7.1", + "license": "MIT", + "dependencies": { + "attr-accept": "^2.2.2", + "file-selector": "^0.4.0", + "prop-types": "^15.8.1" + }, + "engines": { + "node": ">= 10.13" + }, + "peerDependencies": { + "react": ">= 16.8" + } + }, + "node_modules/react-is": { + "version": "19.1.0", + "license": "MIT" + }, + "node_modules/react-material-file-upload": { + "version": "0.0.4", + "license": "MIT", + "dependencies": { + "react-dropzone": "^11.4.2" + }, + "peerDependencies": { + "@emotion/react": "^11.4.1", + "@emotion/styled": "^11.3.0", + "@mui/icons-material": "^5.0.4", + "@mui/material": "^5.0.4", + "react": "^17.0.2", + "react-dom": "^17.0.2" + } + }, + "node_modules/react-pdf": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/react-pdf/-/react-pdf-8.0.2.tgz", + "integrity": "sha512-C0PFC+j9vmEIZ82Iq0c85xUWkgsZTUS05syqOk8NC+7PAanyWlVi/ImYkGQe27zYAlBA6IidRYEt1DAAXKq1Ow==", + "dependencies": { + "clsx": "^2.0.0", + "dequal": "^2.0.3", + "make-cancellable-promise": "^1.3.1", + "make-event-props": "^1.6.0", + "merge-refs": "^1.3.0", + "pdfjs-dist": "3.11.174", + "tiny-invariant": "^1.0.0", + "warning": "^4.0.0" + }, + "funding": { + "url": "https://github.com/wojtekmaj/react-pdf?sponsor=1" + }, + "peerDependencies": { + "@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/react-refresh": { + "version": "0.17.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-transition-group": { + "version": "4.4.5", + "license": "BSD-3-Clause", + "dependencies": { + "@babel/runtime": "^7.5.5", + "dom-helpers": "^5.0.1", + "loose-envify": "^1.4.0", + "prop-types": "^15.6.2" + }, + "peerDependencies": { + "react": ">=16.6.0", + "react-dom": ">=16.6.0" + } + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "optional": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "license": "MIT", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/resolve": { + "version": "1.22.10", + "license": "MIT", + "dependencies": { + "is-core-module": "^2.16.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "license": "MIT", + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "optional": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rollup": { + "version": "4.41.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.7" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.41.1", + "@rollup/rollup-android-arm64": "4.41.1", + "@rollup/rollup-darwin-arm64": "4.41.1", + "@rollup/rollup-darwin-x64": "4.41.1", + "@rollup/rollup-freebsd-arm64": "4.41.1", + "@rollup/rollup-freebsd-x64": "4.41.1", + "@rollup/rollup-linux-arm-gnueabihf": "4.41.1", + "@rollup/rollup-linux-arm-musleabihf": "4.41.1", + "@rollup/rollup-linux-arm64-gnu": "4.41.1", + "@rollup/rollup-linux-arm64-musl": "4.41.1", + "@rollup/rollup-linux-loongarch64-gnu": "4.41.1", + "@rollup/rollup-linux-powerpc64le-gnu": "4.41.1", + "@rollup/rollup-linux-riscv64-gnu": "4.41.1", + "@rollup/rollup-linux-riscv64-musl": "4.41.1", + "@rollup/rollup-linux-s390x-gnu": "4.41.1", + "@rollup/rollup-linux-x64-gnu": "4.41.1", + "@rollup/rollup-linux-x64-musl": "4.41.1", + "@rollup/rollup-win32-arm64-msvc": "4.41.1", + "@rollup/rollup-win32-ia32-msvc": "4.41.1", + "@rollup/rollup-win32-x64-msvc": "4.41.1", + "fsevents": "~2.3.2" + } + }, + "node_modules/rrweb-cssom": { + "version": "0.8.0", + "dev": true, + "license": "MIT" + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "optional": true + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "dev": true, + "license": "MIT" + }, + "node_modules/saxes": { + "version": "6.0.0", + "dev": true, + "license": "ISC", + "dependencies": { + "xmlchars": "^2.2.0" + }, + "engines": { + "node": ">=v12.22.7" + } + }, + "node_modules/scheduler": { + "version": "0.26.0", + "license": "MIT" + }, + "node_modules/semver": { + "version": "6.3.1", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/seroval": { + "version": "1.3.2", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/seroval-plugins": { + "version": "1.3.2", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "seroval": "^1.0" + } + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", + "optional": true + }, + "node_modules/siginfo": { + "version": "2.0.0", + "dev": true, + "license": "ISC" + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "optional": true + }, + "node_modules/simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "optional": true + }, + "node_modules/simple-get": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-3.1.1.tgz", + "integrity": "sha512-CQ5LTKGfCpvE1K0n2us+kuMPbk/q0EKl82s4aheV9oXjFEz6W/Y7oQFVJuU6QG77hRT4Ghb5RURteF5vnWjupA==", + "optional": true, + "dependencies": { + "decompress-response": "^4.2.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "node_modules/socket.io-client": { + "version": "4.8.1", + "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.8.1.tgz", + "integrity": "sha512-hJVXfu3E28NmzGk8o1sHhN3om52tRvwYeidbj7xKy2eIIse5IoKX3USlS6Tqt3BHAtflLIkCQBkzVrEEfWUyYQ==", + "dependencies": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.3.2", + "engine.io-client": "~6.6.1", + "socket.io-parser": "~4.2.4" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/socket.io-client/node_modules/debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/socket.io-parser": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz", + "integrity": "sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==", + "dependencies": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.3.1" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/socket.io-parser/node_modules/debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/solid-js": { + "version": "1.9.7", + "license": "MIT", + "dependencies": { + "csstype": "^3.1.0", + "seroval": "~1.3.0", + "seroval-plugins": "~1.3.0" + } + }, + "node_modules/source-map": { + "version": "0.5.7", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/stackback": { + "version": "0.0.2", + "dev": true, + "license": "MIT" + }, + "node_modules/std-env": { + "version": "3.9.0", + "dev": true, + "license": "MIT" + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "optional": true, + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "optional": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "optional": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/stylis": { + "version": "4.2.0", + "license": "MIT" + }, + "node_modules/supports-color": { + "version": "7.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/symbol-tree": { + "version": "3.2.4", + "dev": true, + "license": "MIT" + }, + "node_modules/tar": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", + "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", + "optional": true, + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/tar/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "optional": true + }, + "node_modules/tiny-invariant": { + "version": "1.3.3", + "license": "MIT" + }, + "node_modules/tiny-warning": { + "version": "1.0.3", + "license": "MIT" + }, + "node_modules/tinybench": { + "version": "2.9.0", + "dev": true, + "license": "MIT" + }, + "node_modules/tinyexec": { + "version": "0.3.2", + "dev": true, + "license": "MIT" + }, + "node_modules/tinyglobby": { + "version": "0.2.14", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.4.4", + "picomatch": "^4.0.2" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/tinyglobby/node_modules/picomatch": { + "version": "4.0.2", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/tinypool": { + "version": "1.0.2", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.0.0 || >=20.0.0" + } + }, + "node_modules/tinyrainbow": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/tinyspy": { + "version": "3.0.2", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/tldts": { + "version": "6.1.86", + "dev": true, + "license": "MIT", + "dependencies": { + "tldts-core": "^6.1.86" + }, + "bin": { + "tldts": "bin/cli.js" + } + }, + "node_modules/tldts-core": { + "version": "6.1.86", + "dev": true, + "license": "MIT" + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/tough-cookie": { + "version": "5.1.2", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "tldts": "^6.1.32" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/tr46": { + "version": "5.1.1", + "dev": true, + "license": "MIT", + "dependencies": { + "punycode": "^2.3.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "license": "0BSD" + }, + "node_modules/tsx": { + "version": "4.19.4", + "license": "MIT", + "dependencies": { + "esbuild": "~0.25.0", + "get-tsconfig": "^4.7.5" + }, + "bin": { + "tsx": "dist/cli.mjs" + }, + "engines": { + "node": ">=18.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + } + }, + "node_modules/typescript": { + "version": "5.8.3", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/unplugin": { + "version": "2.3.5", + "license": "MIT", + "dependencies": { + "acorn": "^8.14.1", + "picomatch": "^4.0.2", + "webpack-virtual-modules": "^0.6.2" + }, + "engines": { + "node": ">=18.12.0" + } + }, + "node_modules/unplugin/node_modules/picomatch": { + "version": "4.0.2", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.1.3", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/use-sync-external-store": { + "version": "1.5.0", + "license": "MIT", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "optional": true + }, + "node_modules/vite": { + "version": "6.3.5", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "^0.25.0", + "fdir": "^6.4.4", + "picomatch": "^4.0.2", + "postcss": "^8.5.3", + "rollup": "^4.34.9", + "tinyglobby": "^0.2.13" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^18.0.0 || ^20.0.0 || >=22.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", + "jiti": ">=1.21.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "sass-embedded": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, + "node_modules/vite-node": { + "version": "3.1.4", + "dev": true, + "license": "MIT", + "dependencies": { + "cac": "^6.7.14", + "debug": "^4.4.0", + "es-module-lexer": "^1.7.0", + "pathe": "^2.0.3", + "vite": "^5.0.0 || ^6.0.0" + }, + "bin": { + "vite-node": "vite-node.mjs" + }, + "engines": { + "node": "^18.0.0 || ^20.0.0 || >=22.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/vite/node_modules/picomatch": { + "version": "4.0.2", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/vitest": { + "version": "3.1.4", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/expect": "3.1.4", + "@vitest/mocker": "3.1.4", + "@vitest/pretty-format": "^3.1.4", + "@vitest/runner": "3.1.4", + "@vitest/snapshot": "3.1.4", + "@vitest/spy": "3.1.4", + "@vitest/utils": "3.1.4", + "chai": "^5.2.0", + "debug": "^4.4.0", + "expect-type": "^1.2.1", + "magic-string": "^0.30.17", + "pathe": "^2.0.3", + "std-env": "^3.9.0", + "tinybench": "^2.9.0", + "tinyexec": "^0.3.2", + "tinyglobby": "^0.2.13", + "tinypool": "^1.0.2", + "tinyrainbow": "^2.0.0", + "vite": "^5.0.0 || ^6.0.0", + "vite-node": "3.1.4", + "why-is-node-running": "^2.3.0" + }, + "bin": { + "vitest": "vitest.mjs" + }, + "engines": { + "node": "^18.0.0 || ^20.0.0 || >=22.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@edge-runtime/vm": "*", + "@types/debug": "^4.1.12", + "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", + "@vitest/browser": "3.1.4", + "@vitest/ui": "3.1.4", + "happy-dom": "*", + "jsdom": "*" + }, + "peerDependenciesMeta": { + "@edge-runtime/vm": { + "optional": true + }, + "@types/debug": { + "optional": true + }, + "@types/node": { + "optional": true + }, + "@vitest/browser": { + "optional": true + }, + "@vitest/ui": { + "optional": true + }, + "happy-dom": { + "optional": true + }, + "jsdom": { + "optional": true + } + } + }, + "node_modules/w3c-xmlserializer": { + "version": "5.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "xml-name-validator": "^5.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/warning": { + "version": "4.0.3", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.0.0" + } + }, + "node_modules/webidl-conversions": { + "version": "7.0.0", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + } + }, + "node_modules/webpack-virtual-modules": { + "version": "0.6.2", + "license": "MIT" + }, + "node_modules/whatwg-encoding": { + "version": "3.1.1", + "dev": true, + "license": "MIT", + "dependencies": { + "iconv-lite": "0.6.3" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/whatwg-mimetype": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/whatwg-url": { + "version": "14.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "tr46": "^5.1.0", + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/why-is-node-running": { + "version": "2.3.0", + "dev": true, + "license": "MIT", + "dependencies": { + "siginfo": "^2.0.0", + "stackback": "0.0.2" + }, + "bin": { + "why-is-node-running": "cli.js" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "optional": true, + "dependencies": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "optional": true + }, + "node_modules/ws": { + "version": "8.18.2", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xml-name-validator": { + "version": "5.0.0", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18" + } + }, + "node_modules/xmlchars": { + "version": "2.2.0", + "dev": true, + "license": "MIT" + }, + "node_modules/xmlhttprequest-ssl": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.1.2.tgz", + "integrity": "sha512-TEU+nJVUUnA4CYJFLvK5X9AOeH4KvDvhIfm0vV1GaQRtchnG0hgK5p8hw/xjv8cunWYCsiPCSDzObPyhEwq3KQ==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "license": "ISC" + }, + "node_modules/yaml": { + "version": "1.10.2", + "license": "ISC", + "engines": { + "node": ">= 6" + } + }, + "node_modules/zod": { + "version": "3.25.32", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + } + }, + "dependencies": { + "@ampproject/remapping": { + "version": "2.3.0", + "requires": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "@asamuzakjp/css-color": { + "version": "3.2.0", + "dev": true, + "requires": { + "@csstools/css-calc": "^2.1.3", + "@csstools/css-color-parser": "^3.0.9", + "@csstools/css-parser-algorithms": "^3.0.4", + "@csstools/css-tokenizer": "^3.0.3", + "lru-cache": "^10.4.3" + }, + "dependencies": { + "lru-cache": { + "version": "10.4.3", + "dev": true + } + } + }, + "@babel/code-frame": { + "version": "7.27.1", + "requires": { + "@babel/helper-validator-identifier": "^7.27.1", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + } + }, + "@babel/compat-data": { + "version": "7.27.3" + }, + "@babel/core": { + "version": "7.27.3", + "requires": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.27.1", + "@babel/generator": "^7.27.3", + "@babel/helper-compilation-targets": "^7.27.2", + "@babel/helper-module-transforms": "^7.27.3", + "@babel/helpers": "^7.27.3", + "@babel/parser": "^7.27.3", + "@babel/template": "^7.27.2", + "@babel/traverse": "^7.27.3", + "@babel/types": "^7.27.3", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "dependencies": { + "convert-source-map": { + "version": "2.0.0" + } + } + }, + "@babel/generator": { + "version": "7.27.3", + "requires": { + "@babel/parser": "^7.27.3", + "@babel/types": "^7.27.3", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", + "jsesc": "^3.0.2" + } + }, + "@babel/helper-compilation-targets": { + "version": "7.27.2", + "requires": { + "@babel/compat-data": "^7.27.2", + "@babel/helper-validator-option": "^7.27.1", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + } + }, + "@babel/helper-module-imports": { + "version": "7.27.1", + "requires": { + "@babel/traverse": "^7.27.1", + "@babel/types": "^7.27.1" + } + }, + "@babel/helper-module-transforms": { + "version": "7.27.3", + "requires": { + "@babel/helper-module-imports": "^7.27.1", + "@babel/helper-validator-identifier": "^7.27.1", + "@babel/traverse": "^7.27.3" + } + }, + "@babel/helper-plugin-utils": { + "version": "7.27.1" + }, + "@babel/helper-string-parser": { + "version": "7.27.1" + }, + "@babel/helper-validator-identifier": { + "version": "7.27.1" + }, + "@babel/helper-validator-option": { + "version": "7.27.1" + }, + "@babel/helpers": { + "version": "7.27.3", + "requires": { + "@babel/template": "^7.27.2", + "@babel/types": "^7.27.3" + } + }, + "@babel/parser": { + "version": "7.27.3", + "requires": { + "@babel/types": "^7.27.3" + } + }, + "@babel/plugin-syntax-jsx": { + "version": "7.27.1", + "requires": { + "@babel/helper-plugin-utils": "^7.27.1" + } + }, + "@babel/plugin-syntax-typescript": { + "version": "7.27.1", + "requires": { + "@babel/helper-plugin-utils": "^7.27.1" + } + }, + "@babel/plugin-transform-react-jsx-self": { + "version": "7.27.1", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.27.1" + } + }, + "@babel/plugin-transform-react-jsx-source": { + "version": "7.27.1", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.27.1" + } + }, + "@babel/runtime": { + "version": "7.27.3" + }, + "@babel/template": { + "version": "7.27.2", + "requires": { + "@babel/code-frame": "^7.27.1", + "@babel/parser": "^7.27.2", + "@babel/types": "^7.27.1" + } + }, + "@babel/traverse": { + "version": "7.27.3", + "requires": { + "@babel/code-frame": "^7.27.1", + "@babel/generator": "^7.27.3", + "@babel/parser": "^7.27.3", + "@babel/template": "^7.27.2", + "@babel/types": "^7.27.3", + "debug": "^4.3.1", + "globals": "^11.1.0" + } + }, + "@babel/types": { + "version": "7.27.3", + "requires": { + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.27.1" + } + }, + "@biomejs/biome": { + "version": "1.9.4", + "dev": true, + "requires": { + "@biomejs/cli-darwin-arm64": "1.9.4", + "@biomejs/cli-darwin-x64": "1.9.4", + "@biomejs/cli-linux-arm64": "1.9.4", + "@biomejs/cli-linux-arm64-musl": "1.9.4", + "@biomejs/cli-linux-x64": "1.9.4", + "@biomejs/cli-linux-x64-musl": "1.9.4", + "@biomejs/cli-win32-arm64": "1.9.4", + "@biomejs/cli-win32-x64": "1.9.4" + } + }, + "@biomejs/cli-win32-x64": { + "version": "1.9.4", + "dev": true, + "optional": true + }, + "@csstools/color-helpers": { + "version": "5.0.2", + "dev": true + }, + "@csstools/css-calc": { + "version": "2.1.4", + "dev": true + }, + "@csstools/css-color-parser": { + "version": "3.0.10", + "dev": true, + "requires": { + "@csstools/color-helpers": "^5.0.2", + "@csstools/css-calc": "^2.1.4" + } + }, + "@csstools/css-parser-algorithms": { + "version": "3.0.5", + "dev": true + }, + "@csstools/css-tokenizer": { + "version": "3.0.4", + "dev": true + }, + "@emotion/babel-plugin": { + "version": "11.13.5", + "requires": { + "@babel/helper-module-imports": "^7.16.7", + "@babel/runtime": "^7.18.3", + "@emotion/hash": "^0.9.2", + "@emotion/memoize": "^0.9.0", + "@emotion/serialize": "^1.3.3", + "babel-plugin-macros": "^3.1.0", + "convert-source-map": "^1.5.0", + "escape-string-regexp": "^4.0.0", + "find-root": "^1.1.0", + "source-map": "^0.5.7", + "stylis": "4.2.0" + } + }, + "@emotion/cache": { + "version": "11.14.0", + "requires": { + "@emotion/memoize": "^0.9.0", + "@emotion/sheet": "^1.4.0", + "@emotion/utils": "^1.4.2", + "@emotion/weak-memoize": "^0.4.0", + "stylis": "4.2.0" + } + }, + "@emotion/hash": { + "version": "0.9.2" + }, + "@emotion/is-prop-valid": { + "version": "1.3.1", + "requires": { + "@emotion/memoize": "^0.9.0" + } + }, + "@emotion/memoize": { + "version": "0.9.0" + }, + "@emotion/react": { + "version": "11.14.0", + "requires": { + "@babel/runtime": "^7.18.3", + "@emotion/babel-plugin": "^11.13.5", + "@emotion/cache": "^11.14.0", + "@emotion/serialize": "^1.3.3", + "@emotion/use-insertion-effect-with-fallbacks": "^1.2.0", + "@emotion/utils": "^1.4.2", + "@emotion/weak-memoize": "^0.4.0", + "hoist-non-react-statics": "^3.3.1" + } + }, + "@emotion/serialize": { + "version": "1.3.3", + "requires": { + "@emotion/hash": "^0.9.2", + "@emotion/memoize": "^0.9.0", + "@emotion/unitless": "^0.10.0", + "@emotion/utils": "^1.4.2", + "csstype": "^3.0.2" + } + }, + "@emotion/sheet": { + "version": "1.4.0" + }, + "@emotion/styled": { + "version": "11.14.0", + "requires": { + "@babel/runtime": "^7.18.3", + "@emotion/babel-plugin": "^11.13.5", + "@emotion/is-prop-valid": "^1.3.0", + "@emotion/serialize": "^1.3.3", + "@emotion/use-insertion-effect-with-fallbacks": "^1.2.0", + "@emotion/utils": "^1.4.2" + } + }, + "@emotion/unitless": { + "version": "0.10.0" + }, + "@emotion/use-insertion-effect-with-fallbacks": { + "version": "1.2.0" + }, + "@emotion/utils": { + "version": "1.4.2" + }, + "@emotion/weak-memoize": { + "version": "0.4.0" + }, + "@esbuild/win32-x64": { + "version": "0.25.5", + "optional": true + }, + "@fontsource/roboto": { + "version": "5.2.5" + }, + "@jridgewell/gen-mapping": { + "version": "0.3.8", + "requires": { + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "@jridgewell/resolve-uri": { + "version": "3.1.2" + }, + "@jridgewell/set-array": { + "version": "1.2.1" + }, + "@jridgewell/sourcemap-codec": { + "version": "1.5.0" + }, + "@jridgewell/trace-mapping": { + "version": "0.3.25", + "requires": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "@mapbox/node-pre-gyp": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz", + "integrity": "sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==", + "optional": true, + "requires": { + "detect-libc": "^2.0.0", + "https-proxy-agent": "^5.0.0", + "make-dir": "^3.1.0", + "node-fetch": "^2.6.7", + "nopt": "^5.0.0", + "npmlog": "^5.0.1", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.11" + }, + "dependencies": { + "agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "optional": true, + "requires": { + "debug": "4" + } + }, + "https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "optional": true, + "requires": { + "agent-base": "6", + "debug": "4" + } + }, + "semver": { + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "optional": true + } + } + }, + "@mui/core-downloads-tracker": { + "version": "7.1.0" + }, + "@mui/icons-material": { + "version": "7.1.0", + "requires": { + "@babel/runtime": "^7.27.1" + } + }, + "@mui/material": { + "version": "7.1.0", + "requires": { + "@babel/runtime": "^7.27.1", + "@mui/core-downloads-tracker": "^7.1.0", + "@mui/system": "^7.1.0", + "@mui/types": "^7.4.2", + "@mui/utils": "^7.1.0", + "@popperjs/core": "^2.11.8", + "@types/react-transition-group": "^4.4.12", + "clsx": "^2.1.1", + "csstype": "^3.1.3", + "prop-types": "^15.8.1", + "react-is": "^19.1.0", + "react-transition-group": "^4.4.5" + } + }, + "@mui/private-theming": { + "version": "7.1.0", + "requires": { + "@babel/runtime": "^7.27.1", + "@mui/utils": "^7.1.0", + "prop-types": "^15.8.1" + } + }, + "@mui/styled-engine": { + "version": "7.1.0", + "requires": { + "@babel/runtime": "^7.27.1", + "@emotion/cache": "^11.13.5", + "@emotion/serialize": "^1.3.3", + "@emotion/sheet": "^1.4.0", + "csstype": "^3.1.3", + "prop-types": "^15.8.1" + } + }, + "@mui/system": { + "version": "7.1.0", + "requires": { + "@babel/runtime": "^7.27.1", + "@mui/private-theming": "^7.1.0", + "@mui/styled-engine": "^7.1.0", + "@mui/types": "^7.4.2", + "@mui/utils": "^7.1.0", + "clsx": "^2.1.1", + "csstype": "^3.1.3", + "prop-types": "^15.8.1" + } + }, + "@mui/types": { + "version": "7.4.2", + "requires": { + "@babel/runtime": "^7.27.1" + } + }, + "@mui/utils": { + "version": "7.1.0", + "requires": { + "@babel/runtime": "^7.27.1", + "@mui/types": "^7.4.2", + "@types/prop-types": "^15.7.14", + "clsx": "^2.1.1", + "prop-types": "^15.8.1", + "react-is": "^19.1.0" + } + }, + "@popperjs/core": { + "version": "2.11.8" + }, + "@rolldown/pluginutils": { + "version": "1.0.0-beta.9", + "dev": true + }, + "@rollup/rollup-win32-x64-msvc": { + "version": "4.41.1", + "dev": true, + "optional": true + }, + "@socket.io/component-emitter": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz", + "integrity": "sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==" + }, + "@tanstack/history": { + "version": "1.115.0" + }, + "@tanstack/query-core": { + "version": "5.77.2" + }, + "@tanstack/query-devtools": { + "version": "5.76.0" + }, + "@tanstack/react-query": { + "version": "5.77.2", + "requires": { + "@tanstack/query-core": "5.77.2" + } + }, + "@tanstack/react-query-devtools": { + "version": "5.77.2", + "requires": { + "@tanstack/query-devtools": "5.76.0" + } + }, + "@tanstack/react-router": { + "version": "1.120.11", + "requires": { + "@tanstack/history": "1.115.0", + "@tanstack/react-store": "^0.7.0", + "@tanstack/router-core": "1.120.10", + "jsesc": "^3.1.0", + "tiny-invariant": "^1.3.3", + "tiny-warning": "^1.0.3" + } + }, + "@tanstack/react-router-devtools": { + "version": "1.120.11", + "requires": { + "@tanstack/router-devtools-core": "^1.120.10", + "solid-js": "^1.9.5" + } + }, + "@tanstack/react-store": { + "version": "0.7.0", + "requires": { + "@tanstack/store": "0.7.0", + "use-sync-external-store": "^1.4.0" + } + }, + "@tanstack/router-core": { + "version": "1.120.10", + "requires": { + "@tanstack/history": "1.115.0", + "@tanstack/store": "^0.7.0", + "tiny-invariant": "^1.3.3" + } + }, + "@tanstack/router-devtools-core": { + "version": "1.120.10", + "requires": { + "clsx": "^2.1.1", + "goober": "^2.1.16" + } + }, + "@tanstack/router-generator": { + "version": "1.120.11", + "requires": { + "@tanstack/virtual-file-routes": "^1.115.0", + "prettier": "^3.5.0", + "tsx": "^4.19.2", + "zod": "^3.24.2" + } + }, + "@tanstack/router-plugin": { + "version": "1.120.11", + "requires": { + "@babel/core": "^7.26.8", + "@babel/plugin-syntax-jsx": "^7.25.9", + "@babel/plugin-syntax-typescript": "^7.25.9", + "@babel/template": "^7.26.8", + "@babel/traverse": "^7.26.8", + "@babel/types": "^7.26.8", + "@tanstack/router-core": "^1.120.10", + "@tanstack/router-generator": "^1.120.11", + "@tanstack/router-utils": "^1.115.0", + "@tanstack/virtual-file-routes": "^1.115.0", + "@types/babel__core": "^7.20.5", + "@types/babel__template": "^7.4.4", + "@types/babel__traverse": "^7.20.6", + "babel-dead-code-elimination": "^1.0.10", + "chokidar": "^3.6.0", + "unplugin": "^2.1.2", + "zod": "^3.24.2" + } + }, + "@tanstack/router-utils": { + "version": "1.115.0", + "requires": { + "@babel/generator": "^7.26.8", + "@babel/parser": "^7.26.8", + "ansis": "^3.11.0", + "diff": "^7.0.0" + } + }, + "@tanstack/store": { + "version": "0.7.0" + }, + "@tanstack/virtual-file-routes": { + "version": "1.115.0" + }, + "@testing-library/dom": { + "version": "10.4.0", + "dev": true, + "requires": { + "@babel/code-frame": "^7.10.4", + "@babel/runtime": "^7.12.5", + "@types/aria-query": "^5.0.1", + "aria-query": "5.3.0", + "chalk": "^4.1.0", + "dom-accessibility-api": "^0.5.9", + "lz-string": "^1.5.0", + "pretty-format": "^27.0.2" + } + }, + "@testing-library/react": { + "version": "16.3.0", + "dev": true, + "requires": { + "@babel/runtime": "^7.12.5" + } + }, + "@types/aria-query": { + "version": "5.0.4", + "dev": true + }, + "@types/babel__core": { + "version": "7.20.5", + "requires": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "@types/babel__generator": { + "version": "7.27.0", + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@types/babel__template": { + "version": "7.4.4", + "requires": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "@types/babel__traverse": { + "version": "7.20.7", + "requires": { + "@babel/types": "^7.20.7" + } + }, + "@types/estree": { + "version": "1.0.7", + "dev": true + }, + "@types/file-saver": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@types/file-saver/-/file-saver-2.0.7.tgz", + "integrity": "sha512-dNKVfHd/jk0SkR/exKGj2ggkB45MAkzvWCaqLUUgkyjITkGNzH8H+yUwr+BLJUBjZOe9w8X3wgmXhZDRg1ED6A==", + "dev": true + }, + "@types/parse-json": { + "version": "4.0.2" + }, + "@types/prop-types": { + "version": "15.7.14" + }, + "@types/react": { + "version": "19.1.6", + "dev": true, + "requires": { + "csstype": "^3.0.2" + } + }, + "@types/react-dom": { + "version": "19.1.5", + "dev": true + }, + "@types/react-transition-group": { + "version": "4.4.12" + }, + "@vitejs/plugin-react": { + "version": "4.5.0", + "dev": true, + "requires": { + "@babel/core": "^7.26.10", + "@babel/plugin-transform-react-jsx-self": "^7.25.9", + "@babel/plugin-transform-react-jsx-source": "^7.25.9", + "@rolldown/pluginutils": "1.0.0-beta.9", + "@types/babel__core": "^7.20.5", + "react-refresh": "^0.17.0" + } + }, + "@vitest/expect": { + "version": "3.1.4", + "dev": true, + "requires": { + "@vitest/spy": "3.1.4", + "@vitest/utils": "3.1.4", + "chai": "^5.2.0", + "tinyrainbow": "^2.0.0" + } + }, + "@vitest/mocker": { + "version": "3.1.4", + "dev": true, + "requires": { + "@vitest/spy": "3.1.4", + "estree-walker": "^3.0.3", + "magic-string": "^0.30.17" + } + }, + "@vitest/pretty-format": { + "version": "3.1.4", + "dev": true, + "requires": { + "tinyrainbow": "^2.0.0" + } + }, + "@vitest/runner": { + "version": "3.1.4", + "dev": true, + "requires": { + "@vitest/utils": "3.1.4", + "pathe": "^2.0.3" + } + }, + "@vitest/snapshot": { + "version": "3.1.4", + "dev": true, + "requires": { + "@vitest/pretty-format": "3.1.4", + "magic-string": "^0.30.17", + "pathe": "^2.0.3" + } + }, + "@vitest/spy": { + "version": "3.1.4", + "dev": true, + "requires": { + "tinyspy": "^3.0.2" + } + }, + "@vitest/utils": { + "version": "3.1.4", + "dev": true, + "requires": { + "@vitest/pretty-format": "3.1.4", + "loupe": "^3.1.3", + "tinyrainbow": "^2.0.0" + } + }, + "abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "optional": true + }, + "acorn": { + "version": "8.14.1" + }, + "agent-base": { + "version": "7.1.3", + "dev": true + }, + "ansi-regex": { + "version": "5.0.1", + "devOptional": true + }, + "ansi-styles": { + "version": "4.3.0", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "ansis": { + "version": "3.17.0" + }, + "anymatch": { + "version": "3.1.3", + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, + "aproba": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", + "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==", + "optional": true + }, + "are-we-there-yet": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", + "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", + "optional": true, + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + } + }, + "aria-query": { + "version": "5.3.0", + "dev": true, + "requires": { + "dequal": "^2.0.3" + } + }, + "assertion-error": { + "version": "2.0.1", + "dev": true + }, + "attr-accept": { + "version": "2.2.5" + }, + "babel-dead-code-elimination": { + "version": "1.0.10", + "requires": { + "@babel/core": "^7.23.7", + "@babel/parser": "^7.23.6", + "@babel/traverse": "^7.23.7", + "@babel/types": "^7.23.6" + } + }, + "babel-plugin-macros": { + "version": "3.1.0", + "requires": { + "@babel/runtime": "^7.12.5", + "cosmiconfig": "^7.0.0", + "resolve": "^1.19.0" + } + }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "optional": true + }, + "binary-extensions": { + "version": "2.3.0" + }, + "brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "optional": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "3.0.3", + "requires": { + "fill-range": "^7.1.1" + } + }, + "browserslist": { + "version": "4.24.5", + "requires": { + "caniuse-lite": "^1.0.30001716", + "electron-to-chromium": "^1.5.149", + "node-releases": "^2.0.19", + "update-browserslist-db": "^1.1.3" + } + }, + "cac": { + "version": "6.7.14", + "dev": true + }, + "callsites": { + "version": "3.1.0" + }, + "caniuse-lite": { + "version": "1.0.30001718" + }, + "canvas": { + "version": "2.11.2", + "resolved": "https://registry.npmjs.org/canvas/-/canvas-2.11.2.tgz", + "integrity": "sha512-ItanGBMrmRV7Py2Z+Xhs7cT+FNt5K0vPL4p9EZ/UX/Mu7hFbkxSjKF2KVtPwX7UYWp7dRKnrTvReflgrItJbdw==", + "optional": true, + "requires": { + "@mapbox/node-pre-gyp": "^1.0.0", + "nan": "^2.17.0", + "simple-get": "^3.0.3" + } + }, + "chai": { + "version": "5.2.0", + "dev": true, + "requires": { + "assertion-error": "^2.0.1", + "check-error": "^2.1.1", + "deep-eql": "^5.0.1", + "loupe": "^3.1.0", + "pathval": "^2.0.0" + } + }, + "chalk": { + "version": "4.1.2", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "check-error": { + "version": "2.1.1", + "dev": true + }, + "chokidar": { + "version": "3.6.0", + "requires": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "fsevents": "~2.3.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + } + }, + "chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "optional": true + }, + "clsx": { + "version": "2.1.1" + }, + "color-convert": { + "version": "2.0.1", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "dev": true + }, + "color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "optional": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "optional": true + }, + "console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==", + "optional": true + }, + "convert-source-map": { + "version": "1.9.0" + }, + "cosmiconfig": { + "version": "7.1.0", + "requires": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.2.1", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.10.0" + } + }, + "cssstyle": { + "version": "4.3.1", + "dev": true, + "requires": { + "@asamuzakjp/css-color": "^3.1.2", + "rrweb-cssom": "^0.8.0" + } + }, + "csstype": { + "version": "3.1.3" + }, + "data-urls": { + "version": "5.0.0", + "dev": true, + "requires": { + "whatwg-mimetype": "^4.0.0", + "whatwg-url": "^14.0.0" + } + }, + "debug": { + "version": "4.4.1", + "requires": { + "ms": "^2.1.3" + } + }, + "decimal.js": { + "version": "10.5.0", + "dev": true + }, + "decompress-response": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-4.2.1.tgz", + "integrity": "sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw==", + "optional": true, + "requires": { + "mimic-response": "^2.0.0" + } + }, + "deep-eql": { + "version": "5.0.2", + "dev": true + }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", + "optional": true + }, + "dequal": { + "version": "2.0.3" + }, + "detect-libc": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.4.tgz", + "integrity": "sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==", + "optional": true + }, + "diff": { + "version": "7.0.0" + }, + "dom-accessibility-api": { + "version": "0.5.16", + "dev": true + }, + "dom-helpers": { + "version": "5.2.1", + "requires": { + "@babel/runtime": "^7.8.7", + "csstype": "^3.0.2" + } + }, + "electron-to-chromium": { + "version": "1.5.159" + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "optional": true + }, + "engine.io-client": { + "version": "6.6.3", + "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.6.3.tgz", + "integrity": "sha512-T0iLjnyNWahNyv/lcjS2y4oE358tVS/SYQNxYXGAJ9/GLgH4VCvOQ/mhTjqU88mLZCQgiG8RIegFHYCdVC+j5w==", + "requires": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.3.1", + "engine.io-parser": "~5.2.1", + "ws": "~8.17.1", + "xmlhttprequest-ssl": "~2.1.1" + }, + "dependencies": { + "debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "requires": { + "ms": "^2.1.3" + } + }, + "ws": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", + "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==" + } + } + }, + "engine.io-parser": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.3.tgz", + "integrity": "sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q==" + }, + "entities": { + "version": "6.0.0", + "dev": true + }, + "error-ex": { + "version": "1.3.2", + "requires": { + "is-arrayish": "^0.2.1" + } + }, + "es-module-lexer": { + "version": "1.7.0", + "dev": true + }, + "esbuild": { + "version": "0.25.5", + "requires": { + "@esbuild/aix-ppc64": "0.25.5", + "@esbuild/android-arm": "0.25.5", + "@esbuild/android-arm64": "0.25.5", + "@esbuild/android-x64": "0.25.5", + "@esbuild/darwin-arm64": "0.25.5", + "@esbuild/darwin-x64": "0.25.5", + "@esbuild/freebsd-arm64": "0.25.5", + "@esbuild/freebsd-x64": "0.25.5", + "@esbuild/linux-arm": "0.25.5", + "@esbuild/linux-arm64": "0.25.5", + "@esbuild/linux-ia32": "0.25.5", + "@esbuild/linux-loong64": "0.25.5", + "@esbuild/linux-mips64el": "0.25.5", + "@esbuild/linux-ppc64": "0.25.5", + "@esbuild/linux-riscv64": "0.25.5", + "@esbuild/linux-s390x": "0.25.5", + "@esbuild/linux-x64": "0.25.5", + "@esbuild/netbsd-arm64": "0.25.5", + "@esbuild/netbsd-x64": "0.25.5", + "@esbuild/openbsd-arm64": "0.25.5", + "@esbuild/openbsd-x64": "0.25.5", + "@esbuild/sunos-x64": "0.25.5", + "@esbuild/win32-arm64": "0.25.5", + "@esbuild/win32-ia32": "0.25.5", + "@esbuild/win32-x64": "0.25.5" + } + }, + "escalade": { + "version": "3.2.0" + }, + "escape-string-regexp": { + "version": "4.0.0" + }, + "estree-walker": { + "version": "3.0.3", + "dev": true, + "requires": { + "@types/estree": "^1.0.0" + } + }, + "expect-type": { + "version": "1.2.1", + "dev": true + }, + "fdir": { + "version": "6.4.5", + "dev": true + }, + "file-saver": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/file-saver/-/file-saver-2.0.5.tgz", + "integrity": "sha512-P9bmyZ3h/PRG+Nzga+rbdI4OEpNDzAVyy74uVO9ATgzLK6VtAsYybF/+TOCvrc0MO793d6+42lLyZTw7/ArVzA==" + }, + "file-selector": { + "version": "0.4.0", + "requires": { + "tslib": "^2.0.3" + } + }, + "fill-range": { + "version": "7.1.1", + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "find-root": { + "version": "1.1.0" + }, + "fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "optional": true, + "requires": { + "minipass": "^3.0.0" + }, + "dependencies": { + "minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "optional": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "optional": true + } + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "optional": true + }, + "function-bind": { + "version": "1.1.2" + }, + "gauge": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", + "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", + "optional": true, + "requires": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.2", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.1", + "object-assign": "^4.1.1", + "signal-exit": "^3.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.2" + } + }, + "gensync": { + "version": "1.0.0-beta.2" + }, + "get-tsconfig": { + "version": "4.10.1", + "requires": { + "resolve-pkg-maps": "^1.0.0" + } + }, + "glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "optional": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "glob-parent": { + "version": "5.1.2", + "requires": { + "is-glob": "^4.0.1" + } + }, + "globals": { + "version": "11.12.0" + }, + "goober": { + "version": "2.1.16" + }, + "has-flag": { + "version": "4.0.0", + "dev": true + }, + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==", + "optional": true + }, + "hasown": { + "version": "2.0.2", + "requires": { + "function-bind": "^1.1.2" + } + }, + "hoist-non-react-statics": { + "version": "3.3.2", + "requires": { + "react-is": "^16.7.0" + }, + "dependencies": { + "react-is": { + "version": "16.13.1" + } + } + }, + "html-encoding-sniffer": { + "version": "4.0.0", + "dev": true, + "requires": { + "whatwg-encoding": "^3.1.1" + } + }, + "http-proxy-agent": { + "version": "7.0.2", + "dev": true, + "requires": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + } + }, + "https-proxy-agent": { + "version": "7.0.6", + "dev": true, + "requires": { + "agent-base": "^7.1.2", + "debug": "4" + } + }, + "iconv-lite": { + "version": "0.6.3", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + } + }, + "import-fresh": { + "version": "3.3.1", + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + } + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "optional": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "optional": true + }, + "is-arrayish": { + "version": "0.2.1" + }, + "is-binary-path": { + "version": "2.1.0", + "requires": { + "binary-extensions": "^2.0.0" + } + }, + "is-core-module": { + "version": "2.16.1", + "requires": { + "hasown": "^2.0.2" + } + }, + "is-extglob": { + "version": "2.1.1" + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "optional": true + }, + "is-glob": { + "version": "4.0.3", + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-number": { + "version": "7.0.0" + }, + "is-potential-custom-element-name": { + "version": "1.0.1", + "dev": true + }, + "js-tokens": { + "version": "4.0.0" + }, + "jsdom": { + "version": "26.1.0", + "dev": true, + "requires": { + "cssstyle": "^4.2.1", + "data-urls": "^5.0.0", + "decimal.js": "^10.5.0", + "html-encoding-sniffer": "^4.0.0", + "http-proxy-agent": "^7.0.2", + "https-proxy-agent": "^7.0.6", + "is-potential-custom-element-name": "^1.0.1", + "nwsapi": "^2.2.16", + "parse5": "^7.2.1", + "rrweb-cssom": "^0.8.0", + "saxes": "^6.0.0", + "symbol-tree": "^3.2.4", + "tough-cookie": "^5.1.1", + "w3c-xmlserializer": "^5.0.0", + "webidl-conversions": "^7.0.0", + "whatwg-encoding": "^3.1.1", + "whatwg-mimetype": "^4.0.0", + "whatwg-url": "^14.1.1", + "ws": "^8.18.0", + "xml-name-validator": "^5.0.0" + } + }, + "jsesc": { + "version": "3.1.0" + }, + "json-parse-even-better-errors": { + "version": "2.3.1" + }, + "json5": { + "version": "2.2.3" + }, + "lines-and-columns": { + "version": "1.2.4" + }, + "loose-envify": { + "version": "1.4.0", + "requires": { + "js-tokens": "^3.0.0 || ^4.0.0" + } + }, + "loupe": { + "version": "3.1.3", + "dev": true + }, + "lru-cache": { + "version": "5.1.1", + "requires": { + "yallist": "^3.0.2" + } + }, + "lz-string": { + "version": "1.5.0", + "dev": true + }, + "magic-string": { + "version": "0.30.17", + "dev": true, + "requires": { + "@jridgewell/sourcemap-codec": "^1.5.0" + } + }, + "make-cancellable-promise": { + "version": "1.3.2" + }, + "make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "optional": true, + "requires": { + "semver": "^6.0.0" + } + }, + "make-event-props": { + "version": "1.6.2" + }, + "merge-refs": { + "version": "1.3.0" + }, + "mimic-response": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-2.1.0.tgz", + "integrity": "sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==", + "optional": true + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "optional": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "optional": true + }, + "minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "optional": true, + "requires": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "dependencies": { + "minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "optional": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "optional": true + } + } + }, + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "optional": true + }, + "ms": { + "version": "2.1.3" + }, + "nan": { + "version": "2.22.2", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.22.2.tgz", + "integrity": "sha512-DANghxFkS1plDdRsX0X9pm0Z6SJNN6gBdtXfanwoZ8hooC5gosGFSBGRYHUVPz1asKA/kMRqDRdHrluZ61SpBQ==", + "optional": true + }, + "nanoid": { + "version": "3.3.11", + "dev": true + }, + "node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "optional": true, + "requires": { + "whatwg-url": "^5.0.0" + }, + "dependencies": { + "tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "optional": true + }, + "webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "optional": true + }, + "whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "optional": true, + "requires": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + } + } + }, + "node-releases": { + "version": "2.0.19" + }, + "nopt": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", + "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", + "optional": true, + "requires": { + "abbrev": "1" + } + }, + "normalize-path": { + "version": "3.0.0" + }, + "npmlog": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", + "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", + "optional": true, + "requires": { + "are-we-there-yet": "^2.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^3.0.0", + "set-blocking": "^2.0.0" + } + }, + "nwsapi": { + "version": "2.2.20", + "dev": true + }, + "object-assign": { + "version": "4.1.1" + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "optional": true, + "requires": { + "wrappy": "1" + } + }, + "parent-module": { + "version": "1.0.1", + "requires": { + "callsites": "^3.0.0" + } + }, + "parse-json": { + "version": "5.2.0", + "requires": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + } + }, + "parse5": { + "version": "7.3.0", + "dev": true, + "requires": { + "entities": "^6.0.0" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "optional": true + }, + "path-parse": { + "version": "1.0.7" + }, + "path-type": { + "version": "4.0.0" + }, + "path2d-polyfill": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path2d-polyfill/-/path2d-polyfill-2.0.1.tgz", + "integrity": "sha512-ad/3bsalbbWhmBo0D6FZ4RNMwsLsPpL6gnvhuSaU5Vm7b06Kr5ubSltQQ0T7YKsiJQO+g22zJ4dJKNTXIyOXtA==", + "optional": true + }, + "pathe": { + "version": "2.0.3", + "dev": true + }, + "pathval": { + "version": "2.0.0", + "dev": true + }, + "pdfjs-dist": { + "version": "3.11.174", + "resolved": "https://registry.npmjs.org/pdfjs-dist/-/pdfjs-dist-3.11.174.tgz", + "integrity": "sha512-TdTZPf1trZ8/UFu5Cx/GXB7GZM30LT+wWUNfsi6Bq8ePLnb+woNKtDymI2mxZYBpMbonNFqKmiz684DIfnd8dA==", + "requires": { + "canvas": "^2.11.2", + "path2d-polyfill": "^2.0.1" + } + }, + "picocolors": { + "version": "1.1.1" + }, + "picomatch": { + "version": "2.3.1" + }, + "postcss": { + "version": "8.5.3", + "dev": true, + "requires": { + "nanoid": "^3.3.8", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + } + }, + "prettier": { + "version": "3.5.3" + }, + "pretty-format": { + "version": "27.5.1", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "dependencies": { + "ansi-styles": { + "version": "5.2.0", + "dev": true + }, + "react-is": { + "version": "17.0.2", + "dev": true + } + } + }, + "prop-types": { + "version": "15.8.1", + "requires": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + }, + "dependencies": { + "react-is": { + "version": "16.13.1" + } + } + }, + "punycode": { + "version": "2.3.1", + "dev": true + }, + "react": { + "version": "19.1.0" + }, + "react-dom": { + "version": "19.1.0", + "requires": { + "scheduler": "^0.26.0" + } + }, + "react-dropzone": { + "version": "11.7.1", + "requires": { + "attr-accept": "^2.2.2", + "file-selector": "^0.4.0", + "prop-types": "^15.8.1" + } + }, + "react-is": { + "version": "19.1.0" + }, + "react-material-file-upload": { + "version": "0.0.4", + "requires": { + "react-dropzone": "^11.4.2" + } + }, + "react-pdf": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/react-pdf/-/react-pdf-8.0.2.tgz", + "integrity": "sha512-C0PFC+j9vmEIZ82Iq0c85xUWkgsZTUS05syqOk8NC+7PAanyWlVi/ImYkGQe27zYAlBA6IidRYEt1DAAXKq1Ow==", + "requires": { + "clsx": "^2.0.0", + "dequal": "^2.0.3", + "make-cancellable-promise": "^1.3.1", + "make-event-props": "^1.6.0", + "merge-refs": "^1.3.0", + "pdfjs-dist": "3.11.174", + "tiny-invariant": "^1.0.0", + "warning": "^4.0.0" + } + }, + "react-refresh": { + "version": "0.17.0", + "dev": true + }, + "react-transition-group": { + "version": "4.4.5", + "requires": { + "@babel/runtime": "^7.5.5", + "dom-helpers": "^5.0.1", + "loose-envify": "^1.4.0", + "prop-types": "^15.6.2" + } + }, + "readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "optional": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "readdirp": { + "version": "3.6.0", + "requires": { + "picomatch": "^2.2.1" + } + }, + "resolve": { + "version": "1.22.10", + "requires": { + "is-core-module": "^2.16.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + } + }, + "resolve-from": { + "version": "4.0.0" + }, + "resolve-pkg-maps": { + "version": "1.0.0" + }, + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "optional": true, + "requires": { + "glob": "^7.1.3" + } + }, + "rollup": { + "version": "4.41.1", + "dev": true, + "requires": { + "@rollup/rollup-android-arm-eabi": "4.41.1", + "@rollup/rollup-android-arm64": "4.41.1", + "@rollup/rollup-darwin-arm64": "4.41.1", + "@rollup/rollup-darwin-x64": "4.41.1", + "@rollup/rollup-freebsd-arm64": "4.41.1", + "@rollup/rollup-freebsd-x64": "4.41.1", + "@rollup/rollup-linux-arm-gnueabihf": "4.41.1", + "@rollup/rollup-linux-arm-musleabihf": "4.41.1", + "@rollup/rollup-linux-arm64-gnu": "4.41.1", + "@rollup/rollup-linux-arm64-musl": "4.41.1", + "@rollup/rollup-linux-loongarch64-gnu": "4.41.1", + "@rollup/rollup-linux-powerpc64le-gnu": "4.41.1", + "@rollup/rollup-linux-riscv64-gnu": "4.41.1", + "@rollup/rollup-linux-riscv64-musl": "4.41.1", + "@rollup/rollup-linux-s390x-gnu": "4.41.1", + "@rollup/rollup-linux-x64-gnu": "4.41.1", + "@rollup/rollup-linux-x64-musl": "4.41.1", + "@rollup/rollup-win32-arm64-msvc": "4.41.1", + "@rollup/rollup-win32-ia32-msvc": "4.41.1", + "@rollup/rollup-win32-x64-msvc": "4.41.1", + "@types/estree": "1.0.7", + "fsevents": "~2.3.2" + } + }, + "rrweb-cssom": { + "version": "0.8.0", + "dev": true + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "optional": true + }, + "safer-buffer": { + "version": "2.1.2", + "dev": true + }, + "saxes": { + "version": "6.0.0", + "dev": true, + "requires": { + "xmlchars": "^2.2.0" + } + }, + "scheduler": { + "version": "0.26.0" + }, + "semver": { + "version": "6.3.1" + }, + "seroval": { + "version": "1.3.2" + }, + "seroval-plugins": { + "version": "1.3.2" + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", + "optional": true + }, + "siginfo": { + "version": "2.0.0", + "dev": true + }, + "signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "optional": true + }, + "simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "optional": true + }, + "simple-get": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-3.1.1.tgz", + "integrity": "sha512-CQ5LTKGfCpvE1K0n2us+kuMPbk/q0EKl82s4aheV9oXjFEz6W/Y7oQFVJuU6QG77hRT4Ghb5RURteF5vnWjupA==", + "optional": true, + "requires": { + "decompress-response": "^4.2.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "socket.io-client": { + "version": "4.8.1", + "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.8.1.tgz", + "integrity": "sha512-hJVXfu3E28NmzGk8o1sHhN3om52tRvwYeidbj7xKy2eIIse5IoKX3USlS6Tqt3BHAtflLIkCQBkzVrEEfWUyYQ==", + "requires": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.3.2", + "engine.io-client": "~6.6.1", + "socket.io-parser": "~4.2.4" + }, + "dependencies": { + "debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "requires": { + "ms": "^2.1.3" + } + } + } + }, + "socket.io-parser": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz", + "integrity": "sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==", + "requires": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.3.1" + }, + "dependencies": { + "debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "requires": { + "ms": "^2.1.3" + } + } + } + }, + "solid-js": { + "version": "1.9.7", + "requires": { + "csstype": "^3.1.0", + "seroval": "~1.3.0", + "seroval-plugins": "~1.3.0" + } + }, + "source-map": { + "version": "0.5.7" + }, + "source-map-js": { + "version": "1.2.1", + "dev": true + }, + "stackback": { + "version": "0.0.2", + "dev": true + }, + "std-env": { + "version": "3.9.0", + "dev": true + }, + "string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "optional": true, + "requires": { + "safe-buffer": "~5.2.0" + } + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "optional": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "optional": true, + "requires": { + "ansi-regex": "^5.0.1" + } + }, + "stylis": { + "version": "4.2.0" + }, + "supports-color": { + "version": "7.2.0", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "supports-preserve-symlinks-flag": { + "version": "1.0.0" + }, + "symbol-tree": { + "version": "3.2.4", + "dev": true + }, + "tar": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", + "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", + "optional": true, + "requires": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "dependencies": { + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "optional": true + } + } + }, + "tiny-invariant": { + "version": "1.3.3" + }, + "tiny-warning": { + "version": "1.0.3" + }, + "tinybench": { + "version": "2.9.0", + "dev": true + }, + "tinyexec": { + "version": "0.3.2", + "dev": true + }, + "tinyglobby": { + "version": "0.2.14", + "dev": true, + "requires": { + "fdir": "^6.4.4", + "picomatch": "^4.0.2" + }, + "dependencies": { + "picomatch": { + "version": "4.0.2", + "dev": true + } + } + }, + "tinypool": { + "version": "1.0.2", + "dev": true + }, + "tinyrainbow": { + "version": "2.0.0", + "dev": true + }, + "tinyspy": { + "version": "3.0.2", + "dev": true + }, + "tldts": { + "version": "6.1.86", + "dev": true, + "requires": { + "tldts-core": "^6.1.86" + } + }, + "tldts-core": { + "version": "6.1.86", + "dev": true + }, + "to-regex-range": { + "version": "5.0.1", + "requires": { + "is-number": "^7.0.0" + } + }, + "tough-cookie": { + "version": "5.1.2", + "dev": true, + "requires": { + "tldts": "^6.1.32" + } + }, + "tr46": { + "version": "5.1.1", + "dev": true, + "requires": { + "punycode": "^2.3.1" + } + }, + "tslib": { + "version": "2.8.1" + }, + "tsx": { + "version": "4.19.4", + "requires": { + "esbuild": "~0.25.0", + "fsevents": "~2.3.3", + "get-tsconfig": "^4.7.5" + } + }, + "typescript": { + "version": "5.8.3", + "dev": true + }, + "unplugin": { + "version": "2.3.5", + "requires": { + "acorn": "^8.14.1", + "picomatch": "^4.0.2", + "webpack-virtual-modules": "^0.6.2" + }, + "dependencies": { + "picomatch": { + "version": "4.0.2" + } + } + }, + "update-browserslist-db": { + "version": "1.1.3", + "requires": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + } + }, + "use-sync-external-store": { + "version": "1.5.0" + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "optional": true + }, + "vite": { + "version": "6.3.5", + "dev": true, + "requires": { + "esbuild": "^0.25.0", + "fdir": "^6.4.4", + "fsevents": "~2.3.3", + "picomatch": "^4.0.2", + "postcss": "^8.5.3", + "rollup": "^4.34.9", + "tinyglobby": "^0.2.13" + }, + "dependencies": { + "picomatch": { + "version": "4.0.2", + "dev": true + } + } + }, + "vite-node": { + "version": "3.1.4", + "dev": true, + "requires": { + "cac": "^6.7.14", + "debug": "^4.4.0", + "es-module-lexer": "^1.7.0", + "pathe": "^2.0.3", + "vite": "^5.0.0 || ^6.0.0" + } + }, + "vitest": { + "version": "3.1.4", + "dev": true, + "requires": { + "@vitest/expect": "3.1.4", + "@vitest/mocker": "3.1.4", + "@vitest/pretty-format": "^3.1.4", + "@vitest/runner": "3.1.4", + "@vitest/snapshot": "3.1.4", + "@vitest/spy": "3.1.4", + "@vitest/utils": "3.1.4", + "chai": "^5.2.0", + "debug": "^4.4.0", + "expect-type": "^1.2.1", + "magic-string": "^0.30.17", + "pathe": "^2.0.3", + "std-env": "^3.9.0", + "tinybench": "^2.9.0", + "tinyexec": "^0.3.2", + "tinyglobby": "^0.2.13", + "tinypool": "^1.0.2", + "tinyrainbow": "^2.0.0", + "vite": "^5.0.0 || ^6.0.0", + "vite-node": "3.1.4", + "why-is-node-running": "^2.3.0" + } + }, + "w3c-xmlserializer": { + "version": "5.0.0", + "dev": true, + "requires": { + "xml-name-validator": "^5.0.0" + } + }, + "warning": { + "version": "4.0.3", + "requires": { + "loose-envify": "^1.0.0" + } + }, + "webidl-conversions": { + "version": "7.0.0", + "dev": true + }, + "webpack-virtual-modules": { + "version": "0.6.2" + }, + "whatwg-encoding": { + "version": "3.1.1", + "dev": true, + "requires": { + "iconv-lite": "0.6.3" + } + }, + "whatwg-mimetype": { + "version": "4.0.0", + "dev": true + }, + "whatwg-url": { + "version": "14.2.0", + "dev": true, + "requires": { + "tr46": "^5.1.0", + "webidl-conversions": "^7.0.0" + } + }, + "why-is-node-running": { + "version": "2.3.0", + "dev": true, + "requires": { + "siginfo": "^2.0.0", + "stackback": "0.0.2" + } + }, + "wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "optional": true, + "requires": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "optional": true + }, + "ws": { + "version": "8.18.2", + "dev": true + }, + "xml-name-validator": { + "version": "5.0.0", + "dev": true + }, + "xmlchars": { + "version": "2.2.0", + "dev": true + }, + "xmlhttprequest-ssl": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.1.2.tgz", + "integrity": "sha512-TEU+nJVUUnA4CYJFLvK5X9AOeH4KvDvhIfm0vV1GaQRtchnG0hgK5p8hw/xjv8cunWYCsiPCSDzObPyhEwq3KQ==" + }, + "yallist": { + "version": "3.1.1" + }, + "yaml": { + "version": "1.10.2" + }, + "zod": { + "version": "3.25.32" + } + } +} diff --git a/project/frontend/package.json b/project/frontend/package.json index 6bb0b68..9ba5f74 100644 --- a/project/frontend/package.json +++ b/project/frontend/package.json @@ -33,6 +33,7 @@ "@biomejs/biome": "1.9.4", "@testing-library/dom": "^10.4.0", "@testing-library/react": "^16.2.0", + "@types/file-saver": "^2.0.7", "@types/react": "^19.0.8", "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^4.3.4", diff --git a/project/frontend/src/components/ConfigTable.tsx b/project/frontend/src/components/ConfigTable.tsx index 2a9ae34..1bfcb38 100644 --- a/project/frontend/src/components/ConfigTable.tsx +++ b/project/frontend/src/components/ConfigTable.tsx @@ -6,41 +6,56 @@ import type { Kennzahl } from "../types/kpi"; import { getDisplayType } from "../types/kpi"; import { fetchKennzahlen as fetchK } from "../util/api"; import { API_HOST } from "../util/api"; +import WarningAmberIcon from "@mui/icons-material/WarningAmber"; -type ConfigTableProps = { + + + +export type ConfigTableProps = { from?: string; + trainingRunning?: boolean; }; -export function ConfigTable({ from }: ConfigTableProps) { + + +export function ConfigTable({ from, trainingRunning }: ConfigTableProps) { const navigate = useNavigate(); const [kennzahlen, setKennzahlen] = useState([]); const [draggedItem, setDraggedItem] = useState(null); const [isUpdatingPositions, setIsUpdatingPositions] = useState(false); const [loading, setLoading] = useState(true); - useEffect(() => { - const fetchKennzahlen = async () => { - while (true) { - try { - console.log("Fetching kennzahlen from API..."); - const data = await fetchK(); - console.log("Fetched kennzahlen:", data); - const sortedData = data.sort( - (a: Kennzahl, b: Kennzahl) => a.position - b.position, - ); - setKennzahlen(sortedData); - setLoading(false); - break; - } catch (err) { - console.error("Error fetching kennzahlen:", err); - await new Promise((resolve) => setTimeout(resolve, 2000)); - } + const fetchKennzahlen = async () => { + while (true) { + try { + console.log("Fetching kennzahlen from API..."); + const data = await fetchK(); + console.log("Fetched kennzahlen:", data); + const sortedData = data.sort((a, b) => a.position - b.position); + setKennzahlen(sortedData); + setLoading(false); + break; + } catch (err) { + console.error("Error fetching kennzahlen:", err); + await new Promise((resolve) => setTimeout(resolve, 2000)); } - }; + } + }; + + useEffect(() => { fetchKennzahlen(); }, []); + useEffect(() => { + if (trainingRunning === false) { + console.log("[ConfigTable] Training beendet → Kennzahlen neu laden..."); + fetchKennzahlen(); + } + }, [trainingRunning]); + + + const handleToggleActive = async (id: number) => { const kennzahl = kennzahlen.find((k) => k.id === id); if (!kennzahl) return; @@ -326,15 +341,32 @@ export function ConfigTable({ from }: ConfigTableProps) { padding: "12px", fontSize: "14px", color: "#333", + display: "flex", + alignItems: "center", + gap: "8px", }} > {kennzahl.name} - {kennzahl.mandatory && ( - * - )} + {kennzahl.mandatory && *} + {kennzahl.is_trained === false && ( + + Diese Kennzahl ist nicht trainiert.
+ Klicken Sie oben auf "Neu trainieren", um das Training zu starten. + + } + arrow + placement="right" + > + +
+ )} + + ) => Promise; onCancel: () => void; loading?: boolean; + resetTrigger?: number; } const emptyKPI: Partial = { name: '', - description: '', mandatory: false, type: 'string', - translation: '', - example: '', - active: true + active: true, + examples: [{ sentence: '', value: '' }], }; -export function KPIForm({ mode, initialData, onSave, onCancel, loading = false }: KPIFormProps) { + +export function KPIForm({ mode, initialData, onSave, onCancel, loading = false, resetTrigger }: KPIFormProps) { const [formData, setFormData] = useState>(emptyKPI); const [isSaving, setIsSaving] = useState(false); + const [snackbarOpen, setSnackbarOpen] = useState(false); + const [snackbarMessage, setSnackbarMessage] = useState(""); + const [snackbarSeverity, setSnackbarSeverity] = useState<'success' | 'error' | 'info'>("success"); + useEffect(() => { if (mode === 'edit' && initialData) { setFormData(initialData); - } else { + } else if (mode === 'add') { setFormData(emptyKPI); } }, [mode, initialData]); + useEffect(() => { + if (mode === 'add') { + setFormData(emptyKPI); + } + }, [resetTrigger]); + + + const handleSave = async () => { if (!formData.name?.trim()) { - alert('Name ist erforderlich'); + setSnackbarMessage("Name ist erforderlich"); + setSnackbarSeverity("error"); + setSnackbarOpen(true); + return; } + if (!formData.examples || formData.examples.length === 0) { + setSnackbarMessage("Mindestens ein Beispielsatz ist erforderlich"); + setSnackbarSeverity("error"); + setSnackbarOpen(true); + + return; + } + + for (const ex of formData.examples) { + if (!ex.sentence?.trim() || !ex.value?.trim()) { + setSnackbarMessage('Alle Beispielsätze müssen vollständig sein.'); + setSnackbarSeverity("error"); + setSnackbarOpen(true); + + return; + } + } + + setIsSaving(true); try { - await onSave(formData); - } catch (error) { - console.error('Error saving KPI:', error); + const spacyEntries = generateSpacyEntries(formData); + + // Für jeden einzelnen Beispielsatz: + for (const entry of spacyEntries) { + // im localStorage speichern (zum Debuggen oder Vorschau) + const stored = localStorage.getItem("spacyData"); + const existingData = stored ? JSON.parse(stored) : []; + const updated = [...existingData, entry]; + localStorage.setItem("spacyData", JSON.stringify(updated)); + + // POST Request an das Flask-Backend + const response = await fetch("http://localhost:5050/api/spacy/append-training-entry", { + method: "POST", + headers: { + "Content-Type": "application/json" + }, + body: JSON.stringify(entry) + }); + + const data = await response.json(); + + if (!response.ok) { + throw new Error(data.error || "Fehler beim Aufruf von append-training-entry"); + } + + console.log("SpaCy-Eintrag gespeichert:", data); + } + + // Dann in die DB speichern + await onSave({ + name: formData.name!, + mandatory: formData.mandatory ?? false, + type: formData.type || 'string', + position: formData.position ?? 0, + active: formData.active ?? true, + examples: formData.examples ?? [], + is_trained: false, + }); + // Formular zurücksetzen: + setFormData(emptyKPI); + + + setSnackbarMessage("Beispielsätze gespeichert. Jetzt auf -Neu trainieren- klicken oder weitere Kennzahlen hinzufügen."); + setSnackbarSeverity("success"); + setSnackbarOpen(true); + } catch (e: any) { + // Prüfe auf 409-Fehler + if (e?.message?.includes("409") || e?.response?.status === 409) { + setSnackbarMessage("Diese Kennzahl existiert bereits. Sie können sie unter -Konfiguration- bearbeiten."); + setSnackbarSeverity("info"); + setSnackbarOpen(true); + } else { + setSnackbarMessage(e.message || "Fehler beim Speichern."); + setSnackbarSeverity("error"); + setSnackbarOpen(true); + } + console.error(e); } finally { setIsSaving(false); } + }; + const handleCancel = () => { + setFormData(emptyKPI); onCancel(); }; @@ -58,6 +154,24 @@ export function KPIForm({ mode, initialData, onSave, onCancel, loading = false } setFormData(prev => ({ ...prev, [field]: value })); }; + const updateExample = (index: number, field: 'sentence' | 'value', value: string) => { + const newExamples = [...(formData.examples || [])]; + newExamples[index][field] = value; + updateField('examples', newExamples); + }; + + const addExample = () => { + const newExamples = [...(formData.examples || []), { sentence: '', value: '' }]; + updateField('examples', newExamples); + }; + + const removeExample = (index: number) => { + const newExamples = [...(formData.examples || [])]; + newExamples.splice(index, 1); + updateField('examples', newExamples); + }; + + if (loading) { return ( - - - Kennzahl - - updateField('name', e.target.value)} - sx={{ mb: 2 }} - required - error={!formData.name?.trim()} - helperText={!formData.name?.trim() ? 'Name ist erforderlich' : ''} - /> - - - - - - - Beschreibung - - updateField('description', e.target.value)} - helperText="Beschreibung der Kennzahl" - /> - - - updateField('mandatory', e.target.checked)} - sx={{ color: '#383838' }} - /> - } - label="Erforderlich" + <> + + + + Kennzahl + + updateField('name', e.target.value)} + sx={{ mb: 2 }} + required + error={!formData.name?.trim()} + helperText={!formData.name?.trim() ? 'Name ist erforderlich' : ''} /> - - Die Kennzahl erlaubt keine leeren Werte + + + + + + + Format: {typeDisplayMapping[formData.type as keyof typeof typeDisplayMapping] || formData.type} + + + Typ + + + + + + {mode === 'add' && ( + <> + + + updateField('active', e.target.checked)} + sx={{ color: '#383838' }} + /> + } + label="Aktiv" + /> + + Die Kennzahl ist aktiv und wird angezeigt + + + + updateField('mandatory', e.target.checked)} + sx={{ color: '#383838' }} + /> + } + label="Erforderlich" + /> + + Die Kennzahl erlaubt keine leeren Werte + + + + )} + + + + {/* Hinweistext vor Beispielsätzen */} + + + Hinweis zur Trainingsqualität + + + Damit das System neue Kennzahlen zuverlässig erkennen kann, empfehlen wir mindestens 5 Beispielsätze zu erstellen – je mehr, desto besser. + + + Wichtig: Neue Kennzahlen werden erst in PDF-Dokumenten erkannt, wenn Sie den Button "Neu trainieren" auf der Konfigurationsseite ausführen. + + + Tipp: Sie können jederzeit weitere Beispielsätze hinzufügen oder vorhandene in der Kennzahlenverwaltung bearbeiten. - - + - - - Format: {typeDisplayMapping[formData.type as keyof typeof typeDisplayMapping] || formData.type} - - - Typ - - - - - - - - - Synonyme & Übersetzungen - - updateField('translation', e.target.value)} - helperText="z.B. Englische Übersetzung der Kennzahl" - /> - - - - - - - Beispiele von Kennzahl - - updateField('example', e.target.value)} - helperText="Beispielwerte für diese Kennzahl" - /> - - - {mode === 'add' && ( - <> - - - updateField('active', e.target.checked)} - sx={{ color: '#383838' }} - /> - } - label="Aktiv" - /> - - Die Kennzahl ist aktiv und wird angezeigt - - - - )} - - - + + + setSnackbarOpen(false)} + anchorOrigin={{ vertical: 'top', horizontal: 'center' }} + > + setSnackbarOpen(false)} + severity={snackbarSeverity} + sx={{ width: '100%', display: 'flex', justifyContent: 'space-between', alignItems: 'center' }} > - Abbrechen - - - - + {snackbarMessage} + + + + + ); -} \ No newline at end of file +} + + +function generateSpacyEntries(formData: Partial) { + const label = formData.name?.trim().toUpperCase() || ""; + return (formData.examples || []).map(({ sentence, value }) => { + const trimmedValue = value.trim(); + const start = sentence.indexOf(trimmedValue); + if (start === -1) { + throw new Error(`"${trimmedValue}" nicht gefunden in Satz: "${sentence}"`); + } + return { + text: sentence, + entities: [[start, start + trimmedValue.length, label]] + }; + }); +} + + + diff --git a/project/frontend/src/routes/config-add.tsx b/project/frontend/src/routes/config-add.tsx index 26bc90a..15db17a 100644 --- a/project/frontend/src/routes/config-add.tsx +++ b/project/frontend/src/routes/config-add.tsx @@ -5,6 +5,7 @@ import { KPIForm } from "../components/KPIForm"; import type { Kennzahl } from "../types/kpi"; import { API_HOST } from "../util/api"; + export const Route = createFileRoute("/config-add")({ component: ConfigAddPage, validateSearch: (search: Record): { from?: string } => { @@ -47,19 +48,28 @@ function ConfigAddPage() { body: JSON.stringify(kpiData), }); + if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } - navigate({ to: "/config" }); + navigate({ + to: "/config", + search: { success: "true", ...(from ? { from } : {}) }, + }); + } catch (error) { console.error('Error creating KPI:', error); throw error; } }; + const handleCancel = () => { - navigate({ to: "/config" }); + navigate({ + to: "/config", + search: from ? { from } : undefined, + }); }; return ( @@ -83,7 +93,7 @@ function ConfigAddPage() { > - + Neue Kennzahl hinzufügen @@ -93,9 +103,10 @@ function ConfigAddPage() { ); -} \ No newline at end of file +} diff --git a/project/frontend/src/routes/config-detail.$kpiId.tsx b/project/frontend/src/routes/config-detail.$kpiId.tsx index 04ef98c..425ff0d 100644 --- a/project/frontend/src/routes/config-detail.$kpiId.tsx +++ b/project/frontend/src/routes/config-detail.$kpiId.tsx @@ -1,5 +1,6 @@ import { createFileRoute, useNavigate } from "@tanstack/react-router"; -import { Box, Typography, IconButton, Button, CircularProgress, Paper, Divider +import { + Box, Typography, IconButton, Button, CircularProgress, Paper, Divider } from "@mui/material"; import ArrowBackIcon from "@mui/icons-material/ArrowBack"; import { useEffect, useState } from "react"; @@ -38,6 +39,7 @@ function KPIDetailPage() { try { setLoading(true); const response = await fetch(`${API_HOST}/api/kpi_setting/${kpiId}`); + if (!response.ok) { if (response.status === 404) { setError('KPI not found'); @@ -72,7 +74,6 @@ function KPIDetailPage() { if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } - const updatedKennzahl = await response.json(); setKennzahl(updatedKennzahl); setIsEditing(false); @@ -82,6 +83,7 @@ function KPIDetailPage() { } }; + const handleCancel = () => { setIsEditing(false); }; @@ -153,7 +155,7 @@ function KPIDetailPage() { > - + Detailansicht @@ -192,18 +194,13 @@ function KPIDetailPage() { - - Beschreibung + + Erforderlich: - - {kennzahl.description || "Zurzeit ist die Beschreibung der Kennzahl leer. Klicken Sie auf den Bearbeiten-Button, um die Beschreibung zu ergänzen."} + + {kennzahl.mandatory ? 'Ja' : 'Nein'} - - - Erforderlich: {kennzahl.mandatory ? 'Ja' : 'Nein'} - - @@ -216,28 +213,6 @@ function KPIDetailPage() { {typeDisplayMapping[kennzahl.type] || kennzahl.type} - - - - - - Synonyme & Übersetzungen - - - {kennzahl.translation || "Zurzeit gibt es keine Einträge für Synonyme und Übersetzungen der Kennzahl. Klicken Sie auf den Bearbeiten-Button, um die Liste zu ergänzen."} - - - - - - - - Beispiele von Kennzahl - - - {kennzahl.example || "Zurzeit gibt es keine Beispiele der Kennzahl. Klicken Sie auf den Bearbeiten-Button, um die Liste zu ergänzen."} - - ); @@ -264,7 +239,7 @@ function KPIDetailPage() { > - + Kennzahl bearbeiten @@ -280,4 +255,4 @@ function KPIDetailPage() { /> ); -} \ No newline at end of file +} diff --git a/project/frontend/src/routes/config.tsx b/project/frontend/src/routes/config.tsx index ac64c3d..eef808b 100644 --- a/project/frontend/src/routes/config.tsx +++ b/project/frontend/src/routes/config.tsx @@ -3,18 +3,87 @@ import { Box, Button, IconButton, Typography } from "@mui/material"; import ArrowBackIcon from "@mui/icons-material/ArrowBack"; import { useNavigate } from "@tanstack/react-router"; import { ConfigTable } from "../components/ConfigTable"; +import { API_HOST } from "../util/api"; +import Snackbar from "@mui/material/Snackbar"; +import MuiAlert from "@mui/material/Alert"; +import { useState, useEffect } from "react"; +import CircularProgress from "@mui/material/CircularProgress"; +import Tooltip from "@mui/material/Tooltip"; + + + + export const Route = createFileRoute("/config")({ component: ConfigPage, - validateSearch: (search: Record): { from?: string } => { - const from = typeof search.from === "string" ? search.from : undefined; - return { from }; + validateSearch: (search: Record): { from?: string; success?: string } => { + return { + from: typeof search.from === "string" ? search.from : undefined, + success: typeof search.success === "string" ? search.success : undefined + }; } + }); function ConfigPage() { const navigate = useNavigate(); - const { from } = Route.useSearch(); + const { from, success } = Route.useSearch(); + const [snackbarOpen, setSnackbarOpen] = useState(success === "true"); + const [snackbarMessage, setSnackbarMessage] = useState("Beispielsätze gespeichert. Jetzt auf -Neu trainieren- klicken oder zuerst weitere Kennzahlen hinzufügen."); + const [trainingRunning, setTrainingRunning] = useState(false); + const [hasUntrainedKPIs, setHasUntrainedKPIs] = useState(false); + + + const fetchKPISettings = async () => { + try { + const res = await fetch(`${API_HOST}/api/kpi/settings`); + const data = await res.json(); + const untrainedExists = data.some((kpi: any) => { + return kpi.is_trained === false; + }); + setHasUntrainedKPIs(untrainedExists); + } catch (err) { + console.error("Fehler beim Laden der KPIs:", err); + } + }; + + + useEffect(() => { + fetchKPISettings(); + }, []); + + + + useEffect(() => { + if (success === "true") { + setTimeout(() => { + navigate({ + to: "/config", + search: from ? { from } : undefined, + replace: true + }); + + }, 100); + } + }, [success]); + + useEffect(() => { + const checkInitialTrainingStatus = async () => { + try { + const res = await fetch(`${API_HOST}/api/spacy/train-status`); + const data = await res.json(); + if (data.running) { + setTrainingRunning(true); + pollTrainingStatus(); + } + } catch (err) { + console.error("Initiale Trainingsstatus-Abfrage fehlgeschlagen", err); + } + }; + + checkInitialTrainingStatus(); + }, []); + const handleAddNewKPI = () => { navigate({ @@ -31,46 +100,160 @@ function ConfigPage() { } }; + const handleTriggerTraining = async () => { + setTrainingRunning(true); + + try { + const response = await fetch(`${API_HOST}/api/spacy/train`, { + method: "POST", + }); + + if (!response.ok) throw new Error("Training konnte nicht gestartet werden"); + + // Erfolgsmeldung erst hier anzeigen + setSnackbarMessage("Training wurde gestartet."); + setSnackbarOpen(true); + + pollTrainingStatus(); // jetzt starten + } catch (err) { + console.error(err); + setSnackbarMessage("Fehler beim Starten des Trainings."); + setSnackbarOpen(true); + setTrainingRunning(false); + } + }; + + + const pollTrainingStatus = () => { + const interval = setInterval(async () => { + try { + const res = await fetch(`${API_HOST}/api/spacy/train-status`); + const data = await res.json(); + console.log("Trainingsstatus:", data); //Debug-Ausgabe + if (!data.running) { + clearInterval(interval); + console.log("Training abgeschlossen – Snackbar wird ausgelöst"); + setSnackbarMessage("Training abgeschlossen!"); + setSnackbarOpen(true); + setTrainingRunning(false); + + fetchKPISettings(); + + + } + } catch (err) { + console.error("Polling-Fehler:", err); + clearInterval(interval); + } + }, 3000); + }; + + return ( - + <> - - - - - - Konfiguration der Kennzahlen - - - + {/* Linke Seite: Zurück & Titel */} + + + + + + Konfiguration der Kennzahlen + + + + + {trainingRunning || !hasUntrainedKPIs ? ( + + + + + + ) : ( + + )} + + + + + + + + + {/* Tabelle */} + + + - - - - + + {/* Snackbar */} + setSnackbarOpen(false)} + anchorOrigin={{ vertical: "top", horizontal: "center" }} + > + setSnackbarOpen(false)} + severity="success" + sx={{ width: "100%" }} + > + {snackbarMessage} + + + ); } \ No newline at end of file diff --git a/project/frontend/src/types/kpi.ts b/project/frontend/src/types/kpi.ts index c8d66da..7674237 100644 --- a/project/frontend/src/types/kpi.ts +++ b/project/frontend/src/types/kpi.ts @@ -1,13 +1,17 @@ export interface Kennzahl { id: number; name: string; - description: string; mandatory: boolean; type: string; - translation: string; - example: string; position: number; active: boolean; + exampleText?: string; + markedValue?: string; + examples?: { + sentence: string; + value: string; + }[]; + is_trained?: boolean; } export const typeDisplayMapping: Record = { diff --git a/project/frontend/vite.config.js b/project/frontend/vite.config.js index 059d9e2..582fe7c 100644 --- a/project/frontend/vite.config.js +++ b/project/frontend/vite.config.js @@ -5,6 +5,9 @@ import { defineConfig } from "vite"; // https://vitejs.dev/config/ export default defineConfig({ plugins: [TanStackRouterVite({ autoCodeSplitting: true }), viteReact()], + build: { + chunkSizeWarningLimit: 1000, // default ist 500 + }, test: { globals: true, environment: "jsdom",