001/*
002# Licensed Materials - Property of IBM
003# Copyright IBM Corp. 2016  
004 */
005package games;
006
007import java.util.concurrent.Future;
008import java.util.concurrent.TimeUnit;
009
010import com.ibm.streamsx.topology.TStream;
011import com.ibm.streamsx.topology.Topology;
012import com.ibm.streamsx.topology.context.StreamsContextFactory;
013import com.ibm.streamsx.topology.function.Function;
014import com.ibm.streamsx.topology.streams.BeaconStreams;
015
016/**
017 * Play
018 * <a href="https://en.wikipedia.org/wiki/Fizz_buzz">Fizz Buzz</a>.
019 *
020 */
021public class FizzBuzz {
022
023    /**
024     * Entry point for a streaming Fizz Buzz!
025     */
026    public static void main(String[] args) throws Exception {
027        Topology topology = new Topology();
028        
029        // Declare an infinite stream of Long values
030        TStream<Long> counting = BeaconStreams.longBeacon(topology);
031        
032        // Throttle the rate to allow the output to be seen easier
033        counting = counting.throttle(100, TimeUnit.MILLISECONDS);
034        
035        // Print the tuples to standard output
036        playFizzBuzz(counting).print();
037        
038        // At this point the streaming topology (streaming) is
039        // declared, but no data is flowing. The topology
040        // must be submitted to a StreamsContext to be executed.
041
042        // Since this is an streaming graph with an endless
043        // data source it will run for ever
044        Future<?> runningTopology = StreamsContextFactory.getEmbedded().submit(topology);
045        
046        // Run for one minute before canceling.
047        Thread.sleep(TimeUnit.MINUTES.toMillis(1));
048        
049        runningTopology.cancel(true);       
050    }
051    
052    /**
053     * Return a stream that plays Fizz Buzz based
054     * upon the values in the input stream.
055     */
056    public static TStream<String> playFizzBuzz(TStream<Long> counting) {
057        
058        /*
059         * Transform an input stream of longs TStream<Long> to a
060         * stream of strings TStream<String> that follow
061         * the Fizz Buzz rules based upon each value in the
062         * input stream.
063         */
064        TStream<String> shouts = counting.transform(new Function<Long,String>() {
065            private static final long serialVersionUID = 1L;
066
067            @Override
068            public String apply(Long v) {
069                // Skip 0, humans count from 1!
070                if (v == 0)
071                    return null;
072                
073                StringBuilder sb = new StringBuilder();
074                if (v % 3 == 0)
075                    sb.append("Fizz");
076                if (v % 5 == 0)
077                    sb.append("Buzz");
078                
079                if (sb.length() == 0)
080                    sb.append(Long.toString(v));
081                else
082                    sb.append("!");
083                
084                return sb.toString();
085            }});
086        
087        return shouts;
088    }
089
090}