You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
PhishingAwarenessSimulation/Assets/SupabaseEventLogger.cs

561 lines
17 KiB
C#

using UnityEngine;
using UnityEngine.Networking;
using System;
using System.Collections;
using System.Collections.Generic;
public class SupabaseEventLogger : MonoBehaviour
{
public static SupabaseEventLogger Instance;
[Header("Supabase")]
public string supabaseUrl = "https://vihjspljbslozbjzxutl.supabase.co";
public string supabaseAnonKey = "YOUR_ANON_KEY_HERE";
private DateTime sessionStartTime;
private void Awake()
{
if (Instance == null)
Instance = this;
else
Destroy(gameObject);
}
[Serializable]
public class GameEventPayload
{
public string event_key;
public string timestamp;
public string user_id;
}
[Serializable]
public class GameAttemptPayload
{
public string game_id;
public string scenario_id;
public string user_id;
public int attempt_number;
public string start_timestamp;
public string end_timestamp;
public int duration_seconds;
public float final_score_percentage;
public bool pass_fail_status;
public int optimal_decisions_count;
public int suboptimal_decisions_count;
public string key_decisions_log;
}
[Serializable]
public class Decision
{
public string decisionId;
public string timestamp;
public bool optimal;
}
[Serializable]
public class DecisionLogWrapper
{
public List<Decision> decisions;
}
public void StartSession()
{
sessionStartTime = DateTime.UtcNow;
GameEventPayload payload = new GameEventPayload
{
event_key = "game_session_started",
timestamp = sessionStartTime.ToString("o"),
user_id = "user123"
};
StartCoroutine(PostToSupabase("game_events", JsonUtility.ToJson(payload)));
}
public void LogDecisionEvent(bool isOptimal)
{
string eventKey = isOptimal ? "game_optimal_decision_made" : "game_suboptimal_decision_made";
GameEventPayload payload = new GameEventPayload
{
event_key = eventKey,
timestamp = DateTime.UtcNow.ToString("o"),
user_id = "user123"
};
StartCoroutine(PostToSupabase("game_events", JsonUtility.ToJson(payload)));
}
public void CompleteSessionAndSubmitResult(string userId, bool passed, int optimal, int suboptimal, string scenarioId, List<Decision> decisionLog = null)
{
var endTime = DateTime.UtcNow;
int duration = (int)(endTime - sessionStartTime).TotalSeconds;
// Submit game_session_completed event
GameEventPayload completedEvent = new GameEventPayload
{
event_key = "game_session_completed",
timestamp = endTime.ToString("o"),
user_id = userId
};
StartCoroutine(PostToSupabase("game_events", JsonUtility.ToJson(completedEvent)));
// Submit game_score_recorded event
GameEventPayload scoreEvent = new GameEventPayload
{
event_key = "game_score_recorded",
timestamp = endTime.ToString("o"),
user_id = userId
};
StartCoroutine(PostToSupabase("game_events", JsonUtility.ToJson(scoreEvent)));
// Submit final game attempt data
GameAttemptPayload attempt = new GameAttemptPayload
{
game_id = "phishing-awareness-1",
scenario_id = scenarioId,
user_id = userId,
attempt_number = 1,
start_timestamp = sessionStartTime.ToString("o"),
end_timestamp = endTime.ToString("o"),
duration_seconds = duration,
final_score_percentage = passed ? 100 : 50,
pass_fail_status = passed,
optimal_decisions_count = optimal,
suboptimal_decisions_count = suboptimal,
key_decisions_log = decisionLog != null ? JsonUtility.ToJson(new DecisionLogWrapper { decisions = decisionLog }) : "[]"
};
StartCoroutine(PostToSupabase("phishing_game_attempts", JsonUtility.ToJson(attempt)));
}
private IEnumerator PostToSupabase(string table, string jsonBody)
{
string url = $"{supabaseUrl}/rest/v1/{table}";
UnityWebRequest request = new UnityWebRequest(url, "POST");
byte[] bodyRaw = System.Text.Encoding.UTF8.GetBytes(jsonBody);
request.uploadHandler = new UploadHandlerRaw(bodyRaw);
request.downloadHandler = new DownloadHandlerBuffer();
request.SetRequestHeader("Content-Type", "application/json");
request.SetRequestHeader("apikey", supabaseAnonKey);
request.SetRequestHeader("Authorization", "Bearer " + supabaseAnonKey);
request.SetRequestHeader("Prefer", "return=representation");
yield return request.SendWebRequest();
if (request.result == UnityWebRequest.Result.Success)
{
Debug.Log($"✅ Supabase POST to {table}: " + request.downloadHandler.text);
}
else
{
Debug.LogError($"❌ Supabase POST Failed ({table}): {request.responseCode}\n{request.error}\n{request.downloadHandler.text}");
}
}
}
//using UnityEngine;
//using System;
//using System.Collections;
//using System.Collections.Generic;
//using System.Threading.Tasks;
//using Supabase;
//using Postgrest.Models;
//using Postgrest.Attributes;
//using static SupabaseTestInsert;
//[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; }
//}
//public class SupabaseEventLogger : MonoBehaviour
//{
// public static SupabaseEventLogger Instance;
// private DateTime sessionStartTime;
// private void Awake()
// {
// if (Instance == null)
// Instance = this;
// else
// Destroy(gameObject);
// }
// public void StartSession()
// {
// StartCoroutine(StartSessionCoroutine());
// }
// private IEnumerator StartSessionCoroutine()
// {
// var task = StartSessionAsync();
// while (!task.IsCompleted)
// yield return null;
// if (task.Exception != null)
// Debug.LogError("❌ Supabase Error: " + task.Exception.InnerException?.Message);
// }
// private async Task StartSessionAsync()
// {
// sessionStartTime = DateTime.UtcNow;
// var gameEvent = new GameEvent
// {
// Id = Guid.NewGuid(),
// EventKey = "game_session_started",
// Timestamp = sessionStartTime,
// UserId = "user123"
// };
// await Client.Instance.From<GameEvent>().Insert(gameEvent);
// Debug.Log("✅ Supabase Event: game_session_started");
// }
// public void LogDecisionEvent(bool isOptimal)
// {
// StartCoroutine(LogDecisionCoroutine(isOptimal));
// }
// private IEnumerator LogDecisionCoroutine(bool isOptimal)
// {
// var task = LogDecisionAsync(isOptimal);
// while (!task.IsCompleted)
// yield return null;
// if (task.Exception != null)
// Debug.LogError("❌ Supabase Error: " + task.Exception.InnerException?.Message);
// }
// private async Task LogDecisionAsync(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<GameEvent>().Insert(gameEvent);
// Debug.Log($"✅ Supabase Event: {eventKey}");
// }
// public void CompleteSessionAndSubmitResult(string userId, bool passed, int optimal, int suboptimal, string scenarioId, List<Decision> decisionLog = null)
// {
// StartCoroutine(CompleteSessionCoroutine(userId, passed, optimal, suboptimal, scenarioId, decisionLog));
// }
// private IEnumerator CompleteSessionCoroutine(string userId, bool passed, int optimal, int suboptimal, string scenarioId, List<Decision> decisionLog)
// {
// var task = CompleteSessionAsync(userId, passed, optimal, suboptimal, scenarioId, decisionLog);
// while (!task.IsCompleted)
// yield return null;
// if (task.Exception != null)
// Debug.LogError("❌ Supabase Error: " + task.Exception.InnerException?.Message);
// }
// private async Task CompleteSessionAsync(string userId, bool passed, int optimal, int suboptimal, string scenarioId, List<Decision> decisionLog)
// {
// var endTime = DateTime.UtcNow;
// int duration = (int)(endTime - sessionStartTime).TotalSeconds;
// await Client.Instance.From<GameEvent>().Insert(new GameEvent
// {
// Id = Guid.NewGuid(),
// EventKey = "game_session_completed",
// Timestamp = endTime,
// UserId = userId
// });
// await Client.Instance.From<GameEvent>().Insert(new GameEvent
// {
// Id = Guid.NewGuid(),
// EventKey = "game_score_recorded",
// Timestamp = endTime,
// UserId = userId
// });
// var gameAttempt = new GameAttempt
// {
// Id = Guid.NewGuid(),
// 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<GameAttempt>().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<Decision> decisions;
// }
//}
////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);
//// }
//// /// <summary>
//// /// Call this at the start of the game session.
//// /// </summary>
//// 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<GameEvent>().Insert(gameEvent);
//// Debug.Log("✅ Supabase Event: game_session_started");
//// }
//// /// <summary>
//// /// Logs optimal/suboptimal decisions at runtime.
//// /// </summary>
//// 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<GameEvent>().Insert(gameEvent);
//// Debug.Log($"✅ Supabase Event: {eventKey}");
//// }
//// /// <summary>
//// /// Completes the session and submits full results to phishing_game_attempts table.
//// /// </summary>
//// public async void CompleteSessionAndSubmitResult(string userId, bool passed, int optimal, int suboptimal, string scenarioId, List<Decision> decisionLog = null)
//// {
//// var endTime = DateTime.UtcNow;
//// int duration = (int)(endTime - sessionStartTime).TotalSeconds;
//// // Log completion events
//// await Client.Instance.From<GameEvent>().Insert(new GameEvent
//// {
//// Id = Guid.NewGuid(),
//// EventKey = "game_session_completed",
//// Timestamp = endTime,
//// UserId = userId
//// });
//// await Client.Instance.From<GameEvent>().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<GameAttempt>().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<Decision> 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; }
////}