Thursday, December 29, 2011

ASCII Art

/**
 * Groovy ASCII Art. Converts an image into ASCII.
 * This doesn't work under the web console due to missing AWT classes.
 *
 * Author  : Cedric Champeau (http://twitter.com/CedricChampeau)
 * Updated : Steven Olsen (http://crazy4groovy.blogspot.com)
 */
import java.awt.color.ColorSpace as CS
import java.awt.geom.AffineTransform
import javax.imageio.ImageIO
import java.awt.image.*

String nl = System.getProperty("line.separator")
String slash = System.getProperty("file.separator")
def input = System.console().&readLine

def charset1 = /#@$&%*o=^|-:,'. / //16 chars
//def charset2 = /#@$&%*o=^|-:,'. / //16 chars
def charset2 = /ABCDEFGHIJKLMNOP/ //16 chars

/////////CLI///////////
def cli = new CliBuilder(usage:'asciiArt [options] [path/file/url]', header:'Options:')
cli.h    (longOpt:'help', 'print this message')
cli.bw    (longOpt:'blackWhiteText', 'set normal black/white text')
cli.ctxt(longOpt:'colourText', 'set html colour (text)')
cli.cbg    (longOpt:'colourBackground', 'set html colour (background)')
cli.ics    (longOpt:'isCharSequ', 'output char map in sequence')
cli.vf    (longOpt:'verifyFile', 'verify each file write with a confirmation message')
cli.r    (longOpt:'recursiveFiles', 'recursively iterate through all files in a directory')
cli.cm    (longOpt:'characterMapping', args:1, argName:'percent', 'set custom char map (16)')
cli.s    (longOpt:'scale', args:1, argName:'percentage', 'scale image resolution for output processing (default=40)')
cli.ext    (longOpt:'fileExtension', args:1, argName:'ext', 'name of file extension (default=txt or html)')
cli.incl(longOpt:'fileExtensionInclude', args:1, argName:'regex', 'regex -- name of file extensions to include (default=jpe?g|png|gif)')
cli.outDir    (longOpt:'outputDir', args:1, argName:'...\\dir\\', 'output into dir')
cli.outFile    (longOpt:'outputFile', args:1, argName:'...\\file', 'output into file')

def opt = cli.parse(args)

if (opt.h) {
    cli.usage(); return
}
/////////CLI///////////

List srcs
if (opt.arguments().size() >= 1)
    srcs = opt.arguments()
else
    srcs = [input('image file (local or http): ')] ?: ['http://gordondickens.com/images/groovy.png']

srcs = srcs.collect{ it.replaceAll('"','').split(',') }.flatten()

Set imgSrcList = [] as SortedSet
String filter = opt.incl ?: 'jpe?g|png|gif'
imgSrcList.metaClass.leftShift { if (it.split('\\.')[-1] ==~ "(${filter})") { delegate.add it } }

srcs.each { s ->
    boolean isRemote = s ==~ 'https?://.*'
    if (isRemote) {
        imgSrcList.add s // bypass meatclass filter with .add
        return
    }
    
    def f = new File(s)
    if (!f.directory == true && f.name.split('\\.')[-1] ==~ '(jpe?g|png)') {
        imgSrcList << s
        return
    }
    
    if (opt.r)
        f.eachFileRecurse { fi -> 
            imgSrcList << fi.path }
    else
        f.eachFile { fi -> 
            imgSrcList << fi.path }
}

boolean isMultiImg = (imgSrcList.size() > 1)

Boolean isCharSequGlobal = null // once set to true/false, val will always be used
imgSrcList.eachWithIndex { src, i ->
try {

println "** IMAGE ${i+1} of ${imgSrcList.size()}: $src ..."

boolean isRemote = src ==~ 'https?://.*'
def imgSrc = ImageIO.read( isRemote ? new URL(src) : new File(src))

def scale = opt.s ? opt.s.toBigDecimal() / 100 : 0.4G
String fileName = opt.outFile ?: opt.outDir ? '' : 'SCREEN'

boolean convert = true
while (convert) {
    ////////////INPUT START////////////
    scale *= 100 // reset scale to %
    scale = isMultiImg ? scale : (input("scale of ascii art (percentage) [${scale}]: ") ?: scale)
    scale = scale.toBigDecimal() / 100 // prep scale for usage
    boolean isHtmlColour = opt.bw ? false : (opt.ctxt ?: opt.cbg ?: (input('html colour chars? [y/N]: ').toLowerCase().contains('y') ? true : false) )
    boolean isBgColour = false
    if (isHtmlColour)
        isBgColour = opt.cbg ?: isMultiImg ? false : (input('set background colour? [y/N]: ').toLowerCase().contains('y') ? true : false)
    String charsMapping = opt.cm ?: isMultiImg ? '' : (input('custom char set? (16): ') ?: null)
    if (isHtmlColour && charsMapping && charsMapping.size() < 16 && !isMultiImg)
        println "WARNING: custom char set size is less than 16 (${charsMapping.size()})\n -- must be output in order!"
    boolean isCharSequ = isCharSequGlobal ?: false
    if (isHtmlColour && charsMapping && charsMapping.size() >= 1) {
        isCharSequ = opt.ics ?: isCharSequGlobal ?: (input('output custom chars in order? [Y/n]:').toLowerCase().contains('n') ? false : true)
        isCharSequGlobal = isCharSequ
    }
    if (isHtmlColour && charsMapping && charsMapping.size() < 16 && !isCharSequ)
        println "ERROR: custom char set REJECTED -- size is less than 16 (${charsMapping.size()}) and output is not ordered.\n -- Using default char set."
    if (!isHtmlColour && charsMapping && charsMapping.size() < 16)
        if (i == 0) println "ERROR: non-colour custom char set REJECTED -- size is less than 16 (${charsMapping.size()})\n -- Using default char set."
    if (!isCharSequ && charsMapping?.size() < 16)
        charsMapping = isHtmlColour ? charset2 : charset1
    
    fileName = opt.outFile ?: opt.outDir ? '' : isMultiImg ? '' : input("save ascii art into File (SCREEN = print to screen) [${fileName}]: ") ?: fileName
    ////////////INPUT END////////////

    def yScaleOffset = isHtmlColour ? 0.7 : 0.6 // ascii imgs looked too "tall" -- dev tweakable!
    def cSpace = isHtmlColour ? CS.CS_sRGB : CS.CS_GRAY

    ////////GENERATE////////
    def img = imgSrc
    if (scale != 1.0) {
        def tx = new AffineTransform()
        tx.scale(scale, scale * yScaleOffset)
        def op = new AffineTransformOp(tx, AffineTransformOp.TYPE_BILINEAR)
        def scaled = new BufferedImage((int) (imgSrc.width * scale), (int) (imgSrc.height * scale * yScaleOffset), imgSrc.type)
        img = op.filter(imgSrc, scaled)
    }

    img = new ColorConvertOp(CS.getInstance(cSpace), null).filter(img, null)

    BigInteger pixelCntr = 0G
    def ascii = { rgb ->
        int r = (rgb & 0x00FF0000) >> 16
        int g = (rgb & 0x0000FF00) >> 8
        int b = (rgb & 0x000000FF)

        int gs
        if (isCharSequ)  gs = (pixelCntr++) % charsMapping.size()
        else  gs = ((int) ( r + g + b ) / 3) >> 4 // multiple of 16

        return [ charsMapping.charAt(gs), [r,g,b] ]
    }

    String preStyle = " style='opacity:1.0;font-size:0.8em;line-height:85%;${ isBgColour ? 'color:#FFF;' : '' }'"
    String spanStyle = isBgColour ? "background-color" : "color"

    StringBuilder sb = new StringBuilder()
    if(isHtmlColour) sb.append("<style>pre img{opacity:0.0;border:4px dotted #444} pre img:hover{opacity:0.95;}</style>"+nl+
        "<pre${preStyle}>"+nl+
        "<div style='position:absolute'><img src='${!isRemote ? 'file://' : ''}${src}' style='position:absolute;top:5px;left:5px;'/></div>"+nl)
    img.height.times { y ->
        img.width.times { x ->
            (chr, rgb) = ascii(img.getRGB(x, y))
            if (isBgColour || (isHtmlColour && chr != ' '))
                sb.append("<span style='${spanStyle}:rgb(${rgb.join(',')});'>${chr}</span>")
            else
                sb.append(chr)
        }
        sb.append(nl)
    }
    if(isHtmlColour) sb.append("</pre>"+(nl * 2))
    ////////GENERATE////////

    if (fileName == 'SCREEN') {
        println sb.toString()
    }
    else {
        if (!fileName) {
            File f = new File(src) // to get file name and parent fields
            String fExt = opt.outFile ? '' : '.ascii'
            fExt += opt.outFile ? '' : ('.' + (opt.ext ?: isHtmlColour ? 'html' : 'txt'))
            fileName =  (opt.outDir ?: f.parent) + slash + f.name + fExt
        }

        boolean ok = !opt.vf ?: input("WARNING: writing to file ${fileName} ok? [Y/n]").toLowerCase().contains('n') ? false : true
        File f = new File(fileName)
        if (ok) {
            f << sb.toString()
            println "\t>> ${f.name}"
        }
    }

    convert = isMultiImg ? false : (input('>> export this image to ascii format again? [y/N]: ').toLowerCase().contains('y') ? true : false)
    if (convert) println '=' * 40
}

} catch (Exception e) { println "\tERROR: ${e.toString()}"}
}


gist link

Thursday, December 15, 2011

rabbitMQ - Publish/Subscribe

@Grab('com.rabbitmq:amqp-client:2.7.0')
import com.rabbitmq.client.*

public class SendReceive {
  private String QUEUE
  private Channel channel
  
  public SendReceive( String hostName = "localhost", String queue = "hello" ) {
        QUEUE = queue
        ConnectionFactory factory = new ConnectionFactory()
//      factory.setUsername(userName)
//      factory.setPassword(password)
//      factory.setVirtualHost(virtualHost)
        factory.setHost(hostName)
//      factory.setPort(portNumber)
        Connection connection = factory.newConnection()
        channel = connection.createChannel()
        channel.exchangeDeclare(QUEUE, "fanout")
  }

  public void send( String message )
      throws java.io.IOException {
        channel.basicPublish(QUEUE, "", null, message.getBytes())
        println(" [x] Sent: $message")
        
        //channel.close()
        //connection.close()
  }

  public void receive()
      throws java.io.IOException, java.lang.InterruptedException {
        String queueName = channel.queueDeclare().getQueue();
        channel.queueBind(queueName, QUEUE, "");
        
        QueueingConsumer consumer = new QueueingConsumer(channel)
        channel.basicConsume(queueName, true, consumer)
        println(" [*] Waiting for messages. To exit press CTRL+C")

        while (true) { //loop forever!
            QueueingConsumer.Delivery delivery = consumer.nextDelivery() // blocks for next message!
            String message = new String(delivery.getBody())
            println(" [x] Received: $message")
        }
    }
}

def input = System.console().&readLine // convenience method

def client = new SendReceive(
    input('\nEnter rabbitMQ host location: '),
    input('\nEnter rabbitMQ queue name: ')
)

String userType = input('\n[s]end or [r]eceive?: ')

if (userType && userType == 'r') {
    client.receive()
}
else {
    while(true) {
        String msg = input('\nType a message to send -- To exit press CTRL+C: ')
        client.send(msg)
    }
}

rabbitMQ - Queue

@Grab('com.rabbitmq:amqp-client:2.7.0')
import com.rabbitmq.client.*

public class SendReceive {
  private String QUEUE
  private Channel channel
  
  public SendReceive( String hostName = "localhost", String queue = "hello" ) {
        QUEUE = queue
        ConnectionFactory factory = new ConnectionFactory()
//      factory.setUsername(userName)
//      factory.setPassword(password)
//      factory.setVirtualHost(virtualHost)
        factory.setHost(hostName)
//      factory.setPort(portNumber)
        Connection connection = factory.newConnection()
        channel = connection.createChannel()
        channel.queueDeclare(QUEUE, false, false, false, null)
  }

  public void send( String message )
      throws java.io.IOException {
        channel.basicPublish("", QUEUE, null, message.getBytes())
        println(" [x] Sent: $message")
        
        //channel.close()
        //connection.close()
  }

  public void receive()
      throws java.io.IOException, java.lang.InterruptedException {

        QueueingConsumer consumer = new QueueingConsumer(channel)
        channel.basicConsume(QUEUE, true, consumer)
        println(" [*] Waiting for messages. To exit press CTRL+C")

        while (true) { //loop forever!
            QueueingConsumer.Delivery delivery = consumer.nextDelivery() // blocks for next message!
            String message = new String(delivery.getBody())
            println(" [x] Received: $message")
        }
    }
}

def input = System.console().&readLine // convenience method

def client = new SendReceive(
    input('\nEnter rabbitMQ host location: '),
    input('\nEnter rabbitMQ queue name: ')
)

String userType = input('\n[s]end or [r]eceive?: ')

if (userType && userType == 'r') {
    client.receive()
}
else {
    while(true) {
        String msg = input('\nType a message to send -- To exit press CTRL+C: ')
        client.send(msg)
    }
}

Multi-Assign, Transform Map Keys

(a,b,c) = [1,2]
assert a == 1
assert c == null

(a,b,c) = {[1,2]}()
assert a == 1
assert c == null

Map o = [a:1,b:2,c:3,d:4,aa:5]
// the objective it to keep only the keys with 'a', and uppercase them //

Map f1 = [:]
o.findAll { i -> i.key.contains('a') }
    .each { i -> f1[i.key.toUpperCase()] = i.value }
println f1 // [A:1, AA:5]

Map f2 = [:]
o.each { i ->
    if (i.key.contains('a'))
        f2[i.key.toUpperCase()] = i.value 
}
println f2 // [A:1, AA:5]

Map g1 = o
    .findAll { i -> i.key.contains('a') }
    .inject([:]) { m, i ->
        m[i.key.toUpperCase()] = i.value
        return m
    }
println g1 // [A:1, AA:5]

Map g2 = o
    .inject([:]) { m, i ->
        if (i.key.contains('a'))
            m[i.key.toUpperCase()] = i.value
        return m
    }
println g2 // [A:1, AA:5]

Wednesday, December 14, 2011

Joda-Time

@Grab('joda-time:joda-time:2.0')
import org.joda.time.*
//see also http://groovycookbook.org/basic_types/dates_times_joda/

public boolean isAfterPayDay(DateTime datetime) {
  if (datetime.getMonthOfYear() == 2) {   // February is month 2!!
    return datetime.getDayOfMonth() > 26;
  }
  return datetime.getDayOfMonth() > 28;
}

public Days daysToNewYear(LocalDate fromDate) {
  LocalDate newYear = fromDate.plusYears(1).withDayOfYear(1);
  return Days.daysBetween(fromDate, newYear);
}

public boolean isRentalOverdue(DateTime datetimeRented) {
  Period rentalPeriod = new Period().withDays(2).withHours(12);
  return datetimeRented.plus(rentalPeriod).isBeforeNow();
}

public String getBirthMonthText(LocalDate dateOfBirth) {
  return dateOfBirth.monthOfYear().getAsText(Locale.ENGLISH);
}

DateTime dt = new DateTime();
int month = dt.getMonthOfYear();

DateTime year2000 = dt.withYear(2000);
DateTime twoHoursLater = dt.plusHours(2);

String monthName = dt.monthOfYear().getAsText();
String frenchShortName = dt.monthOfYear().getAsShortText(Locale.FRENCH);
boolean isLeapYear = dt.year().isLeap();
DateTime rounded = dt.dayOfMonth().roundFloorCopy();

println (new DateTime().withDayOfMonth(4).withMonthOfYear(7).withYear(1899).toString('EEE, dd/MM/yyyy HH:mm:ss'))

println (new Date().parse("d/M/yyyy H:m:s","21/3/2008 17:30:20"))
println (Calendar.instance.time.format('MMM dd, yyyy'))
// standard groovy flavor, see also http://groovycookbook.org/basic_types/dates_times/

Various index techniques

enum Coin {
    penny(1), nickel(5), dime(10), quarter(25)
    private final int value
    Coin(int value) { this.value = value }
    public int value() { return value }
}
assert 'penny' == Coin.penny.toString()
assert 1 == Coin.penny.value

Map Coin2 = [penny:1, nickel:5, dime:10, quarter:25]
assert 1 == Coin2.penny

List Coin3 = ['penny', 'nickel']
assert 1 == Coin3.indexOf('nickel')

Monday, December 5, 2011

Gretty

@GrabResolver(name='gretty', 
  root='http://groovypp.artifactoryonline.com/groovypp/libs-releases-local')
@Grab('org.mbte.groovypp:gretty:0.4.302') 
import org.mbte.gretty.httpserver.* 

GrettyServer server = []
server.groovy = [ 
    localAddress: new InetSocketAddress("localhost", 8080), 
    defaultHandler: { 
        response.redirect "/" 
    }, 
    "/:name": {
        get {
            response.text = "Hello ${request.parameters['name']}"
        } 
    } 
] 
server.start()

//see: https://github.com/groovypp/gretty/wiki/Getting-Started

see: Gretty, article

CSV file parser I/O

@Grab(group = 'net.sf.opencsv', module = 'opencsv', version = '2.3')
import au.com.bytecode.opencsv.CSVReader
import au.com.bytecode.opencsv.CSVParser
import au.com.bytecode.opencsv.CSVWriter

String TEST_FILE_NAME = 'C:\\test.csv'
String TEST_OUTPUT_FILE_NAME = 'C:\\testOut.csv'

List< String[] > rows = new CSVReader(
    new FileReader(new File(TEST_FILE_NAME)), 
    CSVParser.DEFAULT_SEPARATOR, 
    CSVParser.DEFAULT_ESCAPE_CHARACTER, 
    CSVParser.DEFAULT_QUOTE_CHARACTER, 1
).readAll()

List< String[] > rowsOver100 = rows.findAll { it[1].toInteger() > 100 }

File output = new File(TEST_OUTPUT_FILE_NAME)
if (output.exists()) {
    output.delete()
}

output.createNewFile()
output.withWriter { writer ->
    new CSVWriter(writer).writeAll(rowsOver100)
}

// for streaming, see also: http://www.groovy-tutorial.org/basic-csv/

Thursday, November 24, 2011

Spread-dot, a Terse Syntax for Collect or Each

List foo = ['a','bc']
assert (foo*.size() == foo.collect{it.size()})
// *. is basically a super terse syntax for .collect -- i.e. call exactly one operation on each 'it'
// also, if you don't want to save the results, * is basically a super terse .each
threads*.join()

Read Lines in Zip File's (File) Entries

//to read a file:

import java.io.*;
import java.util.*;
import java.util.zip.*;

String fname = "C:\\test.zip"

ZipFile zf = new ZipFile(fname)

zf.entries().each { entry ->
    if (!entry.directory) {
        String entryFileName = entry.name
        println entryFileName
        InputStream inp = zf.getInputStream(entryFileName);
        inp.eachLine { line -> println line }
    }
}

//to write a file:
new AntBuilder().zip(destfile:"zipped.zip", basedir=".", excludes="lib .svn plugins *.class")
//http://groovy-almanac.org/creating-a-zipfile-with-antbuilder/

Thursday, November 17, 2011

Class, @Delegate

class A { String doIt() {println 'do A'} }

class B { String doIt() {println 'do B'} }

def pc = { println ( (it == A ? '' : 'x: ') + it.getName()) }

pc(A)
pc(B) //fail
pc(A1) //fail

def a = new A()
pc(a.getClass())


class A1 extends A { 
    @Delegate B b = new B()
    @Delegate A a = new A() // red herring
}

class C { 
    @Delegate B b = new B()
    @Delegate A a = new A() // red herring
}


def a1 = new A1()
a1.doIt() // do A

def c = new C()
c.doIt() // do B

Monday, November 7, 2011

Command line input


def input = System.console().&readLine
def pwd = System.console().&readPassword

String username = input("username: ");
String password = pwd("password: ");

Wednesday, November 2, 2011

Groovy for Java -- Tutorial #5: Closures

Download it HERE or HERE




Groovy for Java -- Tutorial #4: Lists and Maps

Download it HERE or HERE




Groovy for Java -- Tutorial #3: Scripts and Beans

Download it HERE or HERE




Groovy for Java -- Tutorial #2: Hello World!

Download it HERE or HERE




Sunday, October 23, 2011

Groovy for Java -- Tutorial #1: Installation

Download it HERE or HERE




Monday, October 17, 2011

Parallel GETs (throttle test)

import static groovyx.gpars.GParsPool.withPool as parallel

def list = ['http://google.com','http://bing.com','http://dogpile.com','http://ask.com','http://hbsecurity.com']

int maxThreads = list.size()
Range range = list.size()+1..1 // +1 for warmup round
boolean randomizeUrl = true

Long ts // start time for each thread size

println "WARMUP " + "*" * 40
(range).each { throttle ->
ts = Calendar.instance.timeInMillis

parallel( Math.min(maxThreads, throttle) ) { // restrict the thread pool size
list.eachParallel {
Long t = Calendar.instance.timeInMillis
if (randomizeUrl) it += "/?" + Math.random()*10
it.toURL().text // blockin call

println Thread.currentThread().toString() + 
" [$it] DONE >> seconds: " + ((Calendar.instance.timeInMillis - t)  /1000)
}
}

println "total time: " + ((Calendar.instance.timeInMillis - ts) / 1000)
println "*" * 40
}
println "==DONE=="

source: (here)

Friday, October 14, 2011

GPars: Find the greatest product of five consecutive digits in the 1000-digit number

This post was inspired by this article.

/* calc the maximum product of $len consecutive integers $loops times within $bigNum */

String bigNum = '73167176531330624919225119674426574742355349194934969835203127745063262395783180169848018694788518438586156078911294949545950173795833195285320880551112540698747158523863050715693290963295227443043557668966489504452445231617318564030987111217223831136222989342338030813533627661428280644448664523874930358907296290491560440772390713810515859307960866701724271218839987979087922749219016997208880937766572733300105336788122023542180975125454059475224352584907711670556013604839586446706324415722155397536978179778461740649551492908625693219784686224828397224137565705605749026140797296865241453510047482166370484403199890008895243450658541227588666881164271714799244429282308634656748139191231628245861786645835912456652947654568284891288314260769004224219022671055626321111109370544217506941658960408071984038509624554443629812309878799272442849091888458015616609791913387549920052406368991256071760605886116467109407754100225698315520005593572972571636269561882670428252483600823257530420752963450'
int len = 5
int loops = 2000

int poolSize = 2 // for testing

def ts // start time
Integer r // calc result

println "*" * 40

////normal////
ts = Calendar.instance.time.time
loops.times {
r = (0..bigNum.size()-len).collect { bigNum[it..<(it+len)].toList().inject(1) { p,n -> p*n.toInteger() } }.max { it }
}
println ("normal=$r\ntime:" + (Calendar.instance.time.time - ts)/1000)

println "*" * 40

////gpars////
ts = Calendar.instance.time.time
groovyx.gpars.GParsPool.withPool(poolSize) {
loops.times {
r = (0..bigNum.size()-len).collectParallel { bigNum[it..<(it+len)].toList().inject(1) { p,n -> p*n.toInteger() } }.maxParallel { it }
}
}
println ("gpars=$r\ntime:" + (Calendar.instance.time.time - ts)/1000)

println "*" * 40


source posted: here (crashes the console!)

Monday, May 16, 2011

regex pattern "matches" ==~ with metaclass

Closure foundIn = { a, b ->
  print (/$a --> ${b}?? /); 
  return (a ==~ /${b}/); 
}
 
String testConditionRegex = "[abc]"

println foundIn('a', testConditionRegex) //true
println foundIn('z', testConditionRegex) //false
println foundIn(1, testConditionRegex) //false
 
println foundIn(2, 2) //true
println foundIn(12, 12.0) //false
println foundIn(null, testConditionRegex) //false
 
Object.metaClass.foundIn = { return foundIn (delegate, it); }
 
println ("4".foundIn("[1-9]")) //true
println (8.foundIn("[1-9]")) //true
println ((-8).foundIn("[1-9]")) //false

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

Wednesday, May 4, 2011

Until with metaclass and delegate

Object.metaClass.until = { cond, command = {it} ->
    delegate = delegate as List
    def result = []
    for (def i in delegate) {
        if (!cond(i)) { result << command(i) }
        else { break }
    }
    return result
}

def a = [1,2,3,4,5,6,8,1]
def b = [1.0,2d,3f,4.0,5f,6d,8d,1d]
def c = "123456781"
def d = true

println a.until({it == 6})
println a.until({it == 6}) { it + it }
println b.until({it == 6d}) { it + it }
println c.until({it == '6'}) { it + it }
println d.until({it == false}) { it }

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

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!