Last active
December 30, 2015 11:39
-
-
Save timyates/7823738 to your computer and use it in GitHub Desktop.
Reactive Rock Paper Scissors with Groovy and RxJava
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@Grab( 'com.netflix.rxjava:rxjava-groovy:0.15.1' ) | |
import groovy.transform.* | |
import rx.* | |
@CompileStatic | |
class RPSRX { | |
enum Result { | |
WIN, LOSE, DRAW | |
} | |
enum Move { | |
ROCK( SCISSORS ), | |
PAPER( ROCK ), | |
SCISSORS( PAPER ) | |
Move beats | |
Move( Move beats ) { | |
this.beats = beats | |
} | |
boolean beats( Move other ) { | |
other == beats | |
} | |
} | |
@Immutable | |
static class PlayerMove { | |
String player | |
Move move | |
String toString() { "$player:$move" } | |
} | |
final Random rnd = new Random() | |
private <T> Observable.OnSubscribeFunc<T> subscriptionBuilder( Closure<T> generator ) { | |
{ Observer<T> observer -> | |
boolean running = true | |
new Thread( { -> | |
while( running ) { | |
observer.onNext( generator() ) | |
} | |
observer.onCompleted(); | |
} ).start() | |
return { -> running = false } as Subscription | |
} | |
} | |
Observable<Integer> numbers() { | |
int n = 1 | |
Observable.create( subscriptionBuilder( { -> n++ } ) ) | |
} | |
Observable<Move> moves() { | |
Observable.create( subscriptionBuilder { | |
Move.values()[ rnd.nextInt( Move.values().length ) ] | |
} ) | |
} | |
Observable<PlayerMove> player( String name ) { | |
moves().map { Move it -> new PlayerMove( name, it ) } | |
} | |
String message( Integer index, PlayerMove m1, PlayerMove m2 ) { | |
"Game $index : $m1 vs $m2 : ${resultMessage( m1, m2, result( m1, m2 ) )}" | |
} | |
Result result( PlayerMove m1, PlayerMove m2 ) { | |
m1.move == m2.move ? Result.DRAW : m1.move.beats == m2.move ? Result.WIN : Result.LOSE | |
} | |
String resultMessage( PlayerMove m1, PlayerMove m2, Result r ) { | |
r == Result.DRAW ? 'draw' : r == Result.WIN ? "$m1.player wins" : "$m2.player wins" | |
} | |
Observable<String> game( String name1, String name2 ) { | |
Observable.zip( numbers(), player( name1 ), player( name2 ) ) { Integer n, PlayerMove a, PlayerMove b -> | |
message( n, a, b ) | |
} | |
} | |
} | |
new RPSRX().game( 'tim', 'alice' ).take( 10 ).subscribe { println it } |
Doesn't seem to work anymore:
org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
/Users/rgrinberg/reps/snippets/groovy/rx-rps.groovy: 34: [Static type checking] - Cannot return value of type groovy.lang.Closure <rx.Subscription> on method returning type rx.Observable$OnSubscribeFunc <T>
@ line 34, column 13.
{ Observer<T> observer ->
^
1 error
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@tednaleid Cool! Top tip :-) I hadn't noticed that in the rx-java deps, thanks! :-)
Rock Paper Scissors is my new Hello World ;-) Got my groovy-stream version, a Java 8 one, this one and next I might try project reactor ;-)