Converting roman numerals to numbers using Groovy/Grails

I wrote up a post last week about my experience converting roman numerals to numbers using ColdFusion and I promised a follow up doing the same thing in Grails.

I did learn an interesting tidbit about Grails, the maximum numbers of tests you can have in a where clause is 999. Not a big deal as this is a somewhat contrived example, but something to note nonetheless. Without further ado here is my code, once again this assumes you have entered a valid roman numeral and I've tested the accuracy up to 2000.

view plain print about
1class RomanService {
2    Integer romanToDecimal(String romanNumber) {
3        Integer newNumber = 0, previousNumber = 0
4        Map romanToNumberMapping = [M:1000, D:500, C:100, L:50, X:10, V:5, I:1]
5        for (Integer oneChar = romanNumber.length() - 1; oneChar >
= 0; oneChar--) {
6            String oneLetter = romanNumber.charAt(oneChar)
7            newNumber = processNumber(romanToNumberMapping[oneLetter], previousNumber, newNumber)
8            previousNumber = romanToNumberMapping[oneLetter]
9        }
10        return newNumber
11    }
12
13    Integer processNumber(Integer currentNumber, Integer previousNumber, Integer newNumber) {
14        return previousNumber > currentNumber ? newNumber - currentNumber : newNumber + currentNumber
15    }
16}

On the whole it's really not much different than the ColdFusion version, semicolons are optional in most places (pretty much anything that's not a for loop) and you can strongly type the return values, although that's definitely not a requirement. I wrote the example above exactly how I'd write it for a project, but also wanted to point out some of what I'm doing isn't really required.

One interesting thing about Groovy and not one I'm terribly fond of is if you don't have a return statement the last piece of code executed is returned, so newNumber doesn't need a return statement in the romanToDecimal function and in processNumber the only line is returned. I've left the return statements off in the code below, but it's not something I'd normally do, it saves .1 seconds of typing to not type it and can make the code confusing in my opinion. I also left off the types of variables, but my opinion is the same as not typing out return, it doesn't save much time to not declare the type and it can cause some unnecesary confusion especially when it's left off in the arguments.

view plain print about
1class RomanService {
2    def romanToDecimal(romanNumber) {
3        def newNumber = 0, previousNumber = 0
4        def romanToNumberMapping = [M:1000, D:500, C:100, L:50, X:10, V:5, I:1]
5        for (def oneChar = romanNumber.length() - 1; oneChar >
= 0; oneChar--) {
6            def oneLetter = romanNumber.charAt(oneChar)
7            newNumber = processNumber(romanToNumberMapping[oneLetter], previousNumber, newNumber)
8            previousNumber = romanToNumberMapping[oneLetter]
9        }
10        newNumber
11    }
12
13    def processNumber(currentNumber, previousNumber, newNumber) {
14        previousNumber > currentNumber ? newNumber - currentNumber : newNumber + currentNumber
15    }
16}

I've attached my test case as an external file given the size

Converting roman numerals to numbers using ColdFusion

I recently worked on a project that required translating roman numerals to the numerical counterpart, this needed to work for anything from 1-2000. I wrote my own using TDD and eventually came up with this

view plain print about
1component {
2    public function romanToDecimal(romanNumber) {
3        var newNumber = 0;
4        var previousNumber = 0;
5        var romanToNumberMapping = {M:1000, D:500, C:100, L:50, X:10, V:5, I:1};
6        var romanNumeral = ucase(romanNumber);
7        for (var oneChar = romanNumeral.length() - 1; oneChar >
= 0; oneChar--) {
8            var oneLetter = romanNumeral.charAt(oneChar);
9            if (previousNumber > romanToNumberMapping[oneLetter]) {
10                newNumber-=romanToNumberMapping[oneLetter];
11            } else {
12                newNumber+=romanToNumberMapping[oneLetter];
13            }
14            previousNumber = romanToNumberMapping[oneLetter];
15        }
16        return newNumber;
17    }
18}

It's simple enough that you should be able to add each roman numeral and it's number into the mapping and this should theoretically work for any roman numeral, but I only tested up to 2000. This assumes that you have entered a valid roman numeral that can be translated to 1-2000.

The tests are written in MXUnit, so it's a lot of repetition. I'll be following up with a groovy example using spock that should have a much cleaner looking test. I've attached the test file and additionally have submitted this to cflib for approval.

You can download the test here if you're so inclined.

Enabling multiple cursors based on a selection in Sublime Text

I was writing a bunch of unit tests for a roman numeral translator function that I'm working on and I was copy/pasting the number and roman numeral from a few websites to validate my function was correction. My plan is to write a test for the first 5000 roman numerals, but using ctrl+d to make 5000 selections and format the selection correctly was going to take quite a while and I knew there had to be a better way.

I googled around for a while and eventually found this Stack Overflow answer. You can enable multiple cursors by making a selection and then pressing ctrl+shift+l (l as in Linux). The cursors will be automatically placed at the end of the line, but you can use ctrl+shift+left arrow key (windows command) to move word by word through your selection.

This option is also available from the Sublime menu by going to Selection > Split into Lines, where it will also tell you the shortcut if you're not using Windows.

Keep in mind, once you're past a couple hundred selections Sublime can be very slow even on a fast computer, so be patient if you're enabling hundreds of cursors.

Using grails assets when you can't use the asset tag

In Grails 2.4+ the asset pipeline plugin is included by default and you can access files in the assets folder by using an asset tag

view plain print about
1<asset:javascript src="application.js"/>
2 <asset:stylesheet src="application.css"/>
3 <asset:image src="logo.png" width="200" height="200"/>

However, it's not always feasible to be able to use that syntax. One example is when loading an svg image with a png fallback. The code would ideally look like this when the HTML is generated.

view plain print about
1<svg width="180" height="60">
2 <image xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="logo.svg" src="logo.png"></image>
3</svg>

Rather than using an asset tag you can use assetPath() to find the file just like using the asset tag would do. In this case our SVG and PNG images are stored in variables named logoSVG and logoPNG. When the HTML is generated the resulting HTML is as desired.

view plain print about
1<svg width="180" height="60">
2 <image xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="${assetPath(src: logoSVG)}" src="${assetPath(src: logoPNG)}"></image>
3</svg>

One important thing to note is the asset plugin is not recursive, so if your file is not located in assets/images you will need to include the path relative to the images folder in your src. If your images were in an imgs folder the syntax would be like so

view plain print about
1<svg width="180" height="60">
2 <image xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="${assetPath(src: 'imgs/' + logoSVG)}" src="${assetPath(src: 'imgs/' + logoPNG)}"></image>
3</svg>

Run groovy scripts in sublime text

Wondering how to run Groovy files in Sublime Text? It's really quite simple - to create a new build system in Sublime Text go to Tools > Build System > New Build System and copy/paste the code below

{
	"cmd": ["groovy","$file"],
	"selector": "source.groovy",
	"windows":
	{
		"shell": "cmd.exe"
	}
}

Once the build system is saved you should be able to type Ctrl + B to run the code and output to the Sublime console. If nothing happens you may need to go to Tools > Build System and select groovy.

This is extremely handy if you're creating tests in Grails and want to test things without creating a full test case beforehand, writing/running tests in Grails can be excrutiating and testing within your file can help you spot mistakes much quicker than running test-app and waiting for everyting to compile and output your results.

Grails - Reloading a service without stopping your app

When a grails application is started most Grails artificats are reloaded as they are changed - controllers, filters, tag libraries, but the opposite is true if you strongly type your services like below.

FakeService fakeService

However if you use untyped injected like

def fakeService

then the service will be reloaded as changes are made. This may have been obvious to most people, but I was originally going through the hassle of either restarting my app after each change (huge time waster) or creating a fakeServiceHelper where I made all my changes and introducing a needless extra layer to my application to avoid restarting my app after each change.

Windows Media Center Reports No Signal when Recording

I was having a problem with my local ABC station working when I viewed the channel to watch a show, but every recording was failing saying "There was no TV signal when the show was scheduled to record" even if I went to the channel immediately following that error it was working. If I tried to press record on the show as it was playing it would fail and say no signal again. It turns out the problem is the antenna somehow is picking up two sources. I'm not sure why it could play the show live and not record, but here's how I fixed it.

  1. Open the Program Guide
  2. Right click the problem channel
  3. Choose Edit Channel
  4. Choose Edit Sources - you should see two sources enabled
  5. Disable one of them and try the channel again. If that doesn't work disable the other source and try the channel again.

For reference I'm using Windows 7 with an AVerMedia M780 Tuner.

Adding a default commit message to TortoiseSVN

I always seem to struggle finding how to do this since I do it so infrequently, so I'm posting this here to save me a few minutes next time I need to do this. It's really a very simple process and provides a nice reminder of what should be included in the commit message (if you have any sort of guidelines around it).

Find the folder you want to add the default message to and right click it. Go to TortoiseSVN > Properties

From there select New > Other and then enter "tsvn:logtemplate" (without the quotes) as the Property Name and your default message as the Property value.

I tend not to apply the property recursively as 99.8% of my commits are based off of the main folder, but feel free to check that value if you want it to show up even if you commit a single file or from a single folder within your parent folder.

NCDevCon - Responsive Web Design slides and video

Big thanks to all the volunteers at NCDevCon especially, Jim Priest and Dan Wilson, the conference was really great.

Thanks to everyone who truned out for my Getting Started with Responsive Web Design presentation. My slides are now posted online and the video of my talk is live as well.

All the videos can be viewed here.

Batch inserting records to a database

I was writing some code for a client that processed a csv file and inserted each row into a database, when there were a couple hundred rows the processing time was very quick, but when there are 8000 rows this can take quite a while even on a very fast database, so I wrote up some code to batch insert the records (which I've done too many times).

I was using MSSQL, so the max parameters I could send at one time was 2100 (210 rows x 10 columns), but your mileage may vary. I'd set rowsPerInsert as high as possible and decrease as necessary. You should be able to easily modify the pseudo code below.

view plain print about
1<cfscript>
2 totalrows = 5000; // this would come from a structCount or something similar
3
rowsPerInsert = 210;
4 //this creates a struct with alternating values of true/false for test purposes
5
stRows = {};
6 for (i=1; i
<=totalRows; i++) {
7 stRows[i] = i MOD 2 ? true : false;
8 }
9</cfscript>
10<cfoutput>
11<cfloop from="0" to="#totalRows - 1#" step="#rowsPerInsert#" index="totalRow">
12    <br><br>INSERT #totalRow#<br>
13    <cfloop from="1" to="#rowsPerInsert#" index="indRow">
14        <cfset rowNumber = totalRow + indRow>
15        <cfif rowNumber LTE totalRows>
16            #rowNumber# #stRows[rowNumber]# <!--- SELECT goes here --->
17            <cfif indRow NEQ rowsPerInsert AND rowNumber NEQ totalRows> UNION ALL</cfif>
18            <br>
19        </cfif>
20    </cfloop>
21</cfloop>
22</cfoutput>

This is mostly for me to steal from myself once I need this again, but hopefully you find it useful as well.

More Entries