<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-3696065907170022606</id><updated>2011-07-28T19:21:28.543-07:00</updated><category term='grails'/><category term='groovy'/><category term='family'/><title type='text'>Trygve Amundsen's Blog</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://trygveamundsen.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3696065907170022606/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://trygveamundsen.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>trygvea</name><uri>http://www.blogger.com/profile/15616418278941610590</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>5</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-3696065907170022606.post-8852636933534009231</id><published>2010-01-25T14:45:00.000-08:00</published><updated>2010-02-06T16:01:55.398-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='grails'/><title type='text'>Grails class-diagram plugin mentioned!</title><content type='html'>My grails plugin, &lt;a href="http://grails.org/plugin/class-diagram"&gt;class-diagram&lt;/a&gt; has just been mentioned on the &lt;a href="http://www.grailspodcast.com/blog/id/555"&gt;Grails podcast, episode 104&lt;/a&gt;. That's fun!&lt;br /&gt;&lt;br /&gt;The actual 20 seconds on the podcast (starting at 09:40) is of little interest, it is just a reference to a blog post by Sven Lange, &lt;i&gt;&lt;a href="http://www.svenlange.co.za/?p=80"&gt;Generating UML class diagrams from Grails domain model&lt;/a&gt;&lt;/i&gt; where he compares my plugin with another great plugin, the &lt;i&gt;&lt;a href="http://www.grails.org/plugin/create-domain-uml"&gt;Create Domain UML plugin&lt;/a&gt;&lt;/i&gt; by Al Phillips. (Al published his plugin just a week before me. We talked about joining forces, but agreed that the plugins were different enough to co-exist.)&lt;br /&gt;&lt;br /&gt;Now, go an read &lt;a href="http://www.svenlange.co.za/?p=80"&gt;Sven's blog&lt;/a&gt; and try out both plugins! They can help you boost your productivity even more!&lt;br /&gt;&lt;br /&gt;I should really take the time to fix some issues on the &lt;a href="http://jira.codehaus.org/browse/GRAILSPLUGINS/component/14031"&gt;backlog&lt;/a&gt; now, and get release 0.5 out!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3696065907170022606-8852636933534009231?l=trygveamundsen.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://trygveamundsen.blogspot.com/feeds/8852636933534009231/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://trygveamundsen.blogspot.com/2010/01/grails-class-diagram-plugin-mentioned.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3696065907170022606/posts/default/8852636933534009231'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3696065907170022606/posts/default/8852636933534009231'/><link rel='alternate' type='text/html' href='http://trygveamundsen.blogspot.com/2010/01/grails-class-diagram-plugin-mentioned.html' title='Grails class-diagram plugin mentioned!'/><author><name>trygvea</name><uri>http://www.blogger.com/profile/15616418278941610590</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3696065907170022606.post-5472424284926234856</id><published>2009-11-30T02:09:00.000-08:00</published><updated>2009-11-30T02:14:48.273-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='family'/><title type='text'>Mams sine smykker</title><content type='html'>Min kjære mor har endelig begynt å eksponere sine smykker på nett!&lt;div&gt;Søk på &lt;a href="http://www.google.no/search?q=berits+smykker"&gt;google: Berits Smykker&lt;/a&gt;, der kommer den som nr. 1 eller 2, eller gå rett inn på &lt;a href="http://www.beritssmykker.com"&gt;Berits Smykker&lt;/a&gt;.&lt;/div&gt;&lt;div&gt;Flott, ikke sant!&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3696065907170022606-5472424284926234856?l=trygveamundsen.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://trygveamundsen.blogspot.com/feeds/5472424284926234856/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://trygveamundsen.blogspot.com/2009/11/mams-sine-smykker.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3696065907170022606/posts/default/5472424284926234856'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3696065907170022606/posts/default/5472424284926234856'/><link rel='alternate' type='text/html' href='http://trygveamundsen.blogspot.com/2009/11/mams-sine-smykker.html' title='Mams sine smykker'/><author><name>trygvea</name><uri>http://www.blogger.com/profile/15616418278941610590</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3696065907170022606.post-8570587902499633777</id><published>2009-11-27T01:58:00.000-08:00</published><updated>2009-11-30T02:27:01.358-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='groovy'/><title type='text'>Dijkstra's shortest path algorithm in Groovy</title><content type='html'>Groovy is really great for trying out algorithms without having to write tons of code.&lt;br /&gt;&lt;br /&gt;The other day we were elaborating over how to make a route planner for public transport.&lt;br /&gt;In its simplest form, this can be solved by using &lt;a href="http://en.wikipedia.org/wiki/Edsger_W._Dijkstra"&gt;Dijkstra&lt;/a&gt;'s &lt;a href="http://en.wikipedia.org/wiki/Dijkstra%27s_algorithm"&gt;shortest path algorithm&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;But I couldn't find any groovy versions of this algorithm. I found a decent java version (I've copied parts from it, see &lt;a href="http://renaud.waldura.com/doc/java/dijkstra/" target="blank"&gt;see Renaud Waldura's blog&lt;/a&gt;), but the amount of code is still measured in pages, not lines of code.&lt;br /&gt;&lt;br /&gt;With groovy, I think, we're approaching the simplicity of &lt;a href="http://en.wikipedia.org/wiki/Dijkstra%27s_algorithm"&gt;the algorithm&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;pre class="groovy" name="code"&gt;class DijkstrasShortestPathAlgoritm {&lt;br /&gt;    def graph, start, destination    &lt;br /&gt;    // PriorityQueue performs much better than List - O(log(n)) for poll.    &lt;br /&gt;    def unsettledNodes = new PriorityQueue&amp;lt;String&amp;gt;(100, new Comparator&amp;lt;String&amp;gt;() {&lt;br /&gt;       public int compare(String node1, String node2) {&lt;br /&gt;            shortestDistance(node1).compareTo(shortestDistance(node2))&lt;br /&gt;        }&lt;br /&gt;    });&lt;br /&gt;    def shortestDistances = [:]&lt;br /&gt;    def predecessors = [:]&lt;br /&gt;    def settledNodes = [] as Set&lt;br /&gt;&lt;br /&gt;    DijkstrasShortestPathAlgoritm(graph, start, destination) {&lt;br /&gt;        this.graph = graph&lt;br /&gt;        this.start = start&lt;br /&gt;        this.destination = destination&lt;br /&gt;&lt;br /&gt;        unsettledNodes.add(start)&lt;br /&gt;        shortestDistances[(start)] = 0&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    int shortestDistance(node) {&lt;br /&gt;        shortestDistances.containsKey(node) ? shortestDistances[node] : Integer.MAX_VALUE&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    def extractMin() {&lt;br /&gt;        unsettledNodes.poll()&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    def unsettledNeighbours(node) {&lt;br /&gt;        graph.findAll { edge -&amp;gt;&lt;br /&gt;            edge.node1 == node &amp;amp;&amp;amp; !settledNodes.contains(edge.node2)&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    def relaxNeighbours(node) {&lt;br /&gt;        unsettledNeighbours(node).each { edge -&amp;gt;&lt;br /&gt;            if (shortestDistance(edge.node2) &amp;gt; shortestDistance(edge.node1) + edge.distance) {&lt;br /&gt;                shortestDistances[edge.node2] = shortestDistance(edge.node1) + edge.distance&lt;br /&gt;                predecessors[edge.node2] = edge.node1&lt;br /&gt;                if (!unsettledNodes.contains(edge.node2)) {&lt;br /&gt;                    unsettledNodes.add(edge.node2)&lt;br /&gt;                }&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    def calculateShortestPath() {&lt;br /&gt;        while (!unsettledNodes.isEmpty()) {&lt;br /&gt;            String node = extractMin()&lt;br /&gt;            if (node == destination) {&lt;br /&gt;                break&lt;br /&gt;            }&lt;br /&gt;            settledNodes += node&lt;br /&gt;            relaxNeighbours(node)&lt;br /&gt;        }&lt;br /&gt;        shortestDistances[destination]&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    private def getShortestPath(node, path) {&lt;br /&gt;        node == start ? [node]+path : getShortestPath(predecessors[node], [node]+path)&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;    def getShortestPath() {&lt;br /&gt;        getShortestPath(destination, []) &lt;br /&gt;    }&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;And then, to find the shortest path of a graph, you do like this:&lt;br /&gt;&lt;br /&gt;&lt;pre class="groovy" name="code"&gt;class Edge {&lt;br /&gt;    String node1, node2&lt;br /&gt;    int distance&lt;br /&gt;}&lt;br /&gt;graph = [&lt;br /&gt;    new Edge(node1:'a', node2:'b', distance:4),&lt;br /&gt;    new Edge(node1:'a', node2:'c', distance:2),&lt;br /&gt;    new Edge(node1:'b', node2:'c', distance:3),&lt;br /&gt;    new Edge(node1:'c', node2:'b', distance:1),&lt;br /&gt;    new Edge(node1:'c', node2:'d', distance:5),&lt;br /&gt;    new Edge(node1:'b', node2:'d', distance:1),&lt;br /&gt;    new Edge(node1:'a', node2:'e', distance:1),&lt;br /&gt;    new Edge(node1:'e', node2:'d', distance:4)&lt;br /&gt;]&lt;br /&gt;def dijkstra = new DijkstrasShortestPathAlgoritm(graph, 'a', 'd')&lt;br /&gt;d = dijkstra.calculateShortestPath();&lt;br /&gt;assert d == 4&lt;br /&gt;assert dijkstra.shortestPath == ['a','c','b','d']&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Of course, the public transport domain have a lot of special rules, such as favouring routes with few connections, indirect connections made by walking between stops, buses that dont stop a specific place every second friday, etc. etc. Each and every rule may not be so difficult to solve, but the sum of the rules makes the route planner domain really complex.&lt;br /&gt;&lt;br /&gt;Also, there are other, possibly better, algorithms for route planning, one of them being the &lt;a href="http://en.wikipedia.org/wiki/A*_search_algorithm"&gt;A* algorithm&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3696065907170022606-8570587902499633777?l=trygveamundsen.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://trygveamundsen.blogspot.com/feeds/8570587902499633777/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://trygveamundsen.blogspot.com/2009/11/i-couldnt-find-any-groovy-versions-of.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3696065907170022606/posts/default/8570587902499633777'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3696065907170022606/posts/default/8570587902499633777'/><link rel='alternate' type='text/html' href='http://trygveamundsen.blogspot.com/2009/11/i-couldnt-find-any-groovy-versions-of.html' title='Dijkstra&apos;s shortest path algorithm in Groovy'/><author><name>trygvea</name><uri>http://www.blogger.com/profile/15616418278941610590</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3696065907170022606.post-4293914314213299799</id><published>2009-11-27T00:31:00.001-08:00</published><updated>2009-12-03T14:49:02.788-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='grails'/><title type='text'>Grails autotest</title><content type='html'>A year ago I stumbled upon &lt;a href="http://www.zenspider.com/ZSS/Products/ZenTest/"&gt;ZenTest&lt;/a&gt; / &lt;a href="http://ph7spot.com/musings/getting-started-with-autotest" target="_blank"&gt;autotest&lt;/a&gt;, a simple, but great tool for test-driven development with Ruby or Rails. It runs a subset of your tests whenever you change some source, and keeps you notified whenever something fails.&lt;br /&gt;&lt;br /&gt;There was only one problem. It works on ruby and rails only, not on groovy or grails. I assume you could set up Hudson or whatever to do something similar, but for small projects I need something much simpler than that.&lt;br /&gt;&lt;br /&gt;So I wrote a tiny bash script that does kind of the same as autotest, but on a grails project. It runs all tests whenever some source change, and keeps nagging you with this message if it fails:&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;a href="http://1.bp.blogspot.com/_AKcA1SjM8-w/Sw5220wcQPI/AAAAAAAAASo/FWO2Bv5UH5M/s1600/test-fail-screenshot.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="72" src="http://1.bp.blogspot.com/_AKcA1SjM8-w/Sw5220wcQPI/AAAAAAAAASo/FWO2Bv5UH5M/s320/test-fail-screenshot.png" width="320" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;This notification will stick as long as the tests fails, and change into this when tests succeededs:&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;a href="http://1.bp.blogspot.com/_AKcA1SjM8-w/Sw5z1yayFQI/AAAAAAAAASk/0_OJC0hNuiY/s1600/test-succeed-screenshot.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="87" src="http://1.bp.blogspot.com/_AKcA1SjM8-w/Sw5z1yayFQI/AAAAAAAAASk/0_OJC0hNuiY/s320/test-succeed-screenshot.png" width="320" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;This notifiction will fade away.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://growl.info/"&gt;Growl&lt;/a&gt; is used for notification. Here´s the script:&lt;br /&gt;&lt;br /&gt;&lt;pre class="bash" name="code"&gt;#!/bin/bash&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# Run grails tests continously.&lt;br /&gt;#&lt;br /&gt;# Author trygve.amundsen@gmail.com&lt;br /&gt;#&lt;br /&gt;logfile=.grailsAutoTest.log&lt;br /&gt;last_filestatus=""&lt;br /&gt;imagesDir=`dirname $0`/images&lt;br /&gt;curdir=`pwd`&lt;br /&gt;project=`basename $curdir`&lt;br /&gt;echo "Starting autotest for $project"&lt;br /&gt;&lt;br /&gt;while true; do&lt;br /&gt;    current_filestatus=`ls -lR grails-app lib scripts src test web-app/js web-app/css \&lt;br /&gt;                       *GrailsPlugin.groovy | md5`&lt;br /&gt;&lt;br /&gt;    if [ "$current_filestatus" != "$last_filestatus" ]&lt;br /&gt;    then&lt;br /&gt;        last_filestatus=$current_filestatus&lt;br /&gt;        echo -n "Running tests..."&lt;br /&gt;        grails test-app &gt; $logfile &lt;br /&gt;        tail -3 $logfile | grep -q 'Tests PASSED'&lt;br /&gt;        if [ $? -eq 0 ]&lt;br /&gt;        then&lt;br /&gt;            echo "Tests PASSED - waiting for changes..."&lt;br /&gt;            growlnotify -m "Grails AutoTests succeeded" -t "Test $project" \ &lt;br /&gt;                        -d "$project" --image $imagesDir/succeed.jpg&lt;br /&gt;        else&lt;br /&gt;            last_filestatus="failed"&lt;br /&gt;            tail -3 $logfile | head -1 &lt;br /&gt;            growlnotify -s -m "Grails AutoTests failed" -t "Test $project" \&lt;br /&gt;                        -d "$project" --image $imagesDir/fail-icon.png&lt;br /&gt;        fi&lt;br /&gt;    fi&lt;br /&gt;    sleep 2&lt;br /&gt;done&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Maybe I'll come back with at groovy version of the script later on.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3696065907170022606-4293914314213299799?l=trygveamundsen.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://trygveamundsen.blogspot.com/feeds/4293914314213299799/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://trygveamundsen.blogspot.com/2009/11/grails-autotest.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3696065907170022606/posts/default/4293914314213299799'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3696065907170022606/posts/default/4293914314213299799'/><link rel='alternate' type='text/html' href='http://trygveamundsen.blogspot.com/2009/11/grails-autotest.html' title='Grails autotest'/><author><name>trygvea</name><uri>http://www.blogger.com/profile/15616418278941610590</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_AKcA1SjM8-w/Sw5220wcQPI/AAAAAAAAASo/FWO2Bv5UH5M/s72-c/test-fail-screenshot.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3696065907170022606.post-8052116917136429324</id><published>2009-11-26T06:27:00.000-08:00</published><updated>2009-11-26T06:27:08.021-08:00</updated><title type='text'>Bootstrap</title><content type='html'>Dette er mitt første blogg-innlegg.&lt;br /&gt;&lt;br /&gt;Alle tidligere forsøk på å skrive blogger har strandet med at ambisjonene har vært større enn evnene. Jeg velger å gjøre et nytt forsøk, men øker samtidig maskevidden på selv-sensur-filteret en tanke. Jeg antar at noe søppel vil finne veien igjennom, men har bestemt meg for ikke å være så nøye på det.&lt;br /&gt;&lt;br /&gt;Hvis ting går som jeg har tenkt så vil jeg skrive mest om programmering og relaterte greier. Emner som interesserer en ekte KodeMaker®.&lt;br /&gt;&lt;br /&gt;Jeg kommer nok til å eksperimentere med både form og innhold, og vil sikkert prøve meg både på norsk og engelsk, for å se hva som funker best.&lt;br /&gt;&lt;br /&gt;Jeg har ingen anelse om hvor hvor det bærer. Men det er jo spennende i seg selv.&lt;br /&gt;Nok prat. Disse linjene har allerede tatt alt for lang tid å skrive, og har ingenting med kode å gjøre :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3696065907170022606-8052116917136429324?l=trygveamundsen.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://trygveamundsen.blogspot.com/feeds/8052116917136429324/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://trygveamundsen.blogspot.com/2009/11/dette-er-mitt-frste-blogg-innlegg.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3696065907170022606/posts/default/8052116917136429324'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3696065907170022606/posts/default/8052116917136429324'/><link rel='alternate' type='text/html' href='http://trygveamundsen.blogspot.com/2009/11/dette-er-mitt-frste-blogg-innlegg.html' title='Bootstrap'/><author><name>trygvea</name><uri>http://www.blogger.com/profile/15616418278941610590</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>
