background, mindmap

This commit is contained in:
2025-04-29 10:27:07 +02:00
parent 0852ea070b
commit 63f45abb3e
9 changed files with 442 additions and 69 deletions

8
.vscode/jsconfig.json vendored Normal file
View File

@@ -0,0 +1,8 @@
{
"compilerOptions": {
"target": "esnext",
"lib": [
"esnext"
]
}
}

68
.vscode/main.js vendored Normal file
View File

@@ -0,0 +1,68 @@
/// <reference types="vscode" />
// @ts-check
// API: https://code.visualstudio.com/api/references/vscode-api
// @ts-ignore
const vscode = require('vscode');
* @typedef {import('vscode').ExtensionContext} ExtensionContext
* @typedef {import('vscode').commands} commands
* @typedef {import('vscode').window} window
* @typedef {import('vscode').TextEditor} TextEditor
* @typedef {import('vscode').TextDocument} TextDocument
*/
/**
* Aktiviert die Erweiterung und registriert den Auto-Resume-Befehl
* @param {vscode.ExtensionContext} context - Der Erweiterungskontext
*/
function activate(context) {
const disposable = vscode.commands.registerCommand('extension.autoResume', () => {
const editor = vscode.window.activeTextEditor;
if (!editor) return;
const document = editor.document;
const text = document.getText();
// Track last click time to avoid multiple clicks
let lastClickTime = 0;
// Main function that looks for and clicks the resume link
function clickResumeLink() {
// Prevent clicking too frequently (3 second cooldown)
const now = Date.now();
if (now - lastClickTime < 3000) return;
// Check if text contains rate limit text
if (text.includes('stop the agent after 25 tool calls') ||
text.includes('Note: we default stop')) {
// Find the resume link position
const resumePos = text.indexOf('resume the conversation');
if (resumePos !== -1) {
vscode.window.showInformationMessage('Auto-resuming conversation...');
lastClickTime = now;
}
}
}
// Führe periodisch aus
const interval = global.setInterval(clickResumeLink, 1000);
// Speichere das Intervall in den Subscriptions
context.subscriptions.push({
dispose: () => global.clearInterval(interval)
});
// Führe die Funktion sofort aus
clickResumeLink();
});
context.subscriptions.push(disposable);
}
function deactivate() {
// Cleanup if needed
}
module.exports = {
activate,
deactivate
}

View File

@@ -16,7 +16,82 @@
- Vergessen der Mindmap-Datenstruktur gemäß der Roadmap - Vergessen der Mindmap-Datenstruktur gemäß der Roadmap
# Häufige Fehler und Lösungen # Häufige Fehler und Lösungen
D
## Datenbankfehler
### Fehler: "no such column: user.password"
**Fehlerbeschreibung:**
```
sqlalchemy.exc.OperationalError: (sqlite3.OperationalError) no such column: user.password
[SQL: SELECT user.id AS user_id, user.username AS user_username, user.email AS user_email, user.password AS user_password, user.created_at AS user_created_at, user.is_active AS user_is_active, user.role AS user_role
FROM user
WHERE user.id = ?]
```
**Ursache:**
Die Spalte `password` fehlt in der Tabelle `user` der SQLite-Datenbank. Dies kann durch eine unvollständige Datenbankinitialisierung oder ein fehlerhaftes Schema-Update verursacht worden sein.
**Lösung:**
1. **Datenbank reparieren mit dem Fix-Skript**
```bash
python fix_user_table.py
```
Dieses Skript:
- Prüft, ob die Tabelle `user` existiert und erstellt sie, falls nicht
- Prüft, ob die Spalte `password` existiert und fügt sie hinzu, falls nicht
2. **Standardbenutzer erstellen**
```bash
python create_default_users.py
```
Dieses Skript:
- Erstellt Standardbenutzer (admin, user), falls keine vorhanden sind
- Setzt Passwörter mit korrektem Hashing
3. **Datenbank testen**
```bash
python test_app.py
```
Dieses Skript überprüft:
- Ob die Datenbank existiert
- Ob die Tabelle `user` korrekt konfiguriert ist
- Ob Benutzer vorhanden sind
## Häufige Ursachen für Datenbankfehler
1. **Inkonsistente Datenbankschemas**
- Unterschiede zwischen dem SQLAlchemy-Modell und der tatsächlichen Datenbankstruktur
- Fehlende Spalten, die in den Modellen definiert sind
2. **Falsche Datenbankinitialisierung**
- Die Datenbank wurde nicht korrekt initialisiert
- Fehler bei der Migration oder dem Schema-Update
3. **Datenbankdatei-Korrumpierung**
- Die SQLite-Datenbankdatei wurde beschädigt
- Lösung: Sicherung wiederherstellen oder Datenbank neu erstellen
## Vorbeugende Maßnahmen
1. **Regelmäßige Backups**
- Tägliche Sicherung der Datenbankdatei
2. **Schema-Validierung**
- Regelmäßige Überprüfung der Datenbankstruktur
- Automatisierte Tests für Datenbankschema
3. **Datenbankmigration**
- Verwenden Sie Flask-Migrate für strukturierte Datenbank-Updates
- Dokumentieren Sie alle Schemaänderungen
## Content Security Policy (CSP) ## Content Security Policy (CSP)
### Problem: Externe Ressourcen werden nicht geladen ### Problem: Externe Ressourcen werden nicht geladen
@@ -79,15 +154,6 @@ D
3. Stellen Sie sicher, dass die Datei `static/css/tailwind.min.css` existiert und aktuell ist. 3. Stellen Sie sicher, dass die Datei `static/css/tailwind.min.css` existiert und aktuell ist.
## Datenbank-Fehler
### Problem: Datenbank existiert nicht
**Fehler:** SQLite-Datenbank kann nicht geöffnet werden.
**Lösung:**
1. Datenbank initialisieren: `python TOOLS.py db:rebuild`
2. Sicherstellen, dass das Datenbankverzeichnis existiert und Schreibrechte hat
## Authentifizierung ## Authentifizierung
### Problem: Login funktioniert nicht ### Problem: Login funktioniert nicht

34
check_schema.py Normal file
View File

@@ -0,0 +1,34 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sqlite3
# Verbindung zur Datenbank herstellen
conn = sqlite3.connect('systades.db')
cursor = conn.cursor()
# Liste aller Tabellen abrufen
print("Alle Tabellen in der Datenbank:")
cursor.execute("SELECT name FROM sqlite_master WHERE type='table';")
tables = cursor.fetchall()
for table in tables:
print(f"- {table[0]}")
# Schema der Datenbank abrufen
cursor.execute("SELECT sql FROM sqlite_master WHERE type='table';")
schemas = cursor.fetchall()
# Schematische Informationen ausgeben
print("\nDatenbankschema:")
for schema in schemas:
print("\n" + str(schema[0]))
# Schema der User-Tabelle genauer untersuchen, falls vorhanden
if ('user',) in tables:
print("\n\nBenutzer-Tabellenschema:")
cursor.execute("PRAGMA table_info(user);")
user_columns = cursor.fetchall()
for column in user_columns:
print(f"Column: {column[1]}, Type: {column[2]}, NOT NULL: {column[3]}, Default: {column[4]}, Primary Key: {column[5]}")
conn.close()

72
create_default_users.py Normal file
View File

@@ -0,0 +1,72 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sqlite3
import os
from werkzeug.security import generate_password_hash
from datetime import datetime
# Prüfen, ob die Datenbank existiert
db_path = 'systades.db'
if not os.path.exists(db_path):
print(f"Datenbank {db_path} existiert nicht.")
exit(1)
# Verbindung zur Datenbank herstellen
conn = sqlite3.connect(db_path)
cursor = conn.cursor()
# Überprüfen, ob bereits Benutzer vorhanden sind
cursor.execute("SELECT COUNT(*) FROM user;")
user_count = cursor.fetchone()[0]
if user_count == 0:
print("Keine Benutzer in der Datenbank gefunden. Erstelle Standardbenutzer...")
# Standardbenutzer definieren
default_users = [
{
'username': 'admin',
'email': 'admin@example.com',
'password': generate_password_hash('admin'),
'created_at': datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S'),
'is_active': 1,
'role': 'admin'
},
{
'username': 'user',
'email': 'user@example.com',
'password': generate_password_hash('user'),
'created_at': datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S'),
'is_active': 1,
'role': 'user'
}
]
# Benutzer einfügen
for user in default_users:
cursor.execute("""
INSERT INTO user (username, email, password, created_at, is_active, role)
VALUES (?, ?, ?, ?, ?, ?);
""", (
user['username'],
user['email'],
user['password'],
user['created_at'],
user['is_active'],
user['role']
))
conn.commit()
print(f"{len(default_users)} Standardbenutzer wurden erstellt.")
else:
print(f"Es sind bereits {user_count} Benutzer in der Datenbank vorhanden.")
# Überprüfen der eingefügten Benutzer
print("\nBenutzer in der Datenbank:")
cursor.execute("SELECT id, username, email, role FROM user;")
users = cursor.fetchall()
for user in users:
print(f"ID: {user[0]}, Benutzername: {user[1]}, E-Mail: {user[2]}, Rolle: {user[3]}")
conn.close()
print("\nBenutzeraktualisierung abgeschlossen.")

70
fix_user_table.py Normal file
View File

@@ -0,0 +1,70 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sqlite3
import os
# Prüfen, ob die Datenbank existiert
db_path = 'systades.db'
if not os.path.exists(db_path):
print(f"Datenbank {db_path} existiert nicht.")
exit(1)
# Verbindung zur Datenbank herstellen
conn = sqlite3.connect(db_path)
cursor = conn.cursor()
# Prüfen, ob die User-Tabelle existiert
cursor.execute("SELECT name FROM sqlite_master WHERE type='table' AND name='user';")
if not cursor.fetchone():
print("Die Tabelle 'user' existiert nicht. Erstelle neue Tabelle...")
cursor.execute('''
CREATE TABLE user (
id INTEGER PRIMARY KEY AUTOINCREMENT,
username VARCHAR(80) NOT NULL UNIQUE,
email VARCHAR(120) NOT NULL UNIQUE,
password VARCHAR(512) NOT NULL,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
is_active BOOLEAN DEFAULT 1,
role VARCHAR(20) DEFAULT 'user'
)
''')
conn.commit()
print("Die Tabelle 'user' wurde erfolgreich erstellt.")
else:
# Überprüfen, ob die Spalte 'password' existiert
cursor.execute("PRAGMA table_info(user);")
columns = cursor.fetchall()
column_names = [column[1] for column in columns]
if 'password' not in column_names:
print("Die Spalte 'password' fehlt in der Tabelle 'user'. Füge Spalte hinzu...")
cursor.execute("ALTER TABLE user ADD COLUMN password VARCHAR(512);")
conn.commit()
print("Die Spalte 'password' wurde erfolgreich hinzugefügt.")
else:
print("Die Spalte 'password' existiert bereits in der Tabelle 'user'.")
# Überprüfen der aktualisierten Spaltenstruktur
print("\nAktualisierte Tabellenspalten der 'user'-Tabelle:")
cursor.execute("PRAGMA table_info(user);")
updated_columns = cursor.fetchall()
for column in updated_columns:
print(f"Column: {column[1]}, Type: {column[2]}, NOT NULL: {column[3]}, Default: {column[4]}, Primary Key: {column[5]}")
# Datenbanktabellen anzeigen
print("\nAlle Tabellen in der Datenbank:")
cursor.execute("SELECT name FROM sqlite_master WHERE type='table';")
tables = cursor.fetchall()
for table in tables:
print(f"- {table[0]}")
# Schemaüberprüfung der user-Tabelle
print("\nSchema der 'user'-Tabelle:")
cursor.execute("SELECT sql FROM sqlite_master WHERE type='table' AND name='user';")
schema = cursor.fetchone()
if schema:
print(schema[0])
conn.close()
print("\nDatenbankaktualisierung abgeschlossen.")

View File

@@ -3,7 +3,7 @@
from app import app, initialize_database, db_path from app import app, initialize_database, db_path
from models import db, User, Thought, Comment, MindMapNode, ThoughtRelation, ThoughtRating, RelationType from models import db, User, Thought, Comment, MindMapNode, ThoughtRelation, ThoughtRating, RelationType
from models import Category, UserMindmap, UserMindmapNode, MindmapNote, NodeRelationship from models import Category, UserMindmap, UserMindmapNode, MindmapNote
import os import os
import sqlite3 import sqlite3
from flask import Flask from flask import Flask

View File

@@ -52,39 +52,39 @@ class NeuralNetworkBackground {
// Colors - Subtilere Farben mit weniger Intensität // Colors - Subtilere Farben mit weniger Intensität
this.darkModeColors = { this.darkModeColors = {
background: '#030610', // Dunkler Hintergrund beibehalten background: '#030610', // Dunkler Hintergrund beibehalten
nodeColor: '#6685cc', // Gedämpftere Knotenfarbe nodeColor: '#5a75b0', // Gedämpftere Knotenfarbe
nodePulse: '#a0b5e0', // Weniger intensives Pulsieren nodePulse: '#94a7d0', // Weniger intensives Pulsieren
connectionColor: '#485880', // Subtilere Verbindungen connectionColor: '#485880', // Subtilere Verbindungen
flowColor: '#c0d7f0' // Sanfteres Blitz-Blau flowColor: '#a0c7e0' // Sanfteres Blitz-Blau
}; };
// Farben für Light Mode dezenter und harmonischer gestalten // Farben für Light Mode dezenter und harmonischer gestalten
this.lightModeColors = { this.lightModeColors = {
background: '#f5f7fa', // Hellerer Hintergrund für subtileren Kontrast background: '#f5f7fa', // Hellerer Hintergrund für subtileren Kontrast
nodeColor: '#5a77c2', // Gedämpfteres Blau nodeColor: '#5570b0', // Gedämpfteres Blau
nodePulse: '#80b9e0', // Sanfteres Türkis für Glow nodePulse: '#7aa8d0', // Sanfteres Türkis für Glow
connectionColor: '#8a8fc0', // Dezenteres Lila connectionColor: '#8a8fc0', // Dezenteres Lila
flowColor: '#6d97d0' // Sanfteres Blau für Blitze flowColor: '#6d97d0' // Sanfteres Blau für Blitze
}; };
// Konfigurationsobjekt für subtilere, sanftere Neuronen // Konfigurationsobjekt für subtilere, sanftere Neuronen
this.config = { this.config = {
nodeCount: 45, // Weniger Knoten für bessere Leistung und subtileres Aussehen nodeCount: 35, // Reduziert für bessere Leistung und subtileres Aussehen
nodeSize: 3.5, // Größere Knoten für bessere Sichtbarkeit nodeSize: 3.5, // Größere Knoten für bessere Sichtbarkeit
nodeVariation: 0.5, // Weniger Varianz für gleichmäßigeres Erscheinungsbild nodeVariation: 0.5, // Weniger Varianz für gleichmäßigeres Erscheinungsbild
connectionDistance: 250, // Größere Verbindungsdistanz connectionDistance: 250, // Größere Verbindungsdistanz
connectionOpacity: 0.22, // Deutlichere Verbindungen connectionOpacity: 0.18, // Schwächere Verbindungen für subtileren Effekt
animationSpeed: 0.02, // Langsamere Animation für sanftere Bewegung animationSpeed: 0.015, // Langsamere Animation für sanftere Bewegung
pulseSpeed: 0.002, // Langsameres Pulsieren für subtilere Animation pulseSpeed: 0.0015, // Langsameres Pulsieren für subtilere Animation
flowSpeed: 0.6, // Langsamer für bessere Sichtbarkeit flowSpeed: 0.45, // Langsamer für bessere Sichtbarkeit
flowDensity: 0.005, // Mehr Blitze gleichzeitig erzeugen flowDensity: 0.003, // Weniger Blitze gleichzeitig erzeugen
flowLength: 0.12, // Kürzere Blitze für dezentere Effekte flowLength: 0.1, // Kürzere Blitze für dezentere Effekte
maxConnections: 4, // Mehr Verbindungen pro Neuron maxConnections: 3, // Weniger Verbindungen pro Neuron
clusteringFactor: 0.45, // Stärkeres Clustering clusteringFactor: 0.45, // Stärkeres Clustering
linesFadeDuration: 4000, // Längere Dauer für sanfteres Ein-/Ausblenden von Linien (ms) linesFadeDuration: 4000, // Längere Dauer für sanfteres Ein-/Ausblenden von Linien (ms)
linesWidth: 0.9, // Dickere unterliegende Linien für bessere Sichtbarkeit linesWidth: 0.7, // Dünnere unterliegende Linien für subtileren Eindruck
linesOpacity: 0.35, // Höhere Opazität für Linien linesOpacity: 0.3, // Geringere Opazität für Linien
maxFlowCount: 10 // Maximale Anzahl gleichzeitiger Flüsse maxFlowCount: 8 // Begrenzte Anzahl gleichzeitiger Flüsse
}; };
// Initialize // Initialize
@@ -414,7 +414,7 @@ class NeuralNetworkBackground {
} }
// Zufällig neue Flows zwischen Knoten initiieren // Zufällig neue Flows zwischen Knoten initiieren
if (Math.random() < 0.02) { // 2% Chance in jedem Frame if (Math.random() < 0.015) { // Reduzierte Chance in jedem Frame (1.5% statt 2%)
const randomNodeIdx = Math.floor(Math.random() * this.nodes.length); const randomNodeIdx = Math.floor(Math.random() * this.nodes.length);
const node = this.nodes[randomNodeIdx]; const node = this.nodes[randomNodeIdx];
@@ -659,8 +659,8 @@ class NeuralNetworkBackground {
positions[i * 2 + 1] = node.y; positions[i * 2 + 1] = node.y;
// Sanftere Pulsation mit moderaterem Aktivierungsboost // Sanftere Pulsation mit moderaterem Aktivierungsboost
const activationBoost = node.isActive ? 1.4 : 1.0; const activationBoost = node.isActive ? 1.3 : 1.0;
let pulse = (Math.sin(node.pulsePhase) * 0.35 + 1.3) * activationBoost; let pulse = (Math.sin(node.pulsePhase) * 0.25 + 1.2) * activationBoost;
// Größe basierend auf Konnektivität und Wichtigkeit, aber subtiler // Größe basierend auf Konnektivität und Wichtigkeit, aber subtiler
const connectivityFactor = 1 + (node.connections.length / this.config.maxConnections) * 1.1; const connectivityFactor = 1 + (node.connections.length / this.config.maxConnections) * 1.1;
@@ -722,7 +722,7 @@ class NeuralNetworkBackground {
this.gl.uniform4f( this.gl.uniform4f(
this.programInfo.uniformLocations.color, this.programInfo.uniformLocations.color,
r, g, b, r, g, b,
node.isActive ? 0.85 : 0.75 // Geringere Sichtbarkeit für subtileres Erscheinungsbild node.isActive ? 0.75 : 0.65 // Geringere Sichtbarkeit für subtileres Erscheinungsbild
); );
// Draw each node individually for better control // Draw each node individually for better control
@@ -744,7 +744,7 @@ class NeuralNetworkBackground {
const y2 = fromNode.y + (toNode.y - fromNode.y) * progress; const y2 = fromNode.y + (toNode.y - fromNode.y) * progress;
// Calculate opacity based on fade state // Calculate opacity based on fade state
let opacity = connection.opacity * connection.fadeProgress; let opacity = connection.opacity * connection.fadeProgress * 0.85; // Reduzierte Gesamtopazität
// Erhöhe kurzzeitig die Opazität bei kürzlich aktivierten Verbindungen // Erhöhe kurzzeitig die Opazität bei kürzlich aktivierten Verbindungen
if (connection.lastActivated && now - connection.lastActivated < 800) { if (connection.lastActivated && now - connection.lastActivated < 800) {
@@ -846,7 +846,7 @@ class NeuralNetworkBackground {
flowColor.r / 255, flowColor.r / 255,
flowColor.g / 255, flowColor.g / 255,
flowColor.b / 255, flowColor.b / 255,
0.55 // Dezent, aber sichtbar 0.7 * fadeFactor // Reduced from higher values
); );
this.gl.enable(this.gl.BLEND); this.gl.enable(this.gl.BLEND);
this.gl.blendFunc(this.gl.SRC_ALPHA, this.gl.ONE); this.gl.blendFunc(this.gl.SRC_ALPHA, this.gl.ONE);
@@ -1107,20 +1107,20 @@ class NeuralNetworkBackground {
this.ctx.beginPath(); this.ctx.beginPath();
this.ctx.moveTo(p1.x, p1.y); this.ctx.moveTo(p1.x, p1.y);
this.ctx.lineTo(p2.x, p2.y); this.ctx.lineTo(p2.x, p2.y);
this.ctx.strokeStyle = `rgba(${rgbFlowColor.r}, ${rgbFlowColor.g}, ${rgbFlowColor.b}, ${0.15 * fadeFactor})`; this.ctx.strokeStyle = `rgba(${rgbFlowColor.r}, ${rgbFlowColor.g}, ${rgbFlowColor.b}, ${0.12 * fadeFactor})`; // Reduziert von 0.15
this.ctx.lineWidth = 3; this.ctx.lineWidth = 2.5; // Reduziert von 3
this.ctx.shadowColor = `rgba(${rgbFlowColor.r}, ${rgbFlowColor.g}, ${rgbFlowColor.b}, ${0.1 * fadeFactor})`; this.ctx.shadowColor = `rgba(${rgbFlowColor.r}, ${rgbFlowColor.g}, ${rgbFlowColor.b}, ${0.08 * fadeFactor})`; // Reduziert von 0.1
this.ctx.shadowBlur = 7; this.ctx.shadowBlur = 6; // Reduziert von 7
this.ctx.stroke(); this.ctx.stroke();
// Zickzack-Blitz mit geringerer Vibration generieren // Zickzack-Blitz mit geringerer Vibration generieren
const zigzag = this.generateZigZagPoints(p1, p2, 6, 7); const zigzag = this.generateZigZagPoints(p1, p2, 6, 7);
// Hauptblitz mit dezenterem Ein-/Ausblendeffekt // Hauptblitz mit dezenterem Ein-/Ausblendeffekt
this.ctx.strokeStyle = `rgba(${rgbFlowColor.r}, ${rgbFlowColor.g}, ${rgbFlowColor.b}, ${0.5 * fadeFactor})`; this.ctx.strokeStyle = `rgba(${rgbFlowColor.r}, ${rgbFlowColor.g}, ${rgbFlowColor.b}, ${0.4 * fadeFactor})`; // Reduziert von 0.5
this.ctx.lineWidth = 1.2; this.ctx.lineWidth = 1.0; // Reduziert von 1.2
this.ctx.shadowColor = `rgba(${rgbFlowColor.r}, ${rgbFlowColor.g}, ${rgbFlowColor.b}, ${0.25 * fadeFactor})`; this.ctx.shadowColor = `rgba(${rgbFlowColor.r}, ${rgbFlowColor.g}, ${rgbFlowColor.b}, ${0.2 * fadeFactor})`; // Reduziert von 0.25
this.ctx.shadowBlur = 6; this.ctx.shadowBlur = 5; // Reduziert von 6
this.ctx.beginPath(); this.ctx.beginPath();
this.ctx.moveTo(zigzag[0].x, zigzag[0].y); this.ctx.moveTo(zigzag[0].x, zigzag[0].y);
for (let i = 1; i < zigzag.length; i++) { for (let i = 1; i < zigzag.length; i++) {
@@ -1128,11 +1128,11 @@ class NeuralNetworkBackground {
} }
this.ctx.stroke(); this.ctx.stroke();
// Weniger Funken mit geringerer Vibration // Intensivere und mehr Funken
const sparks = this.generateSparkPoints(zigzag, 4 + Math.floor(Math.random() * 2)); const sparks = this.generateSparkPoints(zigzag, 8 + Math.floor(Math.random() * 5));
// Intensiveres Funkenlicht mit dynamischem Ein-/Ausblendeffekt // Intensiveres Funkenlicht mit dynamischem Ein-/Ausblendeffekt
const sparkBaseOpacity = this.isDarkMode ? 0.75 : 0.65; const sparkBaseOpacity = this.isDarkMode ? 0.85 : 0.75;
const sparkBaseColor = this.isDarkMode const sparkBaseColor = this.isDarkMode
? `rgba(230, 240, 250, ${sparkBaseOpacity * fadeFactor})` ? `rgba(230, 240, 250, ${sparkBaseOpacity * fadeFactor})`
: `rgba(190, 230, 250, ${sparkBaseOpacity * fadeFactor})`; : `rgba(190, 230, 250, ${sparkBaseOpacity * fadeFactor})`;
@@ -1140,10 +1140,10 @@ class NeuralNetworkBackground {
for (const spark of sparks) { for (const spark of sparks) {
this.ctx.beginPath(); this.ctx.beginPath();
// Subtilere Stern/Funken-Form // Dynamischere Stern/Funken-Form
const points = 4 + Math.floor(Math.random() * 3); // 4-6 Spitzen const points = 4 + Math.floor(Math.random() * 4); // 4-7 Spitzen
const outerRadius = spark.size * 1.8; const outerRadius = spark.size * 2.0;
const innerRadius = spark.size * 0.4; const innerRadius = spark.size * 0.35;
for (let i = 0; i < points * 2; i++) { for (let i = 0; i < points * 2; i++) {
const radius = i % 2 === 0 ? outerRadius : innerRadius; const radius = i % 2 === 0 ? outerRadius : innerRadius;
@@ -1159,12 +1159,24 @@ class NeuralNetworkBackground {
} }
this.ctx.closePath(); this.ctx.closePath();
this.ctx.fillStyle = sparkBaseColor;
// Intensiveres Glühen
this.ctx.shadowColor = this.isDarkMode this.ctx.shadowColor = this.isDarkMode
? `rgba(170, 215, 245, ${0.4 * fadeFactor})` ? `rgba(200, 225, 255, ${0.6 * fadeFactor})`
: `rgba(140, 200, 245, ${0.3 * fadeFactor})`; : `rgba(160, 220, 255, ${0.5 * fadeFactor})`;
this.ctx.shadowBlur = 7; this.ctx.shadowBlur = 12;
this.ctx.fillStyle = sparkBaseColor;
this.ctx.fill(); this.ctx.fill();
// Zusätzlicher innerer Glüheffekt für ausgewählte Funken
if (spark.size > 4 && Math.random() > 0.5) {
this.ctx.beginPath();
this.ctx.arc(spark.x, spark.y, spark.size * 0.6, 0, Math.PI * 2);
this.ctx.fillStyle = this.isDarkMode
? `rgba(240, 250, 255, ${0.7 * fadeFactor})`
: `rgba(220, 240, 255, ${0.6 * fadeFactor})`;
this.ctx.fill();
}
} }
// Deutlicherer und länger anhaltender Fortschrittseffekt an der Spitze des Blitzes // Deutlicherer und länger anhaltender Fortschrittseffekt an der Spitze des Blitzes
@@ -1183,23 +1195,6 @@ class NeuralNetworkBackground {
this.ctx.fill(); this.ctx.fill();
} }
// Verstärkter Start- und Endblitz-Fade mit längerer Sichtbarkeit
if (startProgress < 0.15) {
const startFade = startProgress / 0.15; // 0 bis 1
const startGlow = this.ctx.createRadialGradient(
p1.x, p1.y, 0,
p1.x, p1.y, 12 * startFade
);
startGlow.addColorStop(0, `rgba(${rgbFlowColor.r}, ${rgbFlowColor.g}, ${rgbFlowColor.b}, ${0.6 * fadeFactor * startFade})`);
startGlow.addColorStop(0.7, `rgba(${rgbFlowColor.r}, ${rgbFlowColor.g}, ${rgbFlowColor.b}, ${0.3 * fadeFactor * startFade})`);
startGlow.addColorStop(1, `rgba(${rgbFlowColor.r}, ${rgbFlowColor.g}, ${rgbFlowColor.b}, 0)`);
this.ctx.fillStyle = startGlow;
this.ctx.beginPath();
this.ctx.arc(p1.x, p1.y, 12 * startFade, 0, Math.PI * 2);
this.ctx.fill();
}
this.ctx.restore(); this.ctx.restore();
} }
} }

60
test_app.py Normal file
View File

@@ -0,0 +1,60 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sqlite3
import os
import requests
import time
print("Systades Anwendungstest")
print("=======================")
# Prüfen, ob die Datenbank existiert
db_path = 'systades.db'
if not os.path.exists(db_path):
print(f"Datenbank {db_path} existiert nicht.")
exit(1)
# Datenbankprüfung
conn = sqlite3.connect(db_path)
cursor = conn.cursor()
# Prüfen, ob die User-Tabelle existiert und Benutzer enthält
cursor.execute("SELECT COUNT(*) FROM user;")
user_count = cursor.fetchone()[0]
print(f"Anzahl der Benutzer in der Datenbank: {user_count}")
if user_count == 0:
print("WARNUNG: Keine Benutzer in der Datenbank gefunden!")
print("Bitte führen Sie das Skript 'create_default_users.py' aus, um Standardbenutzer zu erstellen.")
conn.close()
exit(1)
# Tabellenschema prüfen
cursor.execute("PRAGMA table_info(user);")
columns = cursor.fetchall()
column_names = [column[1] for column in columns]
print(f"Spalten in der User-Tabelle: {', '.join(column_names)}")
# Überprüfen, ob die password-Spalte existiert
if 'password' not in column_names:
print("FEHLER: Die Spalte 'password' fehlt in der Tabelle 'user'!")
print("Bitte führen Sie das Skript 'fix_user_table.py' aus, um die Datenbank zu reparieren.")
conn.close()
exit(1)
# Benutzer für Testlogin abrufen
cursor.execute("SELECT username, email FROM user LIMIT 1;")
test_user = cursor.fetchone()
if test_user:
print(f"Testbenutzer für Login: {test_user[0]} (E-Mail: {test_user[1]})")
else:
print("FEHLER: Konnte keinen Testbenutzer abrufen.")
conn.close()
print("\nDie Datenbank scheint korrekt konfiguriert zu sein.")
print("Sie können nun die Anwendung starten und sich mit den folgenden Zugangsdaten anmelden:")
print(" Admin: username=admin, password=admin")
print(" User: username=user, password=user")
print("\nTest abgeschlossen.")