A previous `git pull --rebase origin main` dropped 177 local commits,
losing 3400+ files across admin-v2, backend, studio-v2, website,
klausur-service, and many other services. The partial restore attempt
(660295e2) only recovered some files.
This commit restores all missing files from pre-rebase ref 98933f5e
while preserving post-rebase additions (night-scheduler, night-mode UI,
NightModeWidget dashboard integration).
Restored features include:
- AI Module Sidebar (FAB), OCR Labeling, OCR Compare
- GPU Dashboard, RAG Pipeline, Magic Help
- Klausur-Korrektur (8 files), Abitur-Archiv (5+ files)
- Companion, Zeugnisse-Crawler, Screen Flow
- Full backend, studio-v2, website, klausur-service
- All compliance SDKs, agent-core, voice-service
- CI/CD configs, documentation, scripts
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
293 lines
9.5 KiB
C#
293 lines
9.5 KiB
C#
// ==============================================
|
|
// DifficultyManager.cs - Schwierigkeits-Steuerung
|
|
// ==============================================
|
|
// Passt die Spielschwierigkeit dynamisch an
|
|
// basierend auf Lernniveau und Spielerleistung.
|
|
|
|
using System;
|
|
using UnityEngine;
|
|
|
|
namespace BreakpilotDrive
|
|
{
|
|
public class DifficultyManager : MonoBehaviour
|
|
{
|
|
public static DifficultyManager Instance { get; private set; }
|
|
|
|
[Header("Schwierigkeits-Bereich")]
|
|
[SerializeField] private int minDifficulty = 1;
|
|
[SerializeField] private int maxDifficulty = 5;
|
|
|
|
[Header("Dynamische Anpassung")]
|
|
[SerializeField] private bool enableDynamicDifficulty = true;
|
|
[SerializeField] private int questionsForEvaluation = 5;
|
|
[SerializeField] private float accuracyToIncrease = 0.8f; // 80% richtig = schwerer
|
|
[SerializeField] private float accuracyToDecrease = 0.4f; // 40% richtig = leichter
|
|
|
|
[Header("Geschwindigkeits-Steigerung")]
|
|
[SerializeField] private bool enableSpeedIncrease = true;
|
|
[SerializeField] private float speedIncreaseInterval = 30f; // Alle X Sekunden
|
|
[SerializeField] private float speedIncreaseAmount = 0.5f; // Um X erhoehen
|
|
|
|
// Aktueller Zustand
|
|
private int currentDifficulty = 3;
|
|
private GameDifficulty currentSettings;
|
|
private float timeSinceLastSpeedIncrease = 0f;
|
|
|
|
// Statistik fuer dynamische Anpassung
|
|
private int recentQuestionsAnswered = 0;
|
|
private int recentQuestionsCorrect = 0;
|
|
|
|
// Events
|
|
public event Action<int> OnDifficultyChanged;
|
|
public event Action<GameDifficulty> OnSettingsUpdated;
|
|
|
|
// Properties
|
|
public int CurrentDifficulty => currentDifficulty;
|
|
public GameDifficulty CurrentSettings => currentSettings;
|
|
|
|
void Awake()
|
|
{
|
|
if (Instance == null)
|
|
{
|
|
Instance = this;
|
|
}
|
|
else
|
|
{
|
|
Destroy(gameObject);
|
|
}
|
|
}
|
|
|
|
void Start()
|
|
{
|
|
// Quiz-Events abonnieren
|
|
if (QuizManager.Instance != null)
|
|
{
|
|
QuizManager.Instance.OnQuestionAnswered += OnQuestionAnswered;
|
|
}
|
|
|
|
// Initiale Schwierigkeit laden
|
|
LoadDifficulty(currentDifficulty);
|
|
}
|
|
|
|
void OnDestroy()
|
|
{
|
|
if (QuizManager.Instance != null)
|
|
{
|
|
QuizManager.Instance.OnQuestionAnswered -= OnQuestionAnswered;
|
|
}
|
|
}
|
|
|
|
void Update()
|
|
{
|
|
if (GameManager.Instance?.CurrentState != GameState.Playing)
|
|
return;
|
|
|
|
// Geschwindigkeit graduell erhoehen
|
|
if (enableSpeedIncrease)
|
|
{
|
|
timeSinceLastSpeedIncrease += Time.deltaTime;
|
|
|
|
if (timeSinceLastSpeedIncrease >= speedIncreaseInterval)
|
|
{
|
|
timeSinceLastSpeedIncrease = 0f;
|
|
IncreaseSpeed();
|
|
}
|
|
}
|
|
}
|
|
|
|
// ==============================================
|
|
// Schwierigkeit laden
|
|
// ==============================================
|
|
public void LoadDifficulty(int level)
|
|
{
|
|
currentDifficulty = Mathf.Clamp(level, minDifficulty, maxDifficulty);
|
|
|
|
if (BreakpilotAPI.Instance != null)
|
|
{
|
|
StartCoroutine(BreakpilotAPI.Instance.GetDifficulty(currentDifficulty,
|
|
onSuccess: (settings) =>
|
|
{
|
|
currentSettings = settings;
|
|
ApplySettings(settings);
|
|
OnSettingsUpdated?.Invoke(settings);
|
|
Debug.Log($"Schwierigkeit {currentDifficulty} geladen");
|
|
},
|
|
onError: (error) =>
|
|
{
|
|
Debug.LogWarning($"Konnte Schwierigkeit nicht laden: {error}");
|
|
// Fallback zu Default-Werten
|
|
currentSettings = GetDefaultSettings(currentDifficulty);
|
|
ApplySettings(currentSettings);
|
|
}
|
|
));
|
|
}
|
|
else
|
|
{
|
|
currentSettings = GetDefaultSettings(currentDifficulty);
|
|
ApplySettings(currentSettings);
|
|
}
|
|
|
|
OnDifficultyChanged?.Invoke(currentDifficulty);
|
|
}
|
|
|
|
private void ApplySettings(GameDifficulty settings)
|
|
{
|
|
// Geschwindigkeit anwenden
|
|
if (TrackGenerator.Instance != null)
|
|
{
|
|
TrackGenerator.Instance.SetSpeed(settings.lane_speed);
|
|
}
|
|
|
|
if (PlayerController.Instance != null)
|
|
{
|
|
PlayerController.Instance.SetSpeed(settings.lane_speed);
|
|
}
|
|
|
|
// Hindernis-Frequenz anwenden
|
|
// ObstacleSpawner liest die Settings direkt aus GameManager
|
|
|
|
Debug.Log($"Settings angewendet: Speed={settings.lane_speed}, " +
|
|
$"Obstacles={settings.obstacle_frequency}, " +
|
|
$"Hints={settings.hints_enabled}");
|
|
}
|
|
|
|
// ==============================================
|
|
// Dynamische Anpassung
|
|
// ==============================================
|
|
private void OnQuestionAnswered(bool correct, int points)
|
|
{
|
|
if (!enableDynamicDifficulty) return;
|
|
|
|
recentQuestionsAnswered++;
|
|
if (correct) recentQuestionsCorrect++;
|
|
|
|
// Evaluation nach X Fragen
|
|
if (recentQuestionsAnswered >= questionsForEvaluation)
|
|
{
|
|
EvaluateAndAdjust();
|
|
}
|
|
}
|
|
|
|
private void EvaluateAndAdjust()
|
|
{
|
|
float accuracy = (float)recentQuestionsCorrect / recentQuestionsAnswered;
|
|
|
|
Debug.Log($"Quiz-Evaluation: {recentQuestionsCorrect}/{recentQuestionsAnswered} " +
|
|
$"= {accuracy:P0}");
|
|
|
|
if (accuracy >= accuracyToIncrease && currentDifficulty < maxDifficulty)
|
|
{
|
|
// Spieler ist gut - Schwierigkeit erhoehen
|
|
IncreaseDifficulty();
|
|
}
|
|
else if (accuracy <= accuracyToDecrease && currentDifficulty > minDifficulty)
|
|
{
|
|
// Spieler hat Probleme - Schwierigkeit verringern
|
|
DecreaseDifficulty();
|
|
}
|
|
|
|
// Reset fuer naechste Evaluation
|
|
recentQuestionsAnswered = 0;
|
|
recentQuestionsCorrect = 0;
|
|
}
|
|
|
|
public void IncreaseDifficulty()
|
|
{
|
|
if (currentDifficulty < maxDifficulty)
|
|
{
|
|
LoadDifficulty(currentDifficulty + 1);
|
|
Debug.Log($"Schwierigkeit erhoeht auf {currentDifficulty}");
|
|
}
|
|
}
|
|
|
|
public void DecreaseDifficulty()
|
|
{
|
|
if (currentDifficulty > minDifficulty)
|
|
{
|
|
LoadDifficulty(currentDifficulty - 1);
|
|
Debug.Log($"Schwierigkeit verringert auf {currentDifficulty}");
|
|
}
|
|
}
|
|
|
|
// ==============================================
|
|
// Geschwindigkeits-Steigerung
|
|
// ==============================================
|
|
private void IncreaseSpeed()
|
|
{
|
|
if (currentSettings == null) return;
|
|
|
|
float newSpeed = currentSettings.lane_speed + speedIncreaseAmount;
|
|
|
|
// Maximal-Geschwindigkeit basierend auf Difficulty
|
|
float maxSpeed = 5f + (currentDifficulty * 2f);
|
|
newSpeed = Mathf.Min(newSpeed, maxSpeed);
|
|
|
|
currentSettings.lane_speed = newSpeed;
|
|
|
|
if (TrackGenerator.Instance != null)
|
|
{
|
|
TrackGenerator.Instance.SetSpeed(newSpeed);
|
|
}
|
|
|
|
Debug.Log($"Geschwindigkeit erhoeht auf {newSpeed:F1}");
|
|
}
|
|
|
|
// ==============================================
|
|
// Default-Werte (Fallback)
|
|
// ==============================================
|
|
private GameDifficulty GetDefaultSettings(int level)
|
|
{
|
|
return new GameDifficulty
|
|
{
|
|
lane_speed = 4f + level,
|
|
obstacle_frequency = 0.3f + (level * 0.1f),
|
|
power_up_chance = 0.4f - (level * 0.05f),
|
|
question_complexity = level,
|
|
answer_time = 15 - (level * 2),
|
|
hints_enabled = level <= 2,
|
|
speech_speed = 0.8f + (level * 0.1f)
|
|
};
|
|
}
|
|
|
|
// ==============================================
|
|
// Oeffentliche Methoden
|
|
// ==============================================
|
|
public void SetDifficulty(int level)
|
|
{
|
|
LoadDifficulty(level);
|
|
}
|
|
|
|
public void ResetForNewGame()
|
|
{
|
|
recentQuestionsAnswered = 0;
|
|
recentQuestionsCorrect = 0;
|
|
timeSinceLastSpeedIncrease = 0f;
|
|
|
|
// Schwierigkeit von User-Level laden
|
|
if (BreakpilotAPI.Instance != null)
|
|
{
|
|
var cachedLevel = BreakpilotAPI.Instance.GetCachedLevel();
|
|
if (cachedLevel != null)
|
|
{
|
|
LoadDifficulty(cachedLevel.overall_level);
|
|
}
|
|
}
|
|
}
|
|
|
|
public float GetCurrentSpeed()
|
|
{
|
|
return currentSettings?.lane_speed ?? 5f;
|
|
}
|
|
|
|
public bool AreHintsEnabled()
|
|
{
|
|
return currentSettings?.hints_enabled ?? false;
|
|
}
|
|
|
|
public int GetAnswerTime()
|
|
{
|
|
return currentSettings?.answer_time ?? 10;
|
|
}
|
|
}
|
|
}
|