public CommandHandlerResult SetAndEvaluateFormula(string formula, int trackNo, int clipNo) { var clipRef = new ClipReference(trackNo, clipNo); if (ClipSet[clipRef] != ClipSlot.Empty && ClipSet[clipRef].Name == formula) { return CommandHandlerResult.AbortedResult with { Warnings = new List <string> { $"Aborted evaluation of formula at {clipRef.ToString()} since it was unchanged." } } } ; var(success, result, errorMessage) = Parser.ParseFormula(formula); if (!success) { return CommandHandlerResult.AbortedResult with { Errors = new List <string> { errorMessage } } } ; var clipSlot = new ClipSlot(formula, new Clip(clipRef), result); ClipSet[clipSlot.ClipReference] = clipSlot; var(successfulClipRefs, errors) = ClipSet.ProcessClips(new [] { clipSlot }); return(CommandHandlerResult.CompletedResult with { SuccessfulClips = ClipSet.GetClipsFromClipReferences(successfulClipRefs).ToList(), Errors = errors }); }
public void SetFormula(int trackNo, int clipNo, string formula) { var parsedFormula = Parser.ParseFormula(formula); if (parsedFormula.Success) { var clipRef = new ClipReference(trackNo, clipNo); var clipSlot = new ClipSlot(formula, new Clip(clipRef), parsedFormula.Result); ClipSet[clipSlot.ClipReference] = clipSlot; } }
public void TestDecimalToSpreadshimal() { Assert.AreEqual("", ClipReference.ToSpreadshimal(0)); Assert.AreEqual("A", ClipReference.ToSpreadshimal(1)); Assert.AreEqual("B", ClipReference.ToSpreadshimal(2)); Assert.AreEqual("Z", ClipReference.ToSpreadshimal(26)); Assert.AreEqual("AA", ClipReference.ToSpreadshimal(27)); Assert.AreEqual("AC", ClipReference.ToSpreadshimal(29)); Assert.AreEqual("ZZ", ClipReference.ToSpreadshimal(702)); Assert.AreEqual("AAA", ClipReference.ToSpreadshimal(703)); Assert.AreEqual("AAB", ClipReference.ToSpreadshimal(704)); }
public static ProcessResult <Formula> ParseFormula(string formula) { var lexer = new Lexer(formula); var(success, tokens, errorMessage) = lexer.GetTokens(); if (!success) { return(new ProcessResult <Formula>(errorMessage)); } (success, errorMessage) = AreTokensValid(tokens); if (!success) { return(new ProcessResult <Formula>($"Parsing of formula ${formula} was aborted: {errorMessage}")); } TreeToken syntaxTree; (success, syntaxTree, errorMessage) = CreateSyntaxTree(tokens); if (!success) { return(new ProcessResult <Formula>(errorMessage)); } // remaining steps: // convert any nested statements to inline clips - might involve some refactoring where parsing to commands and applying these can be done selectively and not as part of the fixed pipeline we have now Token[] commandTokens; (success, commandTokens, errorMessage) = ResolveAndFlattenSyntaxTree(syntaxTree); if (!success) { return(new ProcessResult <Formula>(errorMessage)); } try { var allReferencedClips = commandTokens.Where(x => x.IsClipReference) .Select(x => ClipReference.FromString(x.Value)).ToList(); var sourceClipReferences = commandTokens.TakeWhile(x => x.IsClipReference).Select(x => ClipReference.FromString(x.Value)).ToList(); var commandTokensLists = ExtractCommandTokensLists(commandTokens.Skip(sourceClipReferences.Count).ToArray()); var commands = commandTokensLists.Select(ParseTokensToCommand).ToList(); var parsedFormula = new Formula(commands, sourceClipReferences, allReferencedClips, new Dictionary <ClipReference, ClipSlot>()); return(new ProcessResult <Formula>(parsedFormula)); } catch (ArgumentException ae) { return(new ProcessResult <Formula>($"ParseFormula threw exception: {ae.Message}")); } }
public void TestSpreadshimalToDecimal() { Assert.AreEqual(0, ClipReference.FromSpreadshimal("")); Assert.AreEqual(1, ClipReference.FromSpreadshimal("A")); Assert.AreEqual(2, ClipReference.FromSpreadshimal("B")); Assert.AreEqual(26, ClipReference.FromSpreadshimal("Z")); Assert.AreEqual(27, ClipReference.FromSpreadshimal("AA")); Assert.AreEqual(29, ClipReference.FromSpreadshimal("AC")); Assert.AreEqual(702, ClipReference.FromSpreadshimal("ZZ")); Assert.AreEqual(703, ClipReference.FromSpreadshimal("AAA")); Assert.AreEqual(704, ClipReference.FromSpreadshimal("AAB")); Assert.AreEqual(702, ClipReference.FromSpreadshimal("zz")); Assert.AreEqual(703, ClipReference.FromSpreadshimal("aaa")); Assert.AreEqual(704, ClipReference.FromSpreadshimal("aab")); }
public void TestEvaluationOfClipIsAbortedWhenContentsUnchanged() { var commandHandler = new CommandHandler(); var result = commandHandler.SetAndEvaluateClipData(new Clip(4, true) { ClipReference = ClipReference.FromString("A1"), Notes = new SortedList <NoteEvent> { new NoteEvent(36, 0, .5m, 100), new NoteEvent(38, 1, .5m, 100), new NoteEvent(40, 2, .75m, 100) } }); Assert.IsTrue(result.RanToCompletion); result = commandHandler.SetAndEvaluateClipData(new Clip(4, true) { ClipReference = ClipReference.FromString("A1"), Notes = new SortedList <NoteEvent> { new NoteEvent(36, 0, .75m, 100), new NoteEvent(38, 1, .5m, 100), new NoteEvent(40, 2, .5m, 100) } }); Assert.IsTrue(result.RanToCompletion); result = commandHandler.SetAndEvaluateClipData(new Clip(4, true) { ClipReference = ClipReference.FromString("A1"), Notes = new SortedList <NoteEvent> { new NoteEvent(36, 0, .75m, 100), new NoteEvent(38, 1, .5m, 100), new NoteEvent(40, 2, .5m, 100) } }); Assert.IsFalse(result.RanToCompletion); Assert.AreEqual($"Aborted evaluation of clip at A1 since it was unchanged.", result.Warnings.FirstOrDefault()); }
public static (List <Clip> Clips, string Formula, ushort Id, byte TrackNo) DecodeData(byte[] data) { var clips = new List <Clip>(); ushort id = BitConverter.ToUInt16(data, 0); byte trackNo = data[2]; byte numClips = data[3]; int dataOffset = 4; // Decode clipdata while (clips.Count < numClips) { ClipReference clipReference = new ClipReference(data[dataOffset], data[dataOffset += 1]); decimal length = (decimal)BitConverter.ToSingle(data, dataOffset += 1); bool isLooping = data[dataOffset += 4] == 1; var clip = new Clip(length, isLooping) { ClipReference = clipReference }; ushort numNotes = BitConverter.ToUInt16(data, dataOffset += 1); dataOffset += 2; for (var i = 0; i < numNotes; i++) { clip.Notes.Add(new NoteEvent( data[dataOffset], (decimal)BitConverter.ToSingle(data, dataOffset += 1), (decimal)BitConverter.ToSingle(data, dataOffset += 4), data[dataOffset += 4]) ); dataOffset++; } clips.Add(clip); } // Convert remaining bytes to text containing the formula string formula = Encoding.ASCII.GetString(data, dataOffset, data.Length - dataOffset); return(clips, formula, id, trackNo); }
public ClipSlot this[ClipReference clipRef] => ClipSlots[clipRef] ?? ClipSlot.Empty;