diff --git a/Program.cs b/Program.cs index c3bc553..cbae6bd 100644 --- a/Program.cs +++ b/Program.cs @@ -17,7 +17,7 @@ namespace director { public class Program { - //private static Telefranz tf; + private static Telefranz tf; public static Config directorConf; private static TimeSpan calendarNaptime = TimeSpan.FromHours(1); public static Scratch scratch; @@ -42,6 +42,7 @@ namespace director System.Text.Encoding.ASCII.GetBytes($"{directorConf.webdav_username}:{directorConf.webdav_password}"))); Telefranz.Configure("scheduler", directorConf.kafka_bootstrap); + tf = Telefranz.Instance; scratch = Scratch.LoadScratch(); @@ -72,6 +73,7 @@ namespace director calChecks.Add(checkCalendar(calendar)); } Task.WaitAll(calChecks.ToArray()); + scratch.agenda = scratch.agenda.OrderBy(s => s.Showtime).ToList(); lock (scratch) { @@ -100,8 +102,11 @@ namespace director Console.WriteLine("debug test"); var psuedo = new schedulable.Scheduled(); - psuedo.Showtime = DateTime.Now + TimeSpan.FromSeconds(30); - var partiallyCopiable = scratch.agenda?.FirstOrDefault(); + psuedo.Showtime = DateTime.Now + TimeSpan.FromMinutes(30); + // foreach(var a in scratch.agenda){ + // Console.WriteLine(a.Occurrence._event.Summary); + // } + var partiallyCopiable = scratch.agenda?.First(a => a.Occurrence._event.Summary == "Good Morning, Phyrexia (in the morning)!"); psuedo.Occurrence = partiallyCopiable.Occurrence; psuedo.Occurrence.OccurrenceStart = psuedo.Showtime; psuedo.Occurrence.OccurrenceEnd = psuedo.Showtime; @@ -117,12 +122,12 @@ namespace director //it likes to throw an error saying "this is the webDAV interface, use webDAV" at my webDAV client, stopping me from using webDAV. Console.WriteLine(calendarUri); var calString = await httpClient.GetStringAsync(directorConf.webdav_uri + calendarUri + "?export"); - var knownChecklist = new List(); + lock (scratch) { var calName = iCalHoopJumping.LoadCalendar(calString); scratch.Calendars[calName] = calString; - //todo: I'm pretty sure some library is returning me only things in the future. Verify, and also make sure it's returning things in the present. + //todo: make sure I'm getting things in the present. foreach (var occurrence in iCalHoopJumping.getOccurrences(calName)) { var newSchedulable = new schedulable.Scheduled() @@ -158,7 +163,9 @@ namespace director } Console.WriteLine("configuration found"); - var handler = new ShowHandler(todo, directorConf.workingDirectory + "/" + todo.Showtime.ToShortDateString()); + var handler = new ShowHandler(todo, directorConf.workingDirectory + todo.Showtime.ToString("_yyyy-MM-dd"), () => { + //tf.ProduceMessage(new silver_messages.directorial.execute_command(){command = "directors_datasync", timeout = TimeSpan.Zero}); + }); handler.StartHandling(); } } diff --git a/ShowHandler.cs b/ShowHandler.cs index e959d4c..69fd88f 100644 --- a/ShowHandler.cs +++ b/ShowHandler.cs @@ -7,6 +7,9 @@ using System.Threading.Tasks; using Newtonsoft.Json; using schedulable; using System.Collections.Generic; +using franz; +using System.Threading; +using System.Collections.Concurrent; namespace director { @@ -14,16 +17,25 @@ namespace director { private Scheduled todo; private string outputPath; - public ShowHandler(Scheduled todo, string outputPath) + private string checklistFilename; + private Action checklistSync; + private static readonly AutoResetEvent _signal = new AutoResetEvent(false); + private static ConcurrentDictionary signalsReceived = new ConcurrentDictionary(); + public ShowHandler(Scheduled todo, string outputPath, Action checklistSync) { this.todo = todo; this.outputPath = outputPath; + this.checklistSync = checklistSync; + + checklistFilename = "checklist.md"; } internal void StartHandling() { - Console.WriteLine("start handling"); - CreateChecklist(); + Console.WriteLine($"begin the pre-pre show by creating a checklist."); + initializeChecklist(); + //todo: any signals one has to wait for, start listening + var napLength = (todo.Showtime - todo.Configuration.LeadTimeDesired) - DateTime.Now; Console.WriteLine($"napping until {todo.Showtime - todo.Configuration.LeadTimeDesired} ({napLength})"); @@ -43,58 +55,130 @@ namespace director HumanCommunication.Instance.Say($"error in show handler! Panicking!\n{JsonConvert.SerializeObject(e)}", HumanCommunication.LogLevel.Showstopper); } } - - private void CreateChecklist() + private void initializeChecklist() { - Console.WriteLine($"begin the pre-pre show by creating a checklist."); Directory.CreateDirectory(outputPath); + + checklistFilename = $"checklist ({todo.Occurrence._event.Summary}).md"; + foreach (char c in System.IO.Path.GetInvalidFileNameChars()) + { + checklistFilename = checklistFilename.Replace(c, '_'); + } + checklistFilename = $"{outputPath}/{checklistFilename}"; + Console.WriteLine($"checklistFilename: {checklistFilename}"); + + WriteChecklist(); + // don't actually know how to share via webdav. But also nextcloud doesn't seem to cooperate anyway. + // #region share with humans + // if (todo.Configuration.checklist?.FirstOrDefault(pl => pl.type == LineType.manual) != null) + // { + // Console.WriteLine($"nothing manual, not sharing with humans."); + // } + // else + // { + // //TODO: share + // } + // #endregion + } + private void WriteChecklist() + { var text = new StringBuilder(); - text.AppendLine($"# {todo.Occurrence._event.Description}"); - - #region share with humans - var allItems = checklistFlattened(); - if(allItems?.FirstOrDefault(pl => pl.type == "manual") != null) + text.AppendLine($"# {todo.Occurrence._event.Summary}"); + + foreach (var line in todo.Configuration.checklist) { - Console.WriteLine($"nothing manual, not sharing with humans."); - } - else - { - //TODO: share - } - #endregion - } - private IEnumerable checklistFlattened() - { - if (todo.Configuration.checklist?.Count() > 0) - { - var toReturn = new List(); - foreach(var line in todo.Configuration.checklist) + if (line.type != LineType.text) { - toReturn.AddRange(recurseChecklist(line)); + text.Append("* [ ] "); } - return toReturn; + text.AppendLine($"{line.description}"); } - return null; + File.WriteAllText(checklistFilename, text.ToString()); + checklistSync(); } - private IEnumerable recurseChecklist(ProcessionLine line) + + private void markLineDone(int lineIndex, string[] fileLines) { - var asContainer = line as container; - if (asContainer == null || asContainer.subitems?.Count() == 0) - { - return new List() { line }; - } - else - { - var toReturn = new List(); - toReturn.AddRange(recurseChecklist(line)); - return toReturn; - } + fileLines[lineIndex] = "* [x] " + fileLines[lineIndex].Substring(6); + File.WriteAllLines(checklistFilename, fileLines); + this.checklistSync(); } - - - internal void HandleChecklist() + private void HandleChecklist() { Console.WriteLine($"should now be at the desired lead time. showtime: {todo.Showtime}"); + checklistSync(); + + while (true) + { + var fileLines = File.ReadAllLines(checklistFilename); + var processionLineIndex = 0; + var fileLineIndex = 0; + foreach (var checklistLine in fileLines) + { + if (checklistLine.StartsWith("* [ ] ")) + { + break; + } + if (checklistLine.Length > 0 && !checklistLine.StartsWith("#")) + { + processionLineIndex++; + } + fileLineIndex++; + } + if (fileLineIndex > fileLines.Count() - 1) + { + ChecklistComplete(); + return; + } + + //file starts with a header line + var targetItem = todo.Configuration.checklist.ToList()[processionLineIndex]; + Console.WriteLine("consider: " + targetItem.description); + switch (targetItem.type) + { + case LineType.manual: + Console.WriteLine($"what can I do but wait? (currently {DateTime.Now.ToShortTimeString()})"); + Task.WaitAll(Task.Delay(new TimeSpan(0, 5, 0))); + Console.WriteLine("alright let's check."); + break; + case LineType.cmd: + Console.WriteLine($"sending command: {targetItem.cmd} {targetItem.args}"); + Telefranz.Instance.ProduceMessage(new silver_messages.directorial.execute_command() + { + command = targetItem.cmd, + args = new List() { targetItem.args } + }); + Console.WriteLine("seem to have survived"); + markLineDone(fileLineIndex, fileLines); + break; + case LineType.await_showtime: + var napLength = todo.Showtime - DateTime.Now; + if (napLength.TotalSeconds > 0) + { + Console.WriteLine("brb quick nap"); + Task.WaitAll(Task.Delay(napLength)); + } + Console.WriteLine("actual showtime tho"); + markLineDone(fileLineIndex, fileLines); + break; + // case LineType.await_signal: + // //mark it if I have the signal, but if not, can't do anything but wait + // if (signalsReceived[targetItem.cmd]) + // { + // markLineDone(fileLineIndex, fileLines); + // } + // else + // { + // _signal.WaitOne(new TimeSpan(0, 2, 0)); + // } + // break; + } + } + } + private void ChecklistComplete() + { + Console.WriteLine("\"another job well executed\" - lotus"); + //TODO: delete folder. if necessary. Maybe. } } } \ No newline at end of file diff --git a/director.csproj b/director.csproj index 74bfdf5..b2dc7d5 100644 --- a/director.csproj +++ b/director.csproj @@ -8,7 +8,6 @@ - diff --git a/iCalHoopJumping.cs b/iCalHoopJumping.cs index f179493..ba4eaf4 100644 --- a/iCalHoopJumping.cs +++ b/iCalHoopJumping.cs @@ -11,7 +11,7 @@ namespace director public class iCalHoopJumping { private static DateTime searchStart = DateTime.Now; //is it slower to just call datetime.now every time? /shrug - private static DateTime searchEnd = DateTime.Now.AddDays(7); + private static DateTime searchEnd = DateTime.Now.AddDays(21); public static readonly ConcurrentDictionary Calendars = new ConcurrentDictionary(); public static string LoadCalendar(string calendarString) { diff --git a/schedulable/Checklist.cs b/schedulable/Checklist.cs index 9f7ed3a..ef7d66f 100644 --- a/schedulable/Checklist.cs +++ b/schedulable/Checklist.cs @@ -3,22 +3,12 @@ using System.Collections.Generic; namespace schedulable { + public enum LineType { text, manual, cmd, await_showtime } public class ProcessionLine { public string description { get; set; } - public string type { get; set; } = "generic"; //TODO: experiment with $type, apparnetly newtonsoft json can use that to choose deserialization? - public ProcessionLine() { type = GetType().ToString(); } - } - public class manual : ProcessionLine { } - public class command : ProcessionLine - { + public LineType type { get; set; } public string cmd { get; set; } - public IEnumerable args { get; set; } + public string args { get; set; } } - public class container : ProcessionLine - { - public IEnumerable subitems { get; set; } - } - public class awaitShowtime : ProcessionLine { } - public class awaitCutSignal : ProcessionLine { } } \ No newline at end of file