From 7530c2aa459774c08cbfe7a2fd3cd32c1f799ce5 Mon Sep 17 00:00:00 2001 From: ALicja Date: Fri, 30 Jan 2026 18:08:36 +0100 Subject: [PATCH] dodanie funkcji --- .idea/.gitignore | 10 - .idea/Pathl.Stona.iml | 21 ++ .idea/Strona AI.iml | 10 - .idea/misc.xml | 4 +- .idea/modules.xml | 2 +- .idea/vcs.xml | 2 +- .idea/workspace.xml | 107 ++++++++++ __pycache__/app.cpython-313.pyc | Bin 0 -> 7156 bytes apks/__pycache__/mk.cpython-313.pyc | Bin 0 -> 343 bytes apks/mk.py | 5 + app.py | 188 +++++++++++------- interpreter.py | 73 +++++++ .../Power/__pycache__/model.cpython-313.pyc | Bin 665 -> 651 bytes static/style.css | 134 +++++++++++-- templates/editor.html | 169 ++++++++++++++++ templates/user.html | 87 +++++--- 16 files changed, 676 insertions(+), 136 deletions(-) delete mode 100644 .idea/.gitignore create mode 100644 .idea/Pathl.Stona.iml delete mode 100644 .idea/Strona AI.iml create mode 100644 .idea/workspace.xml create mode 100644 __pycache__/app.cpython-313.pyc create mode 100644 apks/__pycache__/mk.cpython-313.pyc create mode 100644 apks/mk.py create mode 100644 interpreter.py create mode 100644 templates/editor.html diff --git a/.idea/.gitignore b/.idea/.gitignore deleted file mode 100644 index ab1f416..0000000 --- a/.idea/.gitignore +++ /dev/null @@ -1,10 +0,0 @@ -# Default ignored files -/shelf/ -/workspace.xml -# Ignored default folder with query files -/queries/ -# Datasource local storage ignored files -/dataSources/ -/dataSources.local.xml -# Editor-based HTTP Client requests -/httpRequests/ diff --git a/.idea/Pathl.Stona.iml b/.idea/Pathl.Stona.iml new file mode 100644 index 0000000..024b922 --- /dev/null +++ b/.idea/Pathl.Stona.iml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/Strona AI.iml b/.idea/Strona AI.iml deleted file mode 100644 index a55366f..0000000 --- a/.idea/Strona AI.iml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml index 3769195..6b805dc 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,7 +1,7 @@ - - + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml index 34f09f4..1653e50 100644 --- a/.idea/modules.xml +++ b/.idea/modules.xml @@ -2,7 +2,7 @@ - + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml index 94a25f7..35eb1dd 100644 --- a/.idea/vcs.xml +++ b/.idea/vcs.xml @@ -1,6 +1,6 @@ - + \ No newline at end of file diff --git a/.idea/workspace.xml b/.idea/workspace.xml new file mode 100644 index 0000000..aadd831 --- /dev/null +++ b/.idea/workspace.xml @@ -0,0 +1,107 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1769791641577 + + + + + + + + + \ No newline at end of file diff --git a/__pycache__/app.cpython-313.pyc b/__pycache__/app.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1af1a6cc1b9e34cfa8283c6263eb8d34e35502fb GIT binary patch literal 7156 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 Gn*R@Tu8b!D literal 0 HcmV?d00001 diff --git a/apks/__pycache__/mk.cpython-313.pyc b/apks/__pycache__/mk.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c341966a677a9efd6c3daf23a5dcf90a2025b2c9 GIT binary patch literal 343 zcmey&%ge<81TK$jG97{RV-N=h7@>^M0zk%8hF}IMh9ZVwMj*+U&ZNnl%mh;iq(N+E zApQ(8ZYo0rqb`tEVOYuNw~}Ec(=EotTZ~D?AVmraw-og=@^e%5^HTHk^aB!0GII2S zOY-v)^%D!Si}iD}^$IF)F(;;^6mbHTgWT{L#Asl+!OhcY+TimU$YCI0H_#C(3`HRK z6tRE^Rv-bjy@&(IzQtTznpDIKWPznYZZ6^m5`LOYU|Ydb5Un6#h#n4`-29Z%oK(9a dKA;%LVa5DF;sY}yBjYC~Mn=KUY(N5R4gfs)IQRen literal 0 HcmV?d00001 diff --git a/apks/mk.py b/apks/mk.py new file mode 100644 index 0000000..6cddd28 --- /dev/null +++ b/apks/mk.py @@ -0,0 +1,5 @@ +def add(a, b): + return a + b + +def sub(a, b): + return a - b diff --git a/app.py b/app.py index 72eb3fb..9a658a4 100644 --- a/app.py +++ b/app.py @@ -1,17 +1,27 @@ -from flask import Flask, request, render_template, jsonify, send_from_directory -import os, json, importlib.util -from werkzeug.utils import secure_filename -import markdown -app = Flask(__name__) -UPLOAD_FOLDER = "models" -os.makedirs(UPLOAD_FOLDER, exist_ok=True) -ADMIN_KEY = "supersecretadminkey" +from flask import Flask, request, render_template, jsonify, send_file +import os, json, importlib, importlib.util, sys, re +from markdown import markdown +app = Flask(__name__) + +# FOLDERS +UPLOAD_FOLDER = "scripts" +MODELS_FOLDER = "models" +APKS_FOLDER = "apks" +os.makedirs(UPLOAD_FOLDER, exist_ok=True) +os.makedirs(MODELS_FOLDER, exist_ok=True) +sys.path.insert(0, os.path.join(os.getcwd(), APKS_FOLDER)) + +# GLOBAL MODELS MODELS = {} +# ---- Load models at startup ---- def load_models(): - for folder in os.listdir(UPLOAD_FOLDER): - path = os.path.join(UPLOAD_FOLDER, folder) + global MODELS + MODELS = {} + + for folder in os.listdir(MODELS_FOLDER): + path = os.path.join(MODELS_FOLDER, folder) if not os.path.isdir(path): continue meta_path = os.path.join(path, "meta.json") @@ -38,7 +48,8 @@ def load_models(): load_models() -# ---- DASHBOARD ---- + +# ---------------- DASHBOARD ---------------- @app.route("/") def dashboard(): models_with_md = {} @@ -47,16 +58,81 @@ def dashboard(): try: md_path = os.path.join(model["path"], model["meta"]["description_file"]) with open(md_path, "r", encoding="utf-8") as f: - md_text = f.read() - # konwersja Markdown -> HTML - md_content = markdown.markdown(md_text) - except Exception: + md_content = markdown(f.read()) + except: md_content = "

Brak opisu.

" - models_with_md[name] = {**model, "md_content": md_content} return render_template("user.html", models=models_with_md) -# ---- PREDICT ---- + + +# ---------------- EDITOR ---------------- +@app.route("/editor/") +def editor(model_name): + return render_template("editor.html", model_name=model_name) + + +# ---------------- RUN SCRIPT (MKScript) ---------------- +@app.route("/run_script", methods=["POST"]) +def run_script(): + code = request.json.get("code", "") + output = [] + variables = {} + modules = {} + + try: + lines = code.split(";") + for line in lines: + line = line.strip() + if not line: + continue + + # use mk + if line.startswith("use "): + name = line.split()[1] + mod = importlib.import_module(name) + modules[name] = mod + variables[name] = mod + continue + + # print(...) + if line.startswith("print"): + inside = line[line.find("(")+1:line.rfind(")")] + output.append(str(eval_expr(inside, variables))) + continue + + # typy int/float/bool + if any(line.startswith(t) for t in ["int ", "float ", "bool "]): + _, rest = line.split(" ", 1) + var, expr = rest.split("=") + variables[var.strip()] = eval_expr(expr.strip(), variables) + continue + + # wywołanie funkcji np mk.add(1,2) + if "." in line and "(" in line: + obj, rest = line.split(".", 1) + fname = rest[:rest.find("(")] + args = rest[rest.find("(")+1:rest.find(")")] + args = [eval_expr(a.strip(), variables) for a in args.split(",")] + result = getattr(modules[obj], fname)(*args) + variables["_"] = result + continue + + except Exception as e: + return jsonify({"error": str(e)}) + + return jsonify({ + "output": output, + "variables": {k: str(v) for k, v in variables.items()} + }) + + +def eval_expr(expr, variables): + expr = expr.replace("true", "True").replace("false", "False") + return eval(expr, {}, variables) + + +# ---------------- PREDICT ---------------- @app.route("/predict/", methods=["POST"]) def predict(model_name): model_entry = MODELS.get(model_name) @@ -65,9 +141,7 @@ def predict(model_name): func = model_entry["func"] inputs = model_entry["inputs"] - kwargs = {} - for inp in inputs: - kwargs[inp] = request.form.get(inp) + kwargs = {inp: request.form.get(inp) for inp in inputs} try: for k in kwargs: @@ -81,64 +155,28 @@ def predict(model_name): return jsonify({"output": str(output)}) -# ---- ADD MODEL ---- -@app.route("/add_model", methods=["POST"]) -def add_model(): - admin_key = request.form.get("admin_key") - if admin_key != ADMIN_KEY: - return "Brak dostępu", 403 - name = request.form["name"] - function_name = request.form["function_name"] - inputs = request.form.getlist("inputs") - model_py = request.files["model_py"] - description_file = request.files["description"] +# ---------------- DOWNLOAD SCRIPT ---------------- +@app.route("/download_script/") +def download_script(filename): + path = os.path.join(UPLOAD_FOLDER, filename) + if os.path.exists(path): + return send_file(path, as_attachment=True) + return "Plik nie istnieje", 404 - folder_name = secure_filename(name) - folder_path = os.path.join(UPLOAD_FOLDER, folder_name) - os.makedirs(folder_path, exist_ok=True) - # zapis plików - model_py.save(os.path.join(folder_path, "model.py")) - description_file.save(os.path.join(folder_path, "description.md")) +# ---------------- UPLOAD SCRIPT ---------------- +@app.route("/upload_script", methods=["POST"]) +def upload_script(): + file = request.files.get("file") + if not file: + return "Nie przesłano pliku", 400 + filename = file.filename + path = os.path.join(UPLOAD_FOLDER, filename) + file.save(path) + return "OK" - # meta.json - meta = { - "name": name, - "function_name": function_name, - "inputs": inputs, - "description_file": "description.md", - "downloadable": True, # można pobrać pliki - "type": request.form.get("type", "algorithmic") - } - with open(os.path.join(folder_path, "meta.json"), "w") as f: - json.dump(meta, f) - - # załaduj od razu - spec = importlib.util.spec_from_file_location("model_module", os.path.join(folder_path, "model.py")) - module = importlib.util.module_from_spec(spec) - spec.loader.exec_module(module) - func = getattr(module, function_name) - - MODELS[folder_name] = { - "func": func, - "inputs": inputs, - "meta": meta, - "path": folder_path - } - - return "Dodano model!" - -# ---- DOWNLOAD FILE ---- -@app.route("/download//") -def download_file(model_name, file_name): - model_entry = MODELS.get(model_name) - if not model_entry: - return "Model nie istnieje", 404 - folder_path = model_entry["path"] - if file_name not in ["model.py", "description.md", "meta.json"]: - return "Nieprawidłowy plik", 400 - return send_from_directory(folder_path, file_name, as_attachment=True) +# ---------------- MAIN ---------------- if __name__ == "__main__": - app.run(debug=True) + app.run(port=4500) diff --git a/interpreter.py b/interpreter.py new file mode 100644 index 0000000..57c2a0d --- /dev/null +++ b/interpreter.py @@ -0,0 +1,73 @@ +import re, importlib + +variables = {} +modules = {} +functions = {} + +# Rejestracja “handlerów” dla linii +handlers = [] + +def eval_expr(expr): + """Bezpieczne obliczanie wyrażeń z użyciem zmiennych""" + expr = expr.replace("true", "True").replace("false", "False") + return eval(expr, {}, variables) + +def handle_use(line): + if line.startswith("use "): + name = line.split()[1] + modules[name] = importlib.import_module(f"apks.{name}") + variables[name] = modules[name] + return True + return False + +def handle_print(line): + if line.startswith("print"): + inside = re.search(r"\((.*)\)", line).group(1) + print(eval_expr(inside)) + return True + return False + +def handle_var(line): + for t in ["int ", "float ", "bool ", "string "]: + if line.startswith(t): + _, rest = line.split(" ", 1) + var, expr = rest.split("=") + val = expr.strip() + if t.strip() == "string": + val = val.strip('"').strip("'") + else: + val = eval_expr(val) + variables[var.strip()] = val + return True + return False + +def handle_func_call(line): + if "." in line and "(" in line: + obj, rest = line.split(".", 1) + fname = rest[:rest.find("(")] + args_str = rest[rest.find("(")+1:rest.rfind(")")] + args = [eval_expr(a.strip()) for a in args_str.split(",") if a.strip()] + result = getattr(modules[obj], fname)(*args) + variables["_"] = result # ostatni wynik + return True + return False + +# Dodajemy wszystkie handlery do listy +handlers.extend([handle_use, handle_print, handle_var, handle_func_call]) + +def run(code): + """Interpreter MKScript""" + lines = code.split(";") + for line in lines: + line = line.strip() + if not line or line.startswith("//"): # komentarze + continue + + # uruchamiamy wszystkie handlery aż któryś obsłuży linię + handled = False + for h in handlers: + if h(line): + handled = True + break + if not handled: + print(f"Nieznana linia: {line}") diff --git a/models/Power/__pycache__/model.cpython-313.pyc b/models/Power/__pycache__/model.cpython-313.pyc index ecf8832be9f1ce6ad1fe9f614a2383c59b35ec86..00addebf2cd302455ab27db295e4d237fa1d397c 100644 GIT binary patch delta 47 zcmbQq+Re)KnU|M~0SKxdY~(t{D6XTQk)NBYpO>1Sryr15l98hqT#}!cIQb{z0su+% B53&FN delta 61 zcmeBXoyp4enU|M~0SG=X+Q@Z^QPoO6BR@A)KQA>uPd}hCIU}(sH=rm#D>b>KSU + + + +MKScript Editor – {{model_name}} + + + + + + + + + +

MKScript Editor – {{model_name}}

+ +
+ + + + + + + ← Wróć +
+ +
+ +
+ +
+

Console Output

+

+
+ +
+

Debugger (zmienne)

+

+
+ + + + + + + + + diff --git a/templates/user.html b/templates/user.html index e22d990..73f1fed 100644 --- a/templates/user.html +++ b/templates/user.html @@ -1,42 +1,71 @@ - + + AI Models - - + +

Lista modeli AI

+
- {% for name, model in models.items() %} -
-

{{name}}

-
- {{ model.md_content | safe }} -
+{% for name, model in models.items() %} +
+ + -
+ + + + +

{{name}}

+ + +
+ {{ model.md_content | safe }} +
+ + + {% for inp in model.inputs %} - -
+ + {% endfor %} -
-
- {% if model.meta.downloadable %} - - {% endif %} + + + +
+ + + {% if model.meta.downloadable %} + -
- {% endfor %} + {% endif %} + +
+{% endfor %}
+