Fully working Replay in Observation Scene

This commit is contained in:
Thorbjoern
2025-05-26 20:31:19 +02:00
parent c304bc0e10
commit f47331ef81
3 changed files with 4048 additions and 192 deletions
File diff suppressed because it is too large Load Diff
@@ -2,11 +2,10 @@ using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using UnityEngine; using UnityEngine;
using System.Linq; using System.Linq;
using System.Threading.Tasks;
using System; using System;
using System.Reactive;
using UnityEngine.UI; using UnityEngine.UI;
using Postgrest; using Postgrest;
using Cysharp.Threading.Tasks;
namespace GhostSystem namespace GhostSystem
{ {
@@ -40,6 +39,8 @@ namespace GhostSystem
private bool sceneIdReady = false; private bool sceneIdReady = false;
private string loadedSceneId; private string loadedSceneId;
private DateTime latestLoadedTimestamp;
[Serializable] [Serializable]
public class TrackedObjectBinding public class TrackedObjectBinding
{ {
@@ -72,59 +73,106 @@ namespace GhostSystem
TryInitializeReplay(); TryInitializeReplay();
} }
private async void TryInitializeReplay() private async UniTaskVoid TryInitializeReplay()
{ {
if (!supabaseReady || !sceneIdReady) return; if (!supabaseReady || !sceneIdReady) return;
SceneId = loadedSceneId; SceneId = loadedSceneId;
await LoadFrames(); await LoadAllFrames();
StartReplay(); StartReplay();
_ = PeriodicUpdateFrames();
} }
public async Task LoadFrames() public async UniTask LoadAllFrames()
{ {
Debug.Log("SceneId used in query: " + SceneId); Debug.Log("SceneId used in query: " + SceneId);
Debug.Log("StartTime filter: " + dateSelector.selectedDateTime().ToString("o")); Debug.Log("StartTime filter: " + dateSelector.selectedDateTime().ToString("o"));
objectTracks.Clear();
int batchSize = 1000;
int offset = 0;
bool more = true;
List<FrameModel> allFrames = new();
while (more)
{
var query = SupabaseManager.instance.supabase
.From<FrameModel>()
.Filter("scene_id", Postgrest.Constants.Operator.Equals, SceneId)
.Filter("timestamp", Postgrest.Constants.Operator.GreaterThanOrEqual, dateSelector.selectedDateTime().ToString("o"))
.Order("timestamp", Postgrest.Constants.Ordering.Ascending)
.Limit(batchSize) // Limit, wie viele Frames in einem Batch geladen werden. (Standardmäßig 1000)
.Offset(offset); // Um zu wissen, wo der nçhste Batch anfängt
if (!string.IsNullOrEmpty(UserFilter))
query = query.Filter("user_id", Postgrest.Constants.Operator.Equals, UserFilter);
var result = await query.Get();
if (result.Models.Count == 0) break;
allFrames.AddRange(result.Models);
offset += batchSize;
more = result.Models.Count == batchSize;
}
foreach (var frame in allFrames)
{
if (!objectTracks.ContainsKey(frame.ObjectId))
objectTracks[frame.ObjectId] = new List<FrameModel>();
objectTracks[frame.ObjectId].Add(frame);
}
if (allFrames.Count > 1)
{
latestLoadedTimestamp = allFrames.Last().TimestampParsed;
totalDuration = (float)(latestLoadedTimestamp - allFrames.First().TimestampParsed).TotalSeconds;
firstTimestamp = allFrames.First().TimestampParsed.ToLongTimeString();
lastTimestamp = latestLoadedTimestamp.ToLongTimeString();
}
Debug.LogWarning($"Loaded {allFrames.Count} frames across {objectTracks.Count} objects.");
}
private async UniTaskVoid PeriodicUpdateFrames() // lädt alle 10 s neue Frames nach, falls verfügbar
{
while (true)
{
await UniTask.Delay(TimeSpan.FromSeconds(10));
await LoadNewFramesAfter(latestLoadedTimestamp);
}
}
private async UniTask LoadNewFramesAfter(DateTime afterTime) // lädt einen neuen Batch nach.
{
var query = SupabaseManager.instance.supabase var query = SupabaseManager.instance.supabase
.From<FrameModel>() .From<FrameModel>()
.Filter("scene_id", Postgrest.Constants.Operator.Equals, SceneId) .Filter("scene_id", Postgrest.Constants.Operator.Equals, SceneId)
.Filter("timestamp", Postgrest.Constants.Operator.GreaterThanOrEqual, dateSelector.selectedDateTime().ToString("o")) .Filter("timestamp", Postgrest.Constants.Operator.GreaterThan, afterTime.ToString("o"))
.Order("timestamp", Postgrest.Constants.Ordering.Ascending); .Order("timestamp", Postgrest.Constants.Ordering.Ascending);
if (!string.IsNullOrEmpty(UserFilter)) if (!string.IsNullOrEmpty(UserFilter))
query = query.Filter("user_id", Postgrest.Constants.Operator.Equals, UserFilter); query = query.Filter("user_id", Postgrest.Constants.Operator.Equals, UserFilter);
var result = await query.Get(); var result = await query.Get();
var frames = result.Models; var newFrames = result.Models;
Debug.LogError("Frames: " + frames.Count);
objectTracks.Clear(); foreach (var frame in newFrames)
foreach (var frame in frames)
{ {
if (!objectTracks.ContainsKey(frame.ObjectId)) if (!objectTracks.ContainsKey(frame.ObjectId))
objectTracks[frame.ObjectId] = new List<FrameModel>(); objectTracks[frame.ObjectId] = new List<FrameModel>();
objectTracks[frame.ObjectId].Add(frame); objectTracks[frame.ObjectId].Add(frame);
//Debug.Log($"Loaded frame: {frame.ObjectId} at {frame.Timestamp}");
Debug.Log($"Loaded frame: {frame.ObjectId} at {frame.TimestampParsed} Pos: {frame.Position}");
Debug.Log($"Parsed timestamp: {frame.Timestamp} -> {frame.TimestampParsed.ToString("o")}" + "Pos JSON: " + frame.PositionJson);
} }
Debug.LogWarning("Got the Data!");
Debug.LogWarning(objectTracks.Count);
// Gesamtzeit berechnen (in Sekunden) if (newFrames.Count > 0)
if (frames.Count > 1)
{ {
totalDuration = (float)(frames.Last().TimestampParsed - frames.First().TimestampParsed).TotalSeconds; latestLoadedTimestamp = newFrames.Last().TimestampParsed;
firstTimestamp = frames.First().TimestampParsed.ToLongTimeString(); totalDuration = (float)(latestLoadedTimestamp - objectTracks.Values.SelectMany(f => f).First().TimestampParsed).TotalSeconds;
lastTimestamp = frames.Last().TimestampParsed.ToLongTimeString();
} }
Debug.Log($"Appended {newFrames.Count} new frames.");
} }
public void StartReplay() // Für das Play UI-Element, um das Replay zu starten public void StartReplay() // Für das Play UI-Element, um das Replay zu starten
{ {
isPlaying = true; isPlaying = true;
@@ -147,8 +195,7 @@ namespace GhostSystem
private void Update() private void Update()
{ {
if (!isPlaying || objectTracks.Count == 0) if (!isPlaying || objectTracks.Count == 0) return;
return;
playbackTime += Time.deltaTime * PlaybackSpeed; playbackTime += Time.deltaTime * PlaybackSpeed;
@@ -166,12 +213,10 @@ namespace GhostSystem
foreach (var binding in TrackedObjects) foreach (var binding in TrackedObjects)
{ {
if (!objectTracks.ContainsKey(binding.objectId)) if (!objectTracks.ContainsKey(binding.objectId)) continue;
continue;
var frames = objectTracks[binding.objectId]; var frames = objectTracks[binding.objectId];
if (frames.Count < 2) if (frames.Count < 2) continue;
continue;
FrameModel a = null, b = null; FrameModel a = null, b = null;
+2 -2
View File
@@ -13,7 +13,7 @@ public class DateSelector : MonoBehaviour
public void SetYear(int yearIndex) public void SetYear(int yearIndex)
{ {
selectedYear = yearIndex; // Achtung: ggf. +Offset je nach Dropdown-Inhalt selectedYear = yearIndex + 2025; // Achtung: ggf. +Offset je nach Dropdown-Inhalt
} }
public void SetMonth(int monthIndex) public void SetMonth(int monthIndex)
@@ -33,7 +33,7 @@ public class DateSelector : MonoBehaviour
public void SetMinute(int minuteIndex) public void SetMinute(int minuteIndex)
{ {
selectedMinute = minuteIndex; // 059 selectedMinute = minuteIndex * 5; // 059
} }
public DateTime selectedDateTime() public DateTime selectedDateTime()
{ {