Add Flask-CORS and SocketIO for real-time updates, refactor database handling to use a temporary Flask app; improve error handling with @app.errorhandler decorators.
This commit is contained in:
@@ -69,21 +69,22 @@ class NeuralNetworkBackground {
|
||||
|
||||
// Konfigurationsobjekt für subtilere, sanftere Neuronen
|
||||
this.config = {
|
||||
nodeCount: 60, // Weniger Knoten für bessere Leistung und subtileres Aussehen
|
||||
nodeSize: 2.8, // Kleinere Knoten für dezenteres Erscheinungsbild
|
||||
nodeVariation: 0.6, // Weniger Varianz für gleichmäßigeres Erscheinungsbild
|
||||
connectionDistance: 220, // Etwas geringere Verbindungsdistanz
|
||||
connectionOpacity: 0.15, // Transparentere Verbindungen
|
||||
nodeCount: 45, // Weniger Knoten für bessere Leistung und subtileres Aussehen
|
||||
nodeSize: 3.5, // Größere Knoten für bessere Sichtbarkeit
|
||||
nodeVariation: 0.5, // Weniger Varianz für gleichmäßigeres Erscheinungsbild
|
||||
connectionDistance: 250, // Größere Verbindungsdistanz
|
||||
connectionOpacity: 0.22, // Deutlichere Verbindungen
|
||||
animationSpeed: 0.02, // Langsamere Animation für sanftere Bewegung
|
||||
pulseSpeed: 0.002, // Langsameres Pulsieren für subtilere Animation
|
||||
flowSpeed: 0.6, // Langsamer für sanftere Animation
|
||||
flowDensity: 0.002, // Deutlich weniger Blitze für subtileres Erscheinungsbild
|
||||
flowSpeed: 0.6, // Langsamer für bessere Sichtbarkeit
|
||||
flowDensity: 0.005, // Mehr Blitze gleichzeitig erzeugen
|
||||
flowLength: 0.12, // Kürzere Blitze für dezentere Effekte
|
||||
maxConnections: 3, // Weniger Verbindungen für aufgeräumteres Erscheinungsbild
|
||||
clusteringFactor: 0.4, // Moderate Clustering-Stärke
|
||||
linesFadeDuration: 3500, // Längere Dauer für sanfteres Ein-/Ausblenden von Linien (ms)
|
||||
linesWidth: 0.6, // Dünnere unterliegende Linien
|
||||
linesOpacity: 0.25 // Geringere Opazität für Linien
|
||||
maxConnections: 4, // Mehr Verbindungen pro Neuron
|
||||
clusteringFactor: 0.45, // Stärkeres Clustering
|
||||
linesFadeDuration: 4000, // Längere Dauer für sanfteres Ein-/Ausblenden von Linien (ms)
|
||||
linesWidth: 0.9, // Dickere unterliegende Linien für bessere Sichtbarkeit
|
||||
linesOpacity: 0.35, // Höhere Opazität für Linien
|
||||
maxFlowCount: 10 // Maximale Anzahl gleichzeitiger Flüsse
|
||||
};
|
||||
|
||||
// Initialize
|
||||
@@ -373,11 +374,10 @@ class NeuralNetworkBackground {
|
||||
const height = this.canvas.height / (window.devicePixelRatio || 1);
|
||||
const now = Date.now();
|
||||
|
||||
// Simulate neural firing with reduced activity
|
||||
// Setze zunächst alle Neuronen auf inaktiv
|
||||
for (let i = 0; i < this.nodes.length; i++) {
|
||||
const node = this.nodes[i];
|
||||
|
||||
// Update pulse phase for smoother animation
|
||||
const node = this.nodes[i];
|
||||
node.pulsePhase += this.config.pulseSpeed * (1 + (node.connections.length * 0.04));
|
||||
|
||||
// Animate node position with gentler movement
|
||||
@@ -394,57 +394,77 @@ class NeuralNetworkBackground {
|
||||
node.y = Math.max(0, Math.min(height, node.y));
|
||||
}
|
||||
|
||||
// Check if node should fire based on reduced firing rate
|
||||
if (now - node.lastFired > node.firingRate * 1.3) { // 30% langsamere Feuerrate
|
||||
// Setze alle Knoten standardmäßig auf inaktiv
|
||||
node.isActive = false;
|
||||
}
|
||||
|
||||
// Aktiviere Neuronen basierend auf aktiven Flows
|
||||
for (const flow of this.flows) {
|
||||
// Aktiviere den Quellknoten (der Flow geht von ihm aus)
|
||||
if (flow.sourceNodeIdx !== undefined) {
|
||||
this.nodes[flow.sourceNodeIdx].isActive = true;
|
||||
this.nodes[flow.sourceNodeIdx].lastFired = now;
|
||||
}
|
||||
|
||||
// Aktiviere den Zielknoten nur, wenn der Flow weit genug fortgeschritten ist
|
||||
if (flow.targetNodeIdx !== undefined && flow.progress > 0.9) {
|
||||
this.nodes[flow.targetNodeIdx].isActive = true;
|
||||
this.nodes[flow.targetNodeIdx].lastFired = now;
|
||||
}
|
||||
}
|
||||
|
||||
// Zufällig neue Flows zwischen Knoten initiieren
|
||||
if (Math.random() < 0.02) { // 2% Chance in jedem Frame
|
||||
const randomNodeIdx = Math.floor(Math.random() * this.nodes.length);
|
||||
const node = this.nodes[randomNodeIdx];
|
||||
|
||||
// Nur aktivieren, wenn Knoten Verbindungen hat
|
||||
if (node.connections.length > 0) {
|
||||
node.isActive = true;
|
||||
node.lastFired = now;
|
||||
node.activationTime = now; // Track when activation started
|
||||
|
||||
// Activate connected nodes with probability based on connection strength
|
||||
for (const connIndex of node.connections) {
|
||||
// Find the connection
|
||||
const conn = this.connections.find(c =>
|
||||
(c.from === i && c.to === connIndex) || (c.from === connIndex && c.to === i)
|
||||
);
|
||||
// Wähle eine zufällige Verbindung dieses Knotens
|
||||
const randomConnIdx = Math.floor(Math.random() * node.connections.length);
|
||||
const connectedNodeIdx = node.connections[randomConnIdx];
|
||||
|
||||
// Finde die entsprechende Verbindung
|
||||
const conn = this.connections.find(c =>
|
||||
(c.from === randomNodeIdx && c.to === connectedNodeIdx) ||
|
||||
(c.from === connectedNodeIdx && c.to === randomNodeIdx)
|
||||
);
|
||||
|
||||
if (conn) {
|
||||
// Markiere die Verbindung als kürzlich aktiviert
|
||||
conn.lastActivated = now;
|
||||
|
||||
if (conn) {
|
||||
// Mark connection as recently activated
|
||||
conn.lastActivated = now;
|
||||
// Stelle sicher, dass die Verbindung sichtbar bleibt
|
||||
if (conn.fadeState === 'out') {
|
||||
conn.fadeState = 'visible';
|
||||
conn.fadeStartTime = now;
|
||||
}
|
||||
|
||||
// Verbindung soll schneller aufgebaut werden
|
||||
if (conn.progress < 1) {
|
||||
conn.buildSpeed = 0.015 + Math.random() * 0.01;
|
||||
}
|
||||
|
||||
// Erstelle einen neuen Flow, wenn nicht zu viele existieren
|
||||
if (this.flows.length < this.config.maxFlowCount) {
|
||||
// Bestimme die Richtung (vom aktivierten Knoten weg)
|
||||
const direction = conn.from === randomNodeIdx;
|
||||
|
||||
// Wenn eine Verbindung aktiviert wird, verlängere ggf. ihre Sichtbarkeit
|
||||
if (conn.fadeState === 'out') {
|
||||
conn.fadeState = 'visible';
|
||||
conn.fadeStartTime = now;
|
||||
}
|
||||
|
||||
// Verbindung soll schneller aufgebaut werden, wenn ein Neuron feuert
|
||||
if (conn.progress < 1) {
|
||||
conn.buildSpeed = 0.015 + Math.random() * 0.01; // Schnellerer Aufbau während der Aktivierung
|
||||
}
|
||||
|
||||
// Reduzierte Wahrscheinlichkeit für neue Flows
|
||||
if (this.flows.length < 4 && Math.random() < conn.strength * 0.5) { // Reduzierte Wahrscheinlichkeit
|
||||
this.flows.push({
|
||||
connection: conn,
|
||||
progress: 0,
|
||||
direction: conn.from === i, // Flow from activated node
|
||||
length: this.config.flowLength + Math.random() * 0.05, // Geringere Variation
|
||||
intensity: 0.5 + Math.random() * 0.3, // Geringere Intensität für subtilere Darstellung
|
||||
creationTime: now,
|
||||
totalDuration: 1000 + Math.random() * 600 // Längere Dauer für sanftere Animation
|
||||
});
|
||||
}
|
||||
|
||||
// Probability for connected node to activate
|
||||
if (Math.random() < conn.strength * 0.5) {
|
||||
this.nodes[connIndex].isActive = true;
|
||||
this.nodes[connIndex].activationTime = now;
|
||||
this.nodes[connIndex].lastFired = now - Math.random() * 500; // Slight variation
|
||||
}
|
||||
this.flows.push({
|
||||
connection: conn,
|
||||
progress: 0,
|
||||
direction: direction,
|
||||
length: this.config.flowLength + Math.random() * 0.05,
|
||||
creationTime: now,
|
||||
totalDuration: 1000 + Math.random() * 600,
|
||||
sourceNodeIdx: direction ? conn.from : conn.to,
|
||||
targetNodeIdx: direction ? conn.to : conn.from
|
||||
});
|
||||
}
|
||||
}
|
||||
} else if (now - node.lastFired > 400) { // Deactivate after longer period
|
||||
node.isActive = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -466,60 +486,44 @@ class NeuralNetworkBackground {
|
||||
connection.fadeState = 'out';
|
||||
connection.fadeStartTime = now;
|
||||
connection.fadeProgress = 1.0;
|
||||
|
||||
// Setze den Fortschritt zurück, damit die Verbindung neu aufgebaut werden kann
|
||||
if (Math.random() < 0.7) {
|
||||
connection.progress = 0;
|
||||
}
|
||||
}
|
||||
} else if (connection.fadeState === 'out') {
|
||||
// Ausblenden
|
||||
connection.fadeProgress = Math.max(0.0, 1.0 - (elapsedTime / connection.fadeTotalDuration));
|
||||
if (connection.fadeProgress <= 0.0) {
|
||||
// Setze Verbindung zurück, damit sie wieder eingeblendet werden kann
|
||||
if (Math.random() < 0.4) { // 40% Chance, direkt wieder einzublenden
|
||||
connection.fadeState = 'in';
|
||||
connection.fadeStartTime = now;
|
||||
connection.fadeProgress = 0.0;
|
||||
connection.visibleDuration = 10000 + Math.random() * 15000; // Neue Dauer generieren
|
||||
|
||||
// Setze den Fortschritt zurück, damit die Verbindung neu aufgebaut werden kann
|
||||
connection.progress = 0;
|
||||
} else {
|
||||
// Kurze Pause, bevor die Verbindung wieder erscheint
|
||||
connection.fadeState = 'hidden';
|
||||
connection.fadeStartTime = now;
|
||||
connection.hiddenDuration = 3000 + Math.random() * 7000;
|
||||
|
||||
// Setze den Fortschritt zurück, damit die Verbindung neu aufgebaut werden kann
|
||||
connection.progress = 0;
|
||||
}
|
||||
}
|
||||
} else if (connection.fadeState === 'hidden') {
|
||||
// Verbindung ist unsichtbar, warte auf Wiedereinblendung
|
||||
if (elapsedTime > connection.hiddenDuration) {
|
||||
// Ausblenden, aber nie komplett verschwinden
|
||||
connection.fadeProgress = Math.max(0.1, 1.0 - (elapsedTime / connection.fadeTotalDuration));
|
||||
|
||||
// Verbindungen bleiben immer minimal sichtbar (nie komplett unsichtbar)
|
||||
if (connection.fadeProgress <= 0.1) {
|
||||
// Statt Verbindung komplett zu verstecken, setzen wir sie zurück auf "in"
|
||||
connection.fadeState = 'in';
|
||||
connection.fadeStartTime = now;
|
||||
connection.fadeProgress = 0.0;
|
||||
|
||||
// Verbindung wird komplett neu aufgebaut
|
||||
connection.progress = 0;
|
||||
connection.fadeProgress = 0.1; // Minimal sichtbar bleiben
|
||||
connection.visibleDuration = 15000 + Math.random() * 20000; // Längere Sichtbarkeit
|
||||
}
|
||||
} else if (connection.fadeState === 'hidden') {
|
||||
// Keine Verbindungen mehr verstecken, stattdessen immer wieder einblenden
|
||||
connection.fadeState = 'in';
|
||||
connection.fadeStartTime = now;
|
||||
connection.fadeProgress = 0.1;
|
||||
}
|
||||
|
||||
// Animierter Verbindungsaufbau: progress inkrementieren, aber nur wenn aktiv
|
||||
// Verbindungen immer vollständig aufbauen und nicht zurücksetzen
|
||||
if (connection.progress < 1) {
|
||||
// Verbindung wird nur aufgebaut, wenn sie gerade aktiv ist oder ein Blitz sie aufbaut
|
||||
const buildingSpeed = connection.buildSpeed || 0.002; // Langsamer Standard-Aufbau
|
||||
// Konstante Aufbaugeschwindigkeit, unabhängig vom Status
|
||||
const baseBuildSpeed = 0.003;
|
||||
let buildSpeed = connection.buildSpeed || baseBuildSpeed;
|
||||
|
||||
// Bau die Verbindung auf, wenn sie kürzlich aktiviert wurde
|
||||
// Wenn kürzlich aktiviert, schneller aufbauen
|
||||
if (now - connection.lastActivated < 2000) {
|
||||
connection.progress += buildingSpeed;
|
||||
if (connection.progress > 1) connection.progress = 1;
|
||||
buildSpeed = Math.max(buildSpeed, 0.006);
|
||||
}
|
||||
|
||||
// Zurücksetzen der Aufbaugeschwindigkeit
|
||||
connection.buildSpeed = 0;
|
||||
connection.progress += buildSpeed;
|
||||
|
||||
if (connection.progress > 1) {
|
||||
connection.progress = 1;
|
||||
// Zurücksetzen der Aufbaugeschwindigkeit
|
||||
connection.buildSpeed = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -527,7 +531,7 @@ class NeuralNetworkBackground {
|
||||
this.updateFlows(now);
|
||||
|
||||
// Seltener neue Flows erstellen
|
||||
if (Math.random() < this.config.flowDensity * 0.8 && this.flows.length < 4) { // Reduzierte Kapazität und Rate
|
||||
if (Math.random() < this.config.flowDensity && this.flows.length < this.config.maxFlowCount) {
|
||||
this.createNewFlow(now);
|
||||
}
|
||||
|
||||
@@ -560,6 +564,22 @@ class NeuralNetworkBackground {
|
||||
// Update flow progress
|
||||
flow.progress += this.config.flowSpeed / flow.connection.distance;
|
||||
|
||||
// Aktiviere Quell- und Zielknoten basierend auf Flow-Fortschritt
|
||||
if (flow.sourceNodeIdx !== undefined) {
|
||||
// Quellknoten immer aktivieren, solange der Flow aktiv ist
|
||||
this.nodes[flow.sourceNodeIdx].isActive = true;
|
||||
this.nodes[flow.sourceNodeIdx].lastFired = now;
|
||||
}
|
||||
|
||||
// Zielknoten erst aktivieren, wenn der Flow ihn erreicht hat
|
||||
if (flow.targetNodeIdx !== undefined && flow.progress > 0.9) {
|
||||
this.nodes[flow.targetNodeIdx].isActive = true;
|
||||
this.nodes[flow.targetNodeIdx].lastFired = now;
|
||||
}
|
||||
|
||||
// Stellen Sie sicher, dass die Verbindung aktiv bleibt
|
||||
flow.connection.lastActivated = now;
|
||||
|
||||
// Remove completed or expired flows
|
||||
if (flow.progress > 1.0 || flowProgress >= 1.0) {
|
||||
this.flows.splice(i, 1);
|
||||
@@ -1111,11 +1131,11 @@ class NeuralNetworkBackground {
|
||||
// Weniger Funken mit geringerer Vibration
|
||||
const sparks = this.generateSparkPoints(zigzag, 4 + Math.floor(Math.random() * 2));
|
||||
|
||||
// Dezenteres Funkenlicht mit Ein-/Ausblendeffekt
|
||||
const sparkBaseOpacity = this.isDarkMode ? 0.65 : 0.55;
|
||||
// Intensiveres Funkenlicht mit dynamischem Ein-/Ausblendeffekt
|
||||
const sparkBaseOpacity = this.isDarkMode ? 0.75 : 0.65;
|
||||
const sparkBaseColor = this.isDarkMode
|
||||
? `rgba(220, 235, 245, ${sparkBaseOpacity * fadeFactor})`
|
||||
: `rgba(180, 220, 245, ${sparkBaseOpacity * fadeFactor})`;
|
||||
? `rgba(230, 240, 250, ${sparkBaseOpacity * fadeFactor})`
|
||||
: `rgba(190, 230, 250, ${sparkBaseOpacity * fadeFactor})`;
|
||||
|
||||
for (const spark of sparks) {
|
||||
this.ctx.beginPath();
|
||||
@@ -1147,34 +1167,36 @@ class NeuralNetworkBackground {
|
||||
this.ctx.fill();
|
||||
}
|
||||
|
||||
// Dezenterer Fortschrittseffekt an der Spitze des Blitzes
|
||||
if (endProgress >= connProgress - 0.05 && connProgress < 0.95) {
|
||||
// Deutlicherer und länger anhaltender Fortschrittseffekt an der Spitze des Blitzes
|
||||
if (endProgress >= connProgress - 0.1 && connProgress < 0.98) {
|
||||
const tipGlow = this.ctx.createRadialGradient(
|
||||
p2.x, p2.y, 0,
|
||||
p2.x, p2.y, 6
|
||||
p2.x, p2.y, 10
|
||||
);
|
||||
tipGlow.addColorStop(0, `rgba(${rgbFlowColor.r}, ${rgbFlowColor.g}, ${rgbFlowColor.b}, ${0.7 * fadeFactor})`);
|
||||
tipGlow.addColorStop(0, `rgba(${rgbFlowColor.r}, ${rgbFlowColor.g}, ${rgbFlowColor.b}, ${0.85 * fadeFactor})`);
|
||||
tipGlow.addColorStop(0.5, `rgba(${rgbFlowColor.r}, ${rgbFlowColor.g}, ${rgbFlowColor.b}, ${0.4 * fadeFactor})`);
|
||||
tipGlow.addColorStop(1, `rgba(${rgbFlowColor.r}, ${rgbFlowColor.g}, ${rgbFlowColor.b}, 0)`);
|
||||
|
||||
this.ctx.fillStyle = tipGlow;
|
||||
this.ctx.beginPath();
|
||||
this.ctx.arc(p2.x, p2.y, 6, 0, Math.PI * 2);
|
||||
this.ctx.arc(p2.x, p2.y, 10, 0, Math.PI * 2);
|
||||
this.ctx.fill();
|
||||
}
|
||||
|
||||
// Sanftere Start- und Endblitz-Fades
|
||||
if (startProgress < 0.1) {
|
||||
const startFade = startProgress / 0.1; // 0 bis 1
|
||||
// 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, 8 * startFade
|
||||
p1.x, p1.y, 12 * startFade
|
||||
);
|
||||
startGlow.addColorStop(0, `rgba(${rgbFlowColor.r}, ${rgbFlowColor.g}, ${rgbFlowColor.b}, ${0.4 * fadeFactor * 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, 8 * startFade, 0, Math.PI * 2);
|
||||
this.ctx.arc(p1.x, p1.y, 12 * startFade, 0, Math.PI * 2);
|
||||
this.ctx.fill();
|
||||
}
|
||||
|
||||
@@ -1259,11 +1281,11 @@ class NeuralNetworkBackground {
|
||||
return points;
|
||||
}
|
||||
|
||||
// Hilfsfunktion: Erzeuge dezentere Funkenpunkte mit gemäßigter Verteilung
|
||||
generateSparkPoints(zigzag, sparkCount = 4) {
|
||||
// Hilfsfunktion: Erzeuge intensivere Funkenpunkte mit dynamischer Verteilung
|
||||
generateSparkPoints(zigzag, sparkCount = 15) {
|
||||
const sparks = [];
|
||||
// Weniger Funken
|
||||
const actualSparkCount = Math.min(sparkCount, zigzag.length);
|
||||
// Mehr Funken für intensiveren Effekt
|
||||
const actualSparkCount = Math.min(sparkCount, zigzag.length * 2);
|
||||
|
||||
// Funken an zufälligen Stellen entlang des Blitzes
|
||||
for (let i = 0; i < actualSparkCount; i++) {
|
||||
@@ -1280,15 +1302,31 @@ class NeuralNetworkBackground {
|
||||
const x = zigzag[segIndex].x + dx * t;
|
||||
const y = zigzag[segIndex].y + dy * t;
|
||||
|
||||
// Rechtwinkliger Versatz vom Segment (sanftere Verteilung)
|
||||
const offsetAngle = segmentAngle + Math.PI/2;
|
||||
const offsetDistance = Math.random() * 4 - 2; // Geringerer Offset für dezentere Funken
|
||||
// Dynamischer Versatz für intensivere Funken
|
||||
const offsetAngle = segmentAngle + (Math.random() * Math.PI - Math.PI/2);
|
||||
const offsetDistance = Math.random() * 8 - 4; // Größerer Offset für dramatischere Funken
|
||||
|
||||
// Zufällige Größe für variierende Intensität
|
||||
const baseSize = 3.5 + Math.random() * 3.5;
|
||||
const sizeVariation = Math.random() * 2.5;
|
||||
|
||||
sparks.push({
|
||||
x: x + Math.cos(offsetAngle) * offsetDistance,
|
||||
y: y + Math.sin(offsetAngle) * offsetDistance,
|
||||
size: 1 + Math.random() * 1.5 // Kleinere Funkengröße für subtilere Effekte
|
||||
size: baseSize + sizeVariation // Größere und variablere Funkengröße
|
||||
});
|
||||
|
||||
// Zusätzliche kleinere Funken in der Nähe für einen intensiveren Effekt
|
||||
if (Math.random() < 0.4) { // 40% Chance für zusätzliche Funken
|
||||
const subSparkAngle = offsetAngle + (Math.random() * Math.PI/2 - Math.PI/4);
|
||||
const subDistance = offsetDistance * (0.4 + Math.random() * 0.6);
|
||||
|
||||
sparks.push({
|
||||
x: x + Math.cos(subSparkAngle) * subDistance,
|
||||
y: y + Math.sin(subSparkAngle) * subDistance,
|
||||
size: (baseSize + sizeVariation) * 0.6 // Kleinere Größe für sekundäre Funken
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return sparks;
|
||||
|
||||
Reference in New Issue
Block a user