using UnityEngine; using System; using System.Collections.Generic; using System.Threading.Tasks; using Supabase; // Make sure SupabaseManager initializes this correctly using Postgrest.Models; using Postgrest.Attributes; public class SupabaseEventLogger : MonoBehaviour { public static SupabaseEventLogger Instance; private DateTime sessionStartTime; private void Awake() { if (Instance == null) Instance = this; else Destroy(gameObject); } /// /// Call this at the start of the game session. /// public async void StartSession() { sessionStartTime = DateTime.UtcNow; var gameEvent = new GameEvent { Id = Guid.NewGuid(), // <== Ensure this is explicitly set EventKey = "game_session_started", Timestamp = sessionStartTime, UserId = "user123" }; await Client.Instance.From().Insert(gameEvent); Debug.Log("✅ Supabase Event: game_session_started"); } /// /// Logs optimal/suboptimal decisions at runtime. /// public async void LogDecisionEvent(bool isOptimal) { string eventKey = isOptimal ? "game_optimal_decision_made" : "game_suboptimal_decision_made"; var gameEvent = new GameEvent { Id = Guid.NewGuid(), EventKey = eventKey, Timestamp = DateTime.UtcNow, UserId = "user123" }; await Client.Instance.From().Insert(gameEvent); Debug.Log($"✅ Supabase Event: {eventKey}"); } /// /// Completes the session and submits full results to phishing_game_attempts table. /// public async void CompleteSessionAndSubmitResult(string userId, bool passed, int optimal, int suboptimal, string scenarioId, List decisionLog = null) { var endTime = DateTime.UtcNow; int duration = (int)(endTime - sessionStartTime).TotalSeconds; // Log completion events await Client.Instance.From().Insert(new GameEvent { Id = Guid.NewGuid(), EventKey = "game_session_completed", Timestamp = endTime, UserId = userId }); await Client.Instance.From().Insert(new GameEvent {Id = Guid.NewGuid(), EventKey = "game_score_recorded", Timestamp = endTime, UserId = userId }); // Insert session result var gameAttempt = new GameAttempt { GameId = "phishing-awareness-1", ScenarioId = scenarioId, UserId = userId, AttemptNumber = 1, StartTime = sessionStartTime, EndTime = endTime, DurationSeconds = duration, Score = passed ? 100 : 50, Passed = passed, Optimal = optimal, Suboptimal = suboptimal, KeyDecisionsLogJson = decisionLog != null ? JsonUtility.ToJson(new DecisionLogWrapper { decisions = decisionLog }) : "[]" }; await Client.Instance.From().Insert(gameAttempt); Debug.Log("✅ Supabase Game Result Submitted"); } [Serializable] public class Decision { public string decisionId; public string timestamp; public bool optimal; } [Serializable] public class DecisionLogWrapper { public List decisions; } } // Existing SupabaseEventLogger class here... // ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ [Table("game_events")] public class GameEvent : BaseModel { [PrimaryKey("id", false)] public Guid Id { get; set; } [Column("event_key")] public string EventKey { get; set; } [Column("timestamp")] public DateTime Timestamp { get; set; } [Column("user_id")] public string UserId { get; set; } } [Table("phishing_game_attempts")] public class GameAttempt : BaseModel { [PrimaryKey("id", false)] public Guid Id { get; set; } = Guid.NewGuid(); [Column("game_id")] public string GameId { get; set; } [Column("scenario_id")] public string ScenarioId { get; set; } [Column("user_id")] public string UserId { get; set; } [Column("attempt_number")] public int AttemptNumber { get; set; } [Column("start_timestamp")] public DateTime StartTime { get; set; } [Column("end_timestamp")] public DateTime EndTime { get; set; } [Column("duration_seconds")] public int DurationSeconds { get; set; } [Column("final_score_percentage")] public float Score { get; set; } [Column("pass_fail_status")] public bool Passed { get; set; } [Column("optimal_decisions_count")] public int Optimal { get; set; } [Column("suboptimal_decisions_count")] public int Suboptimal { get; set; } [Column("key_decisions_log")] public string KeyDecisionsLogJson { get; set; } }