Time Lapse
Formatting Lilypond Sheet Music for the Kindle
Since Lilypond is similar to Tex, Lilypond files have incredible control of the output. No exception is adjusting paper dimensions, only a simple command is required:
\paper { paper-height = H\mm paper-width = W\mm }where H is the desired height in millimeters and W is the desired width in millimeters of the output paper. Since the kindle was a "fit-to-width" option for PDFs, the first step is to figure out the aspect ratio of the display. Once we have the aspect ratio, then we can configure the scaling to make the actual output legible from a reasonable distance. At first I thought that this would be easy. The Kindle has a resolution of 600x800, or an aspect ratio of 3:4 (the screen is taller than it is wide). However, when creating sheet music of this ratio and the display mode of the Kindle set to "fit-to-width", the pages spanned multiple virtual pages. This meant that the music was cut off between virtual pages. This makes playing the music impossible. From here I decided to figure out the ratio by creating a bunch of files of varying ratios and testing the output.
It turns out that the Kindle is doing a little fudging on the display and allows a range of display ratios that will appear as one virtual page. From what I observe, any ratio between .57-.61. I tried many variations and it also seems there is some other logic going on in the "fit-to-width" option and determining when to page, but this is a decent rule of thumb to work with. Now that we have a few aspect ratios to work with, I wanted to figure out some nice paper size in absolute terms such that Lilypond will output notes about the same size as normal sheet music.
At first I tried 100mm x 59mm. As you can see, the notes were extremely large and didn't allow many notes to displayed at once. This would making paging an annoying operation while trying to play the music.
Next I doubled everything. I found 200mm x 122mm appears nice.
Compared to actual sheet music, the font is a little small, but completely usable. If you want a bigger font and don't mind paging frequently, I tried the in the between, 150mm x 80mm.
This is the closest to actual size, but fine tuning could be done.
It is worth noting that while doing this, the "fudge" factor I mentioned earlier, or variability in determining the aspect ratio of the virtual page the Kindle will chose to display, is frustrating. These values I found through trial and error by generating many sheet music files, and looking at all of them.
Custom HTML "Widgets" for ASP.NET MVC3
@Html.DropDownList("DropDownID", Model.Items)
The way I accomplished this was extension methods. Extension methods are an interesting way to add functionality to a class without inheritence. There are drawbacks, such as not being able to access protected members of the base class, but for some cases this is ok.
I decided to use extension methods to add a method to the class that corresponded to the @Html object in the Razor engine. I found out that this class was the HtmlHelper class in the System.Web.Mvc namespace. By extending the HtmlHelper class via extension methods, I was able to achieve my goal of adding a custom widget.
namespace MvcHtml { using System.Web.Mvc; public static class ExtensionHtml { public static MvcHtmlString CustomWidget(this HtmlHelper htmlHelper, string property) { TagBuilder tagBuilder = new TagBuilder("div"); tagBuilder.SetInnerText(property); return new MvcHtmlString(tagBuilder.ToString()); } } }
After this little bit of work, we are ready to use the custom widget in our view template just as traditional widgets provided for us.
@Html.CustomWidget("SampleProperty")
I hope this helps people understand how Razor is producing HTML from these view files!
Combining the Decorator Pattern with the Template Method Pattern
/* The template method */ interface AbstractClass { void Method(); } /* One implementation */ class ConcreteClass1 : AbstractClass { public void Method() { System.Console.WriteLine(" ConcreteClass1"); } } /* Second implementation */ class ConcreteClass2 : AbstractClass { public void Method() { System.Console.WriteLine(" ConcreteClass2"); } } /* Now comes the decorator, which feels just like any other implementation */ abstract class AbstractClassDecorator : AbstractClass { public AbstractClassDecorator(AbstractClass abstractClass) { this.abstractClass = abstractClass; } public virtual void Method() { this.abstractClass.Method(); } protected AbstractClass abstractClass; }Now it becomes time to implement the decorators. The nice thing about the decorator pattern is that it allows you to add decorators simply by extending a class. Here I have two decorators.
class ConcreteDecoratedAbstractClass1 : AbstractClassDecorator { public ConcreteDecoratedAbstractClass1(AbstractClass abstractClass) : base(abstractClass) { } public override void Method() { this.abstractClass.Method(); System.Console.WriteLine(" Decorator1"); } } class ConcreteDecoratedAbstractClass2 : AbstractClassDecorator { public ConcreteDecoratedAbstractClass2(AbstractClass abstractClass) : base(abstractClass) { } public override void Method() { this.abstractClass.Method(); System.Console.WriteLine(" Decorator2"); } }And now that the patterns are in place, all we have to do is simply use them. Because of the decoration and template pattern, we are able to create many possibilities to execute the "same" method. We can decorate or not decorate with any of the decorators, and we have multiple implementations of each method.
class Program { static void Main(string[] args) { AbstractClass concrete1 = new ConcreteClass1(); AbstractClass concrete2 = new ConcreteClass2(); ConcreteDecoratedAbstractClass1 decorated1Concrete1 = new ConcreteDecoratedAbstractClass1(concrete1); ConcreteDecoratedAbstractClass1 decorated1Concrete2 = new ConcreteDecoratedAbstractClass1(concrete2); ConcreteDecoratedAbstractClass2 decorated2Concrete1 = new ConcreteDecoratedAbstractClass2(concrete1); ConcreteDecoratedAbstractClass2 decorated2Concrete2 = new ConcreteDecoratedAbstractClass2(concrete2); ConcreteDecoratedAbstractClass2 decorated21Concrete1 = new ConcreteDecoratedAbstractClass2(decorated1Concrete1); /* Et cetra */ System.Console.WriteLine("Implementaiton 1"); concrete1.Method(); System.Console.WriteLine("Implementation 2"); concrete2.Method(); System.Console.WriteLine("Implementation 1 decorated by decorator 1"); decorated1Concrete1.Method(); System.Console.WriteLine("Implementation 2 decorated by decorator 1"); decorated1Concrete2.Method(); System.Console.WriteLine("Implementation 1 decorated by decorator 2"); decorated2Concrete1.Method(); System.Console.WriteLine("Implementation 2 decorated by decorator 2"); decorated2Concrete2.Method(); System.Console.WriteLine("Implementation 1 decorated by decorator 1 and decorator 2"); decorated21Concrete1.Method(); }This program outputs
Implementaiton 1 ConcreteClass1 Implementation 2 ConcreteClass2 Implementation 1 decorated by decorator 1 ConcreteClass1 Decorator1 Implementation 2 decorated by decorator 1 ConcreteClass2 Decorator1 Implementation 1 decorated by decorator 2 ConcreteClass1 Decorator2 Implementation 2 decorated by decorator 2 ConcreteClass2 Decorator2 Implementation 1 decorated by decorator 1 and decorator 2 ConcreteClass1 Decorator1 Decorator2I hope that this was informative in demonstrating the power of patterns and how they can be combined for even greater utility. Please feel free to comment below.