Wednesday, March 30, 2011

Groovy++ Mixin and Category

@Typed
package categoriestest

@Category(List)
@Typed
class Shuffler {
    def shuffleit() {
        def result = new ArrayList(this)
        Collections.shuffle(result)
        result
    }
}

// @Mixin(Shuffler)
@Typed
class Sentence extends ArrayList {
    Sentence(Collection initial) { super(initial) }
}

@Typed
class Main {
    static main(args) {
        def words = ["The", "quick", "brown", "fox"]
        
        Sentence.mixin Shuffler.class

        def sentence = new Sentence(words)
        println sentence.shuffleit()
    }
}

Main.main(null)

http://gppconsole.appspot.com/script/20001

Tuesday, March 29, 2011

sqLite

@Grapes([    
   @Grab(group='org.xerial', module='sqlite-jdbc', version='3.7.2'),
   @GrabConfig(systemClassLoader=true)
 ])
import java.sql.Connection
import java.sql.DriverManager
import java.sql.ResultSet
import java.sql.SQLException
import java.sql.Statement
import java.sql.PreparedStatement
import groovy.sql.Sql
import java.text.SimpleDateFormat

String databasefileName = "testDB.db" // this will write file to your system

Class.forName("org.sqlite.SQLite")
try {
    Sql.newInstance("jdbc:sqlite:"+databasefileName,"org.sqlite.JDBC")
    connection = DriverManager.getConnection("jdbc:sqlite:" + databasefileName)
    executeCommand = connection.createStatement().&executeUpdate

    executeCommand("drop table if exists myTable")

    String ct = "create table myTable (col1 string, col2 date, col3 string, col4 int)"
    executeCommand(ct)

    prepStatment = connection.prepareStatement("insert into myTable values(?, ?, ?, ?)")
} 
catch(SQLException e) { System.err.println("sql: " + e.getMessage()); return }

//populate table
updateSqLiteDB(connection, prepStatment)

Sql sql = new Sql(connection)
//run sql select statement
sql.eachRow("select * from myTable") {
    print(" col1 = " + it.getString("col1").padRight(5))
    print(" col2 = " + it.getDate("col2"))
    print(" col3 = " + it.getString("col3").padRight(15))
    println(" col4 = " + it.getInt("col4"))
}

//close connection
try { 
    if(connection != null) 
      connection.close();
} 
catch(SQLException e) { 
    // connection close failed. 
    System.err.println("sql: " + e) 
} 

////////////////////////////////END OF MAIN/////////////////////////////////

static void updateSqLiteDB(def connection, def prepStatment) {
    try {
        100.times { i ->
            String valCol1 = i.toString()
            Date valCol2 = (new java.sql.Date(111,0,15)) + i
            String valCol3 = (i.toString()) * 5
            Integer valCol4 = i * i
            prepStatment.setString(1, valCol1)
            prepStatment.setDate(2, valCol2)
            prepStatment.setString(3, valCol3)
            prepStatment.setInt(4, valCol4)
            prepStatment.addBatch()
        }
        connection.setAutoCommit(false);
        prepStatment.executeBatch();
        connection.setAutoCommit(true);
    }
    catch(SQLException e) { System.err.println("sql batch: " + e.getMessage()) } 
}

Scrape HTML

Note: This scrape no longer works correctly -- such are the dangers of screen scraping! ;)


@Grapes([
    @Grab(group='org.ccil.cowan.tagsoup', module='tagsoup', version='1.2')
    ,@Grab(group='net.sourceforge.nekohtml', module='nekohtml', version='1.9.14')
    //,@Grab(group='org.htmlcleaner', module='htmlcleaner', version='2.2')
    ]
)

import org.ccil.cowan.tagsoup.* //TagSoup
import org.cyberneko.html.parsers.SAXParser //NekoHTML
import org.htmlcleaner.* //not in maven -- http://htmlcleaner.sourceforge.net/, http://dist.wso2.org/maven2/org/htmlcleaner/htmlcleaner/

def url = new URL("http://lifehacker.com")


println "*" * 15 + 'TAG SOUP' + "*" * 15
slurper = new XmlSlurper(new Parser())
url.withReader { reader ->
    html = slurper.parse(reader)
    println findLinks(html).join('\n')
}


println "*" * 15 + 'NekoHTML' + "*" * 15
def parser = new SAXParser()
parser.setFeature("http://cyberneko.org/html/features/balance-tags/document-fragment",true)
html = new XmlSlurper(parser).parseText(url.text)
println findLinks(html).join('\n')

/*
println "*" * 15 + 'HTMLCleaner' + "*" * 15
def cleaner = new HtmlCleaner()
def node = cleaner.clean(url)
def props = cleaner.getProperties()
def serializer = new SimpleXmlSerializer(props)
def xml = serializer.getXmlAsString(node)
def page = new XmlSlurper(false,false).parseText(xml)
println findLinks(page).join('\n')
*/


///  UTILS
Set findLinks(def root) {
    int cnt = 0
    def posts = root?.depthFirst()?.find { it.@id.text() == "splashPosts"}
    Set links = posts?.depthFirst()?.findAll { it.name().toLowerCase() == "a" && !it.@href.text().contains('/tag/') }.collect([]) { cnt++; it.@href.text() - '?skyline=true&s=i'} as Set
    println "found $cnt"
    return links.sort()
}

http://groovyconsole.appspot.com/script/448003

BONUS: CSS Selectors with JSoup

@Grapes( @Grab(group='org.jsoup', module='jsoup', version='1.6.1' ))
def doc = org.jsoup.Jsoup.connect("http://www.bing.com/search?q=web+scraping").get()
println 'start'
doc.select("#results h3 a").each { node ->
    println '-->' + node.text() + ' == ' + node.attr('href') 
}
println 'done'

BONUS: XPath Selectors with TagSoup

@Grapes( @Grab('org.ccil.cowan.tagsoup:tagsoup:1.2') ) 
import org.ccil.cowan.tagsoup.Parser;
import org.xml.sax.*;
import javax.xml.transform.*;
import javax.xml.transform.dom.*;
import javax.xml.transform.sax.*;
import javax.xml.xpath.*

def urlString = "http://www.bing.com/search?q=web+scraping"
URL url = new URL(urlString);

XMLReader reader = new Parser();
//Transform SAX to DOM
reader.setFeature(Parser.namespacesFeature, false);
reader.setFeature(Parser.namespacePrefixesFeature, false);
Transformer transformer = TransformerFactory.newInstance().newTransformer();
DOMResult result = new DOMResult();
transformer.transform(new SAXSource(reader, new InputSource(url.openStream())), result);

def xpath = XPathFactory.newInstance().newXPath()

//CSS selector: $('#results h3 a')
def results = xpath.evaluate( '//*[@id=\'results\']//h3/a', result.getNode(), XPathConstants.NODESET )

results.each { println it }
println 'done'

Roulette

//roulette gamble
result = 0

netGain = 0
POT = 50000
BET_MULTIPLY = 2.5

YEARS = 5
DAYS = 364
ROUNDS = 500

YEARS.times { it ->

DAYS.times {

money = POT
bet = 1

ROUNDS.times {
    int result = Math.round(Math.random() + 1)
    if (result == 1) { //win
        money += bet
        bet = 1
    } else if (result == 2) { //lose
        money -= bet
        bet = ((money >= bet * BET_MULTIPLY) ? bet * BET_MULTIPLY : 0)
    }
}

gain = Math.round(money) - POT
netGain += gain

}

println "\n yr#${it+1} NET TOTAL:" + netGain
}

http://groovyconsole.appspot.com/script/449006

nodeGraph GUI

@Grapes(
    // http://prefuse.org
    //@Grab(group='org.prefuse', module='prefuse', version='beta-20060220')
    @Grab(group='org.prefuse', module='prefuse', version='beta-20071021')
)
import groovy.swing.SwingBuilder
import javax.swing.WindowConstants
import groovy.util.BuilderSupport
import prefuse.Constants
import prefuse.Display
import prefuse.Visualization
import prefuse.action.ActionList
import prefuse.action.RepaintAction
import prefuse.action.assignment.ColorAction
import prefuse.action.assignment.DataColorAction
import prefuse.action.layout.graph.ForceDirectedLayout
import prefuse.activity.Activity
import prefuse.controls.DragControl
import prefuse.controls.PanControl
import prefuse.controls.ZoomControl
import prefuse.data.Graph
import prefuse.data.Node
import prefuse.render.DefaultRendererFactory
import prefuse.render.LabelRenderer
import prefuse.util.ColorLib
import prefuse.visual.VisualItem

class PrefuseBuilder extends BuilderSupport {
    
    def graph
    def visualization
    
    void setParent(Object parent, Object child) {
        if (parent instanceof Node && child instanceof Node) {
            graph.addEdge(parent, child)
        }
    }
        
    Object createNode(Object name) {
        return createNode(name, null, null)
    }
    
    Object createNode(Object name, Object value) {
        return createNode(name, null, value)
    }
    
    Object createNode(Object name, Map attributes) {
        return createNode(name, attributes, null)
    }
    
    Object createNode(Object name, Map attributes, Object value) {
        def node = null
        if (name == 'node') {
            node = graph.addNode()
            node.setString("name", value)
            visualization.run("color")
        }
        if (name == 'graph') {
            graph = new Graph()
            graph.addColumn("name", String.class)
            visualization = new Visualization()
            visualization.add("graph", graph)
            def labelRenderer = new LabelRenderer("name")
            labelRenderer.setRoundedCorner(8, 8)
            visualization.setRendererFactory(new DefaultRendererFactory(labelRenderer))
            def fill = new ColorAction("graph.nodes", VisualItem.FILLCOLOR, ColorLib.rgb(190,190,255))
            def text = new ColorAction("graph.nodes", VisualItem.TEXTCOLOR, ColorLib.gray(0))
            def edges = new ColorAction("graph.edges", VisualItem.STROKECOLOR, ColorLib.gray(200))
            def color = new ActionList()
            color.add(fill)
            color.add(text)
            color.add(edges)
            def layout = new ActionList(Activity.INFINITY)
            layout.add(new ForceDirectedLayout("graph", true))
            layout.add(new RepaintAction())
            visualization.putAction("color", color)
            visualization.putAction("layout", layout)
            def display = new Display(visualization)
            display.setSize(720, 500)
            display.addControlListener(new DragControl())
            display.addControlListener(new PanControl())
            display.addControlListener(new ZoomControl())
            display.setHighQuality(true)
            visualization.run("color")
            visualization.run("layout")
            node = display
        }
        return node
    }
}

def go = {
   def graph = new PrefuseBuilder().graph {
       node("Grand Parent") {
           node("Parent") {
               node("Child 1")
               node("Child 2") {
                   node("Baby 1")
                   node("Baby 2")
               }
           }
       }
   }
   
   // create a swing app using the Groovy SwingBuilder to display the graph
   def sb = new groovy.swing.SwingBuilder()
   sb.frame(id:"nodeFrame", size:[300,300], visible:true, resizable:true, title:'PrefuseBuilder Test') {
       widget(graph)
   }
   
   sb.nodeFrame.pack()
}

go()

http://groovyconsole.appspot.com/script/453001

Map/Reduce Constructs

.collect() & .inject():

def map1 = { it -> it > 5 ? it * 2 : it * 10 }
def reduce1 = { coll, i -> if (i > 29) coll << i; coll }

println ([1,2,3,4,5,6,7,8,11,88].collect(map1).inject([], reduce1))

def map2 = { it -> it.value *= 2; it }
def reduce2 = { coll, me -> String key = me.key[0]; coll[key] = coll[key] ?: 0; coll[key] += me.value; coll }

println ([a1:1,b1:2,a2:3,b2:4].collect(map2).inject([:], reduce2))

http://groovyconsole.appspot.com/script/450002

groovyWS

@Grab(group='org.codehaus.groovy.modules', module='groovyws', version='0.5.2') // may take a while to download all dependencies!
import groovyx.net.ws.WSClient

proxy = new WSClient("http://www.w3schools.com/webservices/tempconvert.asmx?WSDL", this.class.classLoader)
proxy.initialize()

result = proxy.CelsiusToFahrenheit(0)
println "You are probably freezing at ${result} degrees Farhenheit"

http://groovyconsole.appspot.com/script/451004

Updated (just for fun...)

@Grab(group='org.codehaus.groovy.modules', module='groovyws', version='0.5.2')
import groovyx.net.ws.WSClient

proxy = new WSClient("http://www.w3schools.com/webservices/tempconvert.asmx?WSDL", this.class.classLoader)
proxy.initialize()

(-15..40).step(5) { i ->
    result = proxy.CelsiusToFahrenheit(i)
    println "${i} Celcius == ${result} Farhenheit"
}

GPath

class Person {
 String address
 Name name
}

class Name {
 String first
 String last
}

List ps = []
// create mockup data
10.times { i ->
 Name nm = new Name(first:"first ${i + 1}", last:"last $i")
 ps << new Person(name:nm, address:"${(i+1)*7} Street")
}
assert ps.class.name == "java.util.ArrayList"


//print out each array element
for (p in ps) { System.out.print(p.address + ", ") }; System.out.println("") // Java, yuck!
ps.each { p -> print "${p.address}, " }; println "" // Groovy
println ps.collect { p -> p.address } // returns list, more Groovy


// Now for some GPath magic!!
println ps.address // returns list, same as .collect above
assert  ps.name.class.name == "java.util.ArrayList" // list of Names
assert  ps.name[0].class.name == "Name"
println ps.name.first // returns list
println ps.name.last // returns list

http://groovyconsole.appspot.com/script/449005

GPars Concurrent/Parallel

@Grab(group='org.codehaus.gpars', module='gpars', version='0.11') //not needed in Groovy 1.8.x
import java.util.concurrent.Future
import groovyx.gpars.*
import groovyx.gpars.actor.*
import groovyx.gpars.agent.*

//COLLECTIONS//
List images = ['0001.jpg','2.jpeg','3.png']
GParsPool.withPool {
    def selfPortraits = images.findAllParallel{it.contains('j')}.collectParallel{it.toUpperCase()}
    assert selfPortraits.join(', ') == '0001.JPG, 2.JPEG'
    println selfPortraits.join(', ')

    //a map-reduce functional style
    def smallestSelfPortrait = images.parallel
        .filter{it.contains('j')}
        .map{it.toUpperCase()}
        .min{it.size()}
    assert smallestSelfPortrait == '2.JPEG'
    println smallestSelfPortrait
}

println '*' * 20

//FUTURES//
GParsPool.withPool {
    Closure longLastingCalculation =  { BigInteger a = 1; 2000001.times {i-> a += i }; a }
    //create a new closure, which starts the original closure on a thread pool
    Closure fastCalculation = longLastingCalculation.async()
    //returns almost immediately
    Future result = fastCalculation()
    //do stuff while long calculation performs …
    10.times { print it + '.. '}
    println '\nBLOCKED!'
    //finally ask for the result, blocking if not yet available
    println 'Long result: ' + result.get()
    println 'FINALLY DONE!'
}

println '*' * 20

//ACTORS//
class GameMaster extends DefaultActor {
    int secretNum
    int upto = 20

    void afterStart() {
        secretNum = new Random().nextInt(upto)
    }

    void act() {
        loop {
            react { int num ->
                if (num > secretNum)
                    reply 'too large'
                else if (num < secretNum)
                    reply 'too small'
                else {
                    reply 'you win'
                    terminate()
                }
            }
        }
    }
}

class Player extends DefaultActor {
    String name
    Actor server
    int myNum
    int upto = 20
    int guessCounter = 0

    void act() {
        loop {
            myNum = new Random().nextInt(upto)
            server.send myNum
            react { String msg ->
                guessCounter++
                
                switch (msg) {
                    case 'too large':
                        println "$name: (guess #${guessCounter}) $myNum was too large"
                        break
                    case 'too small':
                        println "$name: (guess #${guessCounter}) $myNum was too small"
                        break
                    case 'you win':
                        println "$name: (guess #${guessCounter}) I won: $myNum"
                        terminate()
                }
            }
        }
    }
}

def master = new GameMaster().start()
def player = new Player(name: 'Player', server: master).start()
[master, player]*.join()
println 'GAME OVER!'

println '*' * 20

//AGENTS//
/**
 * Conference stores number of registrations and allows parties to register and unregister.
 * It inherits from the Agent class and adds the register() and unregister() private methods,
 * which callers may use it the commands they submit to the Conference.
 */
class Conference extends Agent {
    def Conference() { super(0) }
    private def registered() { return data }
    private def register(long num) { data += num }
    private def unregister(long num) { data -= num }
}
final Agent conference = new Conference()  //new Conference created
/**
 * Three external parties will try to register/unregister concurrently
 */
final Thread t1 = Thread.start {
    conference << {register(10L)}               //send a command to register 10 attendees
}
final Thread t4 = Thread.start {
    conference << {register(5L); println "!"+registered()}    //send a command to view registered number
}
final Thread t2 = Thread.start {
    conference << {register(5L)}                //send a command to register 5 attendees
}
final Thread t3 = Thread.start {
    conference << {unregister(13L)}              //send a command to unregister 3 attendees
}

[t1, t2, t3, t4]*.join()

assert 7L == conference.val
println conference.val

println '*' * 20
http://groovyconsole.appspot.com/script/452001

Functional Inject & DSL

def l = [8,9,2,3,4,-1,5]

//max
println l.inject(l[0]) { last, next ->
    last > next ? last : next
}

//isEven
println l.inject([]) { l, n ->
   if (n % 2) l << n * 2
   else l
}
println l.collect{ if (it % 2) {it * 2} }.findAll{it}
println l.findAll{ it % 2 }.collect{ it * 2 }

def filtered = { list, f ->
  list.inject([]) { l, n ->
    if (f(n)) l << n
    else l
  }
}
println filtered(l, {true})
println filtered(l, { it % 2 })




class Mail {
  def to(String b) { println "To:$b" }
  def body(String b) { println "Body:\n$b" }
  def attachment(Object f) { println "Attachment:$f" }
  static send(doIt) {
      def mail = new Mail()
      mail.with doIt
      //mail.smtp()
  }
}

Mail.send {
    to 'Steven.Olsen'
    body 'Dear So And So,\n...\nSincerely!'
    attachment 'file/path/here.txt'
}

http://groovyconsole.appspot.com/script/449004

XML Filter and Printer

def filename = "C:\\test.xml" // will create a file on your system here!

def example="""
<contacts>
   <campuscontact>
      <firstname>Jane</firstname>
      <lastname>Doe</lastname>
      <storenumber>123</storenumber>
   </campuscontact>
   <campuscontact>
      <firstname>Mike</firstname>
      <lastname>Jones</lastname>
      <storenumber>789</storenumber>
   </campuscontact>
   <campuscontact>
      <firstname>Joe</firstname>
      <lastname>Smith</lastname>
      <storenumber>555</storenumber>
   </campuscontact>
</contacts>"""

def nodes = new XmlParser().parseText(example)
def filterBy = ['555','123']

inList = nodes.CampusContact.grep {it.StoreNumber.text() in filterBy}
notInList = nodes.CampusContact.grep {!(it.StoreNumber.text() in filterBy)}
assert inList.size() == 2
assert notInList.size() == 1

//or

notInList = nodes.CampusContact.grep {!(it in inList)}
assert notInList.size() == 1

new PrintWriter(filename).with {
    append("<root>\n")
    p = new XmlNodePrinter(delegate)
    p.preserveWhitespace = true
    p.namespaceAware = false
    inList.each { p.print(it) }
    append("</root>").close()
}

/*
<root>
<campuscontact>
  <firstname>Jane</firstname>
  <lastname>Doe</lastname>
  <storenumber>123</storenumber>
</campuscontact>
<campuscontact>
  <firstname>Joe</firstname>
  <lastname>Smith</lastname>
  <storenumber>555</storenumber>
</campuscontact>
</root>
*/

http://groovyconsole.appspot.com/script/447002

YQL for eBates Stores

String endpoint = "http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20html%20where%20url%3D%22http%3A%2F%2Fwww.ebates.com%2Fstores%2Fall%2Findex.htm%22%20and%20xpath%3D%22%2F%2Fhtml%2Fbody%2Fdiv%2Fdiv%2Fdiv%2Fdiv%2Fdiv%2Fform%2Ftable%2Ftr%5B%40class%3D'store'%5D%2Ftd%5B%40class%3D'storeName'%5D%2Fstrong%2Fa%22"
println 'getting data...'
def xml = endpoint.toURL().text

//println 'got!\n'

//println xml.size()

List names = new XmlSlurper().parseText(xml).results.a.collect{it.@href.text() - '/stores/' - '.htm'}

println "['" + names.sort().join("','") + "']"
return names.size()

RSS Feed Parser/Reader

def rssurl = "http://feeds.digg.com/digg/news/popular.rss"  
def slurp = new XmlSlurper()  
def rssObj = slurp.parse(rssurl).declareNamespace(digg: "http://digg.com/docs/diggrss/", media: "http://search.yahoo.com/mrss/")  

rssObj.channel.item.eachWithIndex { item , num ->  
    println "-------------------------------------------"  
    println "#${num + 1}: ${item.title}"
    println item."digg:category"  
    def url = item."media:thumbnail".@url.text()  
    if ( url ) {  
        println url  
        download(num, url)  
    }  
}  

def download(num , address)  
{  
    def filename =  address.tokenize("/")[-2]  
    def tmp = address.tokenize("/")[-1]   
    def ext = tmp.tokenize(".")[-1]  
    filename = filename << "." << ext  
    println "saving image file : " << filename  
    def file = new FileOutputStream(filename.toString())  
    def out = new BufferedOutputStream(file)  
    out << new URL(address).openStream()  
    out.close()  
}

println "-------------------------------------------\ndone"

http://groovyconsole.appspot.com/script/451002

GContracts

@Grab('org.gcontracts:gcontracts-core:1.2.10') 
import org.gcontracts.annotations.*

@Contracted
@Invariant({ myspeed >= 0 })
class Rocket { 
    boolean moving = false
    int myspeed = 0
    
    @Requires({ !moving && myspeed == 0 })
    void start() { moving = true }
    
    @Requires({ moving && myspeed == 0 })
    void stop() { moving = false }
    
    @Requires({ moving })
    @Ensures({ old.myspeed < myspeed })
    void accelerate(Integer inc) {
        println ">>$inc"
        this.myspeed += inc ?: 1
    }
    
    @Requires({ isStarted() })
    @Ensures({ old.myspeed > myspeed })
    void deccelerate(Integer inc) {  
        println "<<$inc"
        this.myspeed -= inc ?: 1
    }

    
    private boolean isStarted() { return moving } 
    private int speed() { return myspeed }
}

def r = new Rocket()

//r.accelerate() //THIS WOULD FAIL
r.start()
r.accelerate()
println '==' + r.speed()
r.accelerate(2)
println '==' + r.speed()
//r.accelerate(-2) //THIS WOULD FAIL
r.deccelerate(2)
println '==' + r.speed()
//r.deccelerate(2) //THIS WOULD FAIL
//r.stop() //THIS WOULD FAIL
//r.start() //THIS WOULD FAIL
r.deccelerate(1)
r.stop()
r.start()
//r.deccelerate(1) //THIS WOULD FAIL
r.stop()

see: http://groovyconsole.appspot.com/script/449003

Category - Advanced

class StringCategory {
  static String camelize(String self) {
    def newName = self.split("_").collect() { 
      it.substring(0, 1).toUpperCase() + it.substring(1, it.length())
    }.join()
    
    newName[0..<1].toLowerCase() +  newName[1..-1]      
  }
  static Integer getPm(Integer self) {
      (self == 12 ? 12 : self + 12)
  }
  static Integer getAm(Integer self) {
      self == 12 ? 0 : self
  }
}

class SpeakCategory {
    static String shout(String self) {  // Method argument is String, so we can add shout() to String object.
        self.toUpperCase() + '!!'
    }
    static String whisper(String self, boolean veryQuiet = false, Integer a = 0) {
        "${veryQuiet ? 'sssssssh' : 'sssh'}.. $self $a"
    }
    static String army(String self) {
        "$self. Sir, yes sir!"
    }
}

use (StringCategory) {
    println 'Hi_there_fella'.camelize()
    println 12.am + ' o\'clock'
    println 2.pm + ' o\'clock'
}

use (SpeakCategory) {
    println "Pay attention".shout()
    println "Be vewy, vewy, quiet.".whisper()
    println "Be vewy, vewy, quiet.".whisper(true, 1)
    println "Groovy rocks".army()
}

// Or we can use the @Category annotation.
// implicit 'this', no 'self' arg passed in
@Category(String) 
class StreetTalk {
    String hiphop(Integer times = 1) {
        "Yo, yo, here we go! " * times + "${this}"
    }
}

use(StreetTalk) {
    println 'Groovy is dope!'.hiphop(2)
}

http://groovyconsole.appspot.com/script/448002

Category - Simple

class MathCategory {
    static Number sin(Number self, Number add = 0){Math.sin(self) + add}
    static Number cos(Number self, Number add = 0){Math.cos(self) + add}
}

use(MathCategory) {
    println 42.sin()
    println 42.sin(1)
    println 42f.sin()
    println 42f.class.name
    println 42G.cos()
    println 42G.cos(2)
    println 42G.class.name
}

http://groovyconsole.appspot.com/script/451001

Swing Calculator

import groovy.swing.*;
import java.awt.*;
import javax.swing.*;
 
public class Calc{ 
    def sb = new SwingBuilder();
    
    public static void main(String[] args) {
        // create itself
        new Calc(args);
    }

    public Calc(String[] args){

  Toolkit tk = Toolkit.getDefaultToolkit();
  Dimension screenSize = tk.getScreenSize();
  final int WIDTH = screenSize.width;
  final int HEIGHT = screenSize.height;

  int w = WIDTH / 2
  int h = HEIGHT / 2

  int x = (WIDTH / 2) - (w / 2)
  int y = (HEIGHT / 2) - (h / 2) - 50

  sb.frame(id:"calcFrame", title:"XCalc", visible:true, alwaysOnTop:true, resizable:false, defaultCloseOperation:JFrame.EXIT_ON_CLOSE, location:[x, y], size:[w, h]) {
            borderLayout()
            textField(id:"display", editable:false, horizontalAlignment:JTextField.RIGHT, constraints:BorderLayout.NORTH);
            
            panel(constraints:BorderLayout.CENTER){
                gridLayout(cols:4, rows:5, hgap:2, vgap:2)
 
                if (args.size() > 0) 
                     label(args[0])
                else
                     label("")
    
                label("")
                button(text:"<", actionPerformed:{backSpace()})
                button(text:"X", actionPerformed:{clear()})
 
                button(text:"7", actionPerformed:{insertText(it.source.text)})
                button(text:"8", actionPerformed:{insertText(it.source.text)})
                button(text:"9", actionPerformed:{insertText(it.source.text)})
                button(text:"/", actionPerformed:{insertText(it.source.text)}) 
 
                button(text:"4", actionPerformed:{insertText(it.source.text)})
                button(text:"5", actionPerformed:{insertText(it.source.text)})
                button(text:"6", actionPerformed:{insertText(it.source.text)})
                button(text:"*", actionPerformed:{insertText(it.source.text)})
 
                button(text:"1", actionPerformed:{insertText(it.source.text)})
                button(text:"2", actionPerformed:{insertText(it.source.text)})
                button(text:"3", actionPerformed:{insertText(it.source.text)})
                button(text:"-", actionPerformed:{insertText(it.source.text)})
 
                button(text:"0", actionPerformed:{insertText(it.source.text)})
                button(text:".", actionPerformed:{insertText(it.source.text)})
                button(text:"=", actionPerformed:{doEquals()})
                button(text:"+", actionPerformed:{insertText(it.source.text)})                    
            }
        }
        //sb.calcFrame.pack(); //compact display, ignores the size attribute
        sb.calcFrame.show();

    }
 
    public void insertText(text){
        sb.display.text += text
    }
 
    public void backSpace(){
        sb.display.text=sb.display.text[0..sb.display.text.length()-2]        
    }
 
    public void clear(){
        sb.display.text="";
    }
 
    public void doEquals(){
        GroovyShell shell = new GroovyShell();
        sb.display.text = shell.evaluate(sb.display.text);
    }
}
http://groovyconsole.appspot.com/script/449002

What's This Blog About?

Quite simply, this blog serves as a public paste pad for me to place sample Groovy code that I can easily reference later.

Usually the code will run in the console with a simple copy-paste, but not always (due to Grape limitations, etc).

Would love any comments or feedback you'd like to share. Cheers!