diff --git a/src/Ghosts.Api/Controllers/ViewSocialController.cs b/src/Ghosts.Api/Controllers/ViewSocialController.cs index cc91f594..b70bdede 100644 --- a/src/Ghosts.Api/Controllers/ViewSocialController.cs +++ b/src/Ghosts.Api/Controllers/ViewSocialController.cs @@ -2,155 +2,181 @@ using System; using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; using Ghosts.Api; using Ghosts.Api.Infrastructure; using Microsoft.AspNetCore.Mvc; +using Newtonsoft.Json; using NLog; -namespace ghosts.api.Controllers; - -[Route("view-social")] -[ApiExplorerSettings(IgnoreApi = true)] -public class ViewSocialController : Controller +namespace ghosts.api.Controllers { - private static readonly Logger _log = LogManager.GetCurrentClassLogger(); - private readonly ApplicationSettings _configuration; - - public ViewSocialController() + [Route("view-social")] + [ApiExplorerSettings(IgnoreApi = true)] + public class ViewSocialController : Controller { - this._configuration = Program.ApplicationSettings; - } + private static readonly Logger _log = LogManager.GetCurrentClassLogger(); + private readonly ApplicationSettings _configuration; - [HttpGet] - public IActionResult Index() - { - throw new NotImplementedException(); - // ViewBag.IsEnabled = this._configuration.AnimatorSettings.Animations.SocialGraph.IsEnabled; - // if (!this._configuration.AnimatorSettings.Animations.SocialGraph.IsEnabled) - // { - // return View(); - // } - // - // var path = SocialGraphJob.GetSocialGraphFile(); - // if (!System.IO.File.Exists(path)) - // { - // ViewBag.IsEnabled = false; - // return View(); - // } - // - // var graphs = JsonConvert.DeserializeObject>(System.IO.File.ReadAllText(path)); - // _log.Info($"SocialGraph loaded from disk..."); - // - // return View(graphs); - } + public ViewSocialController(ApplicationSettings configuration) + { + _configuration = configuration; + } - [HttpGet("{id}")] - public IActionResult Detail(Guid id) - { - throw new NotImplementedException(); - // ViewBag.IsEnabled = this._configuration.AnimatorSettings.Animations.SocialGraph.IsEnabled; - // if (!this._configuration.AnimatorSettings.Animations.SocialGraph.IsEnabled) - // { - // return View(); - // } - // - // var path = SocialGraphJob.GetSocialGraphFile(); - // if (!System.IO.File.Exists(path)) - // { - // ViewBag.IsEnabled = false; - // return View(); - // } - // - // var graph = JsonConvert.DeserializeObject>(System.IO.File.ReadAllText(path)).FirstOrDefault(x => x.Id == id); - // _log.Info($"SocialGraph loaded from disk..."); - // - // return View(graph); - } + [HttpGet] + public async Task Index() + { + if (!IsSocialGraphEnabled()) + { + return View(); // Social graph is not enabled, return default view + } - [HttpGet("{id}/interactions")] - public IActionResult Interactions(string id) - { - ViewBag.Id = id; - return View(); - } + var graphs = await LoadSocialGraphsAsync(); + if (graphs == null) + { + return View(); // Return default view if no graphs found + } - [HttpGet("{id}/file")] - public IActionResult File(Guid id) - { - throw new NotImplementedException(); - // var path = SocialGraphJob.GetSocialGraphFile(); - // var graph = JsonConvert.DeserializeObject>(System.IO.File.ReadAllText(path)).FirstOrDefault(x => x.Id == id); - // _log.Info("SocialGraph loaded from disk..."); - // - // var interactions = new InteractionMap(); - // var startTime = DateTime.Now.AddMinutes(-graph.Connections.Count).AddMinutes(-1); - // var endTime = DateTime.Now.AddMinutes(1); - // - // var node = new Node - // { - // id = id.ToString(), - // start = startTime, - // end = endTime - // }; - // interactions.nodes.Add(node); - // - // foreach (var connection in graph.Connections) - // { - // if (connection.Interactions.Count < 1) - // continue; - // node = new Node - // { - // id = connection.Id.ToString(), - // start = startTime.AddMinutes(connection.Interactions.Min(x=>x.Step)), - // end = endTime - // }; - // interactions.nodes.Add(node); - // } - // - // foreach (var learning in graph.Knowledge) - // { - // var link = new Link - // { - // start = startTime.AddMinutes(learning.Step), - // source = learning.To.ToString(), - // target = learning.From.ToString() - // }; - // link.end = link.start.AddMinutes(1); - // interactions.links.Add(link); - // } - // - // // var content = System.IO.File.ReadAllText( - // // "/Users/dustin/Projects/ghosts-animator/src/ghosts-animator-api/wwwroot/view-social/files/5c0e56b44362ec8e2621299d2ddce5ac68e4e1b11e08ac4547075b0e6374d9083a589eec442479ef7876be75215b8499cf9463743191cfe01e4ca3cb826135e5.json"); - // var content = JsonConvert.SerializeObject(interactions); - // var fileBytes = Encoding.ASCII.GetBytes(content); - // return File(fileBytes, "application/json", $"{Guid.NewGuid()}.json"); - } + _log.Info("SocialGraph loaded from disk."); + return View(graphs); // Return the view with the graph data + } + [HttpGet("{id}")] + public async Task Detail(Guid id) + { + if (!IsSocialGraphEnabled()) + { + return View(); // Social graph not enabled + } - public class Link - { - public string source { get; set; } - public string target { get; set; } - public DateTime start { get; set; } - public DateTime end { get; set; } - } + var graph = await LoadGraphByIdAsync(id); + if (graph == null) + { + return NotFound(); // Graph with the given ID was not found + } - public class Node - { - public string id { get; set; } - public DateTime start { get; set; } - public DateTime end { get; set; } - } + _log.Info("SocialGraph loaded from disk."); + return View(graph); // Return view with the graph data + } - public class InteractionMap - { - public List nodes { get; set; } - public List links { get; set; } + [HttpGet("{id}/interactions")] + public IActionResult Interactions(string id) + { + ViewBag.Id = id; + return View(); + } - public InteractionMap() + [HttpGet("{id}/file")] + public async Task File(Guid id) { - this.nodes = new List(); - this.links = new List(); + var graph = await LoadGraphByIdAsync(id); + if (graph == null) + { + return NotFound(); // Graph not found + } + + _log.Info("SocialGraph loaded from disk."); + var interactions = CreateInteractionMap(graph); + + var content = JsonConvert.SerializeObject(interactions); // Serialize the interaction map to JSON + var fileBytes = Encoding.ASCII.GetBytes(content); // Convert JSON to bytes + + return File(fileBytes, "application/json", $"{Guid.NewGuid()}.json"); // Return as a JSON file + } + + private bool IsSocialGraphEnabled() + { + return _configuration.AnimatorSettings.Animations.SocialGraph.IsEnabled; + } + + private async Task> LoadSocialGraphsAsync() + { + var path = SocialGraphJob.GetSocialGraphFile(); + if (!System.IO.File.Exists(path)) + { + return null; // File not found, return null + } + + var json = await System.IO.File.ReadAllTextAsync(path); + return JsonConvert.DeserializeObject>(json); + } + + private async Task LoadGraphByIdAsync(Guid id) + { + var graphs = await LoadSocialGraphsAsync(); + return graphs?.FirstOrDefault(x => x.Id == id); + } + + private InteractionMap CreateInteractionMap(NpcSocialGraph graph) + { + var interactions = new InteractionMap(); + var startTime = DateTime.Now.AddMinutes(-graph.Connections.Count).AddMinutes(-1); // Adjust start time + var endTime = DateTime.Now.AddMinutes(1); // End time + + // Create a node for the main graph + interactions.nodes.Add(new Node + { + id = graph.Id.ToString(), + start = startTime, + end = endTime + }); + + // Add nodes for each connection + foreach (var connection in graph.Connections) + { + if (connection.Interactions.Count < 1) continue; + + interactions.nodes.Add(new Node + { + id = connection.Id.ToString(), + start = startTime.AddMinutes(connection.Interactions.Min(x => x.Step)), + end = endTime + }); + } + + // Add links for each knowledge entry + foreach (var learning in graph.Knowledge) + { + interactions.links.Add(new Link + { + start = startTime.AddMinutes(learning.Step), + source = learning.To.ToString(), + target = learning.From.ToString(), + end = startTime.AddMinutes(1) // Adjusting end time for links + }); + } + + return interactions; + } + + public class Link + { + public string source { get; set; } + public string target { get; set; } + public DateTime start { get; set; } + public DateTime end { get; set; } + } + + public class Node + { + public string id { get; set; } + public DateTime start { get; set; } + public DateTime end { get; set; } + } + + public class InteractionMap + { + public List nodes { get; set; } + public List links { get; set; } + + public InteractionMap() + { + this.nodes = new List(); + this.links = new List(); + } } } -} \ No newline at end of file +}