This repository has been archived on 2026-02-15. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
Benjamin Admin 21a844cb8a fix: Restore all files lost during destructive rebase
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>
2026-02-09 09:51:32 +01:00

318 lines
9.5 KiB
C#

// ==============================================
// GameManager.cs - Zentrale Spielsteuerung
// ==============================================
// Verwaltet Spielzustand, Score, Leben und
// koordiniert alle anderen Manager.
using System;
using UnityEngine;
using UnityEngine.SceneManagement;
namespace BreakpilotDrive
{
public enum GameState
{
MainMenu,
Playing,
Paused,
QuizActive,
GameOver
}
public class GameManager : MonoBehaviour
{
public static GameManager Instance { get; private set; }
[Header("Spieleinstellungen")]
[SerializeField] private int startLives = 3;
[SerializeField] private float pauseQuestionInterval = 500f; // Alle X Meter
[Header("UI Referenzen")]
[SerializeField] private GameObject gameOverPanel;
[SerializeField] private GameObject pausePanel;
// Spielzustand
private GameState currentState = GameState.MainMenu;
private int score = 0;
private int lives;
private float distanceTraveled = 0f;
private float playTime = 0f;
private float nextPauseQuestionDistance;
// Schwierigkeit (von API geladen)
private int currentDifficulty = 3;
private GameDifficulty difficultySettings;
// Events
public event Action<int> OnScoreChanged;
public event Action<int> OnLivesChanged;
public event Action<float> OnDistanceChanged;
public event Action<GameState> OnStateChanged;
// Properties
public GameState CurrentState => currentState;
public int Score => score;
public int Lives => lives;
public float DistanceTraveled => distanceTraveled;
public float PlayTime => playTime;
public int CurrentDifficulty => currentDifficulty;
public GameDifficulty DifficultySettings => difficultySettings;
void Awake()
{
if (Instance == null)
{
Instance = this;
DontDestroyOnLoad(gameObject);
}
else
{
Destroy(gameObject);
}
}
void Start()
{
// UI initial verstecken
if (gameOverPanel) gameOverPanel.SetActive(false);
if (pausePanel) pausePanel.SetActive(false);
}
void Update()
{
if (currentState == GameState.Playing)
{
// Spielzeit zaehlen
playTime += Time.deltaTime;
// Pause-Fragen pruefen
if (distanceTraveled >= nextPauseQuestionDistance)
{
TriggerPauseQuestion();
}
// Escape fuer Pause
if (Input.GetKeyDown(KeyCode.Escape))
{
PauseGame();
}
}
else if (currentState == GameState.Paused)
{
if (Input.GetKeyDown(KeyCode.Escape))
{
ResumeGame();
}
}
}
// ==============================================
// Spiel starten
// ==============================================
public void StartGame(string userId = "guest")
{
// Werte zuruecksetzen
score = 0;
lives = startLives;
distanceTraveled = 0f;
playTime = 0f;
nextPauseQuestionDistance = pauseQuestionInterval;
// Events ausloesen
OnScoreChanged?.Invoke(score);
OnLivesChanged?.Invoke(lives);
// Schwierigkeit laden
if (BreakpilotAPI.Instance != null)
{
StartCoroutine(BreakpilotAPI.Instance.GetLearningLevel(userId,
onSuccess: (level) =>
{
currentDifficulty = level.overall_level;
LoadDifficultySettings();
}
));
}
else
{
LoadDifficultySettings();
}
// Quiz-Statistik zuruecksetzen
if (QuizManager.Instance != null)
{
QuizManager.Instance.ResetStatistics();
}
SetState(GameState.Playing);
}
private void LoadDifficultySettings()
{
if (BreakpilotAPI.Instance != null)
{
StartCoroutine(BreakpilotAPI.Instance.GetDifficulty(currentDifficulty,
onSuccess: (settings) =>
{
difficultySettings = settings;
Debug.Log($"Schwierigkeit {currentDifficulty} geladen: Speed={settings.lane_speed}");
}
));
}
}
// ==============================================
// Score-System
// ==============================================
public void AddScore(int points)
{
score = Mathf.Max(0, score + points);
OnScoreChanged?.Invoke(score);
}
public void AddDistance(float distance)
{
distanceTraveled += distance;
OnDistanceChanged?.Invoke(distanceTraveled);
}
// ==============================================
// Leben-System
// ==============================================
public void LoseLife()
{
lives--;
OnLivesChanged?.Invoke(lives);
if (lives <= 0)
{
GameOver();
}
}
public void GainLife()
{
lives++;
OnLivesChanged?.Invoke(lives);
}
// ==============================================
// Pause-Fragen
// ==============================================
private void TriggerPauseQuestion()
{
nextPauseQuestionDistance += pauseQuestionInterval;
if (BreakpilotAPI.Instance != null && QuizManager.Instance != null)
{
// Pause-Frage aus Cache holen
var questions = BreakpilotAPI.Instance.GetCachedQuestions();
var pauseQuestions = questions.FindAll(q => q.quiz_mode == "pause");
if (pauseQuestions.Count > 0)
{
int index = UnityEngine.Random.Range(0, pauseQuestions.Count);
QuizManager.Instance.ShowPauseQuestion(pauseQuestions[index]);
}
}
}
// ==============================================
// Spielzustand
// ==============================================
public void SetState(GameState newState)
{
currentState = newState;
OnStateChanged?.Invoke(newState);
switch (newState)
{
case GameState.Playing:
Time.timeScale = 1f;
break;
case GameState.Paused:
case GameState.QuizActive:
Time.timeScale = 0f;
break;
case GameState.GameOver:
Time.timeScale = 0f;
break;
}
}
public void PauseGame()
{
if (currentState == GameState.Playing)
{
SetState(GameState.Paused);
if (pausePanel) pausePanel.SetActive(true);
}
}
public void ResumeGame()
{
if (currentState == GameState.Paused)
{
SetState(GameState.Playing);
if (pausePanel) pausePanel.SetActive(false);
}
}
// ==============================================
// Spiel beenden
// ==============================================
public void GameOver()
{
SetState(GameState.GameOver);
if (gameOverPanel) gameOverPanel.SetActive(true);
// Session speichern
SaveSession();
}
private void SaveSession()
{
if (BreakpilotAPI.Instance == null) return;
GameSession session = new GameSession
{
user_id = "guest", // TODO: Echte User-ID
game_mode = "video",
duration_seconds = Mathf.RoundToInt(playTime),
distance_traveled = distanceTraveled,
score = score,
questions_answered = QuizManager.Instance?.GetQuestionsAnswered() ?? 0,
questions_correct = QuizManager.Instance?.GetQuestionsCorrect() ?? 0,
difficulty_level = currentDifficulty
};
StartCoroutine(BreakpilotAPI.Instance.SaveGameSession(session,
onSuccess: (response) =>
{
Debug.Log($"Session gespeichert: {response.session_id}");
if (response.new_level.HasValue)
{
Debug.Log($"Level Up! Neues Level: {response.new_level}");
}
}
));
}
// ==============================================
// Neustart
// ==============================================
public void RestartGame()
{
if (gameOverPanel) gameOverPanel.SetActive(false);
StartGame();
}
public void LoadMainMenu()
{
Time.timeScale = 1f;
SceneManager.LoadScene("MainMenu");
}
}
}