Commit f8c7d75b authored by Dave McCormick's avatar Dave McCormick
Browse files

adding tempt files

parent cbec12bb
package controllers;
/**
* Created by davidmccormick on 21/08/16.
*/
import akka.actor.*;
import model.GibberishHub;
import model.GibberishListener;
public class GibberishWebSocketActor extends UntypedActor {
/**
* We don't create the actor ourselves. Instead, Play will ask Akka to make it for us. We have to give Akka a
* "Props" object that tells Akka what kind of actor to create, and what constructor arguments to pass to it.
* This method produces that Props object.
*/
public static Props props(String topic, ActorRef out) {
// Create a Props object that says:
// - I want a GibberishWebSocketActor,
// - and pass (topic, out) as the arguments to its constructor
return Props.create(GibberishWebSocketActor.class, topic, out);
}
/** The Actor for the client (browser) */
private final ActorRef out;
/** The topic string we have subscribed to */
private final String topic;
/** A listener that we will register with our GibberishHub */
private final GibberishListener listener;
/**
* This constructor is called by Akka to create our actor (we don't call it ourselves).
*/
public GibberishWebSocketActor(String topic, ActorRef out) {
this.topic = topic;
this.out = out;
/*
Our GibberishListener, written as a Java 8 Lambda.
Whenever we receive a gibberish, if it matches our topic, convert it to a JSON string, and send it to the client.
*/
this.listener = (g) -> {
String message = g.toString();
out.tell(message, self());
};
// Register this actor to hear gibberish
GibberishHub.getInstance().addListener(listener);
}
/**
* This is called whenever the browser sends a message to the serverover the websocket
*/
public void onReceive(Object message) throws Exception {
// The client isn't going to send us messages down the websocket in this example, so this doesn't matter
if (message instanceof String) {
out.tell("I received your message: " + message, self());
}
}
/**
* This is called by Play after the WebSocket has closed
*/
public void postStop() throws Exception {
// De-register our listener
GibberishHub.getInstance().removeListener(this.listener);
}
}
package controllers;
/**
* Created by davidmccormick on 21/08/16.
*/
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import model.Gibberish;
import model.GibberishHub;
import play.libs.Json;
import play.mvc.Controller;
import play.mvc.LegacyWebSocket;
import play.mvc.Result;
import play.mvc.WebSocket;
public class JsonExample extends Controller {
public static ObjectNode toJson(Gibberish g) {
ObjectNode n = Json.newObject();
n.put("msg", g.getSubject());
n.put("lat", g.getAdverb());
n.put("lng", g.getVerb());
n.put("adjective", g.getAdjective());
n.put("object", g.getObj());
return n;
}
public Result getGibberish(int n) {
ObjectNode[] arr = new ObjectNode[n];
ArrayNode an = Json.newArray();
for (int i = 0; i < n; i++) {
Gibberish g = new Gibberish();
an.add(toJson(g));
// Send the gibberish to the GibberishHub
//GibberishHub.getInstance().send(g);
}
return ok(an);
}
public static Result postGibberish() {
JsonNode json = request().body().asJson();
if(json == null) {
return badRequest("Expecting Json data");
} else {
Gibberish g = new Gibberish();
g.setSubject(json.findPath("subject").textValue());
g.setAdverb(json.findPath("adverb").textValue());
g.setVerb(json.findPath("verb").textValue());
g.setAdjective(json.findPath("adjective").textValue());
g.setObj(json.findPath("object").textValue());
System.out.println(g);
return ok("printed it");
}
}
/**
* Our WebSockets endpoint. We'll assume we're sending String messages for now
*/
public LegacyWebSocket<String> socket(String topic) {
/*
Play framework provides an Actor for client automatically. That's the <code>out</code> argument below.
We need to tell Play what kind of actor we want on the server side. We do that with a "Props" object, because
Play will ask Akka to create the actor for us.
We want a GibberishWebSocketActor, and we want to pass the client actor and the topic as constructor arguments.
GibberishWebSocketActor.props(topic, out) will produce a Props object saying that.
*/
return WebSocket.<String>withActor((out) -> GibberishWebSocketActor.props(topic, out));
}
}
\ No newline at end of file
package model;
/**
* Created by davidmccormick on 21/08/16.
*/
/**
* A nonsense class, just for sending something to the client
*/
public class Gibberish {
static final String[] SUBJECTS = {
"Algernon", "Bertie", "Cecily", "Dahlia", "Edwin"
};
static final String[] ADVERBS = {
"quickly", "slowly", "hesitatingly", "grudgingly", "naughtily"
};
static final String[] VERBS = {
"ate", "juggled", "bounced", "dropped", "hid"
};
static final String[] ADJECTIVES = {
"yellow", "polkadot", "small", "smelly", "tasty", "plastic"
};
static final String[] OBJS = {
"toy ducks", "mice", "bananas", "tissues", "shoes"
};
public String getSubject() {
return subject;
}
public String getAdverb() {
return adverb;
}
public String getVerb() {
return verb;
}
public String getAdjective() {
return adjective;
}
public String getObj() {
return obj;
}
public void setSubject(String subject) {
this.subject = subject;
}
public void setAdverb(String adverb) {
this.adverb = adverb;
}
public void setVerb(String verb) {
this.verb = verb;
}
public void setAdjective(String adjective) {
this.adjective = adjective;
}
public void setObj(String obj) {
this.obj = obj;
}
String subject;
String adverb;
String verb;
String adjective;
String obj;
public String allocate(String[] candidates) {
return candidates[(int)(Math.random() * candidates.length)];
}
public Gibberish() {
this.subject = allocate(SUBJECTS);
this.adverb = allocate(ADVERBS);
this.verb = allocate(VERBS);
this.adjective = allocate(ADJECTIVES);
this.obj = allocate(OBJS);
}
@Override
public String toString() {
return subject + " " + adverb + " " + verb + " " + adjective + " " + obj + ".";
}
}
\ No newline at end of file
package model;
/**
* Created by davidmccormick on 21/08/16.
*/
import com.fasterxml.jackson.databind.node.ObjectNode;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* This is a simple publish-subscribe list. It maintains a list of listeners, and whenever it receives a call to
* <code>send</code>, it calls <code>receiveGibberish</code> on every registered listener.
*/
public class GibberishHub {
List<GibberishListener> listeners;
static final GibberishHub instance = new GibberishHub();
public static GibberishHub getInstance() {
return instance;
}
protected GibberishHub() {
this.listeners = Collections.synchronizedList(new ArrayList<>());
}
public void send(ObjectNode g) {
for (GibberishListener listener : listeners) {
listener.receiveGibberish(g);
}
}
public void addListener(GibberishListener l) {
this.listeners.add(l);
}
public void removeListener(GibberishListener l) {
this.listeners.remove(l);
}
}
\ No newline at end of file
package model;
import com.fasterxml.jackson.databind.node.ObjectNode;
/**
* Created by davidmccormick on 21/08/16.
*/
public interface GibberishListener {
public void receiveGibberish(ObjectNode g);
}
\ No newline at end of file
(function (global) {
function CBuffer() {
// handle cases where "new" keyword wasn't used
if (!(this instanceof CBuffer)) {
// multiple conditions need to be checked to properly emulate Array
if (arguments.length > 1 || typeof arguments[0] !== 'number') {
return CBuffer.apply(new CBuffer(arguments.length), arguments);
} else {
return new CBuffer(arguments[0]);
}
}
// if no arguments, then nothing needs to be set
if (arguments.length === 0)
throw new Error('Missing Argument: You must pass a valid buffer size');
// this is the same in either scenario
this.length = this.start = 0;
// set to callback fn if data is about to be overwritten
this.overflow = null;
// emulate Array based on passed arguments
if (arguments.length > 1 || typeof arguments[0] !== 'number') {
this.data = new Array(arguments.length);
this.end = (this.size = arguments.length) - 1;
this.push.apply(this, arguments);
} else {
this.data = new Array(arguments[0]);
this.end = (this.size = arguments[0]) - 1;
}
// need to `return this` so `return CBuffer.apply` works
return this;
}
function defaultComparitor(a, b) {
return a == b ? 0 : a > b ? 1 : -1;
}
CBuffer.prototype = {
// properly set constructor
constructor : CBuffer,
/* mutator methods */
// pop last item
pop : function () {
var item;
if (this.length === 0) return;
item = this.data[this.end];
// remove the reference to the object so it can be garbage collected
delete this.data[this.end];
this.end = (this.end - 1 + this.size) % this.size;
this.length--;
return item;
},
// push item to the end
push : function () {
var i = 0;
// check if overflow is set, and if data is about to be overwritten
if (this.overflow && this.length + arguments.length > this.size) {
// call overflow function and send data that's about to be overwritten
for (; i < this.length + arguments.length - this.size; i++) {
this.overflow(this.data[(this.end + i + 1) % this.size], this);
}
}
// push items to the end, wrapping and erasing existing items
// using arguments variable directly to reduce gc footprint
for (i = 0; i < arguments.length; i++) {
this.data[(this.end + i + 1) % this.size] = arguments[i];
}
// recalculate length
if (this.length < this.size) {
if (this.length + i > this.size) this.length = this.size;
else this.length += i;
}
// recalculate end
this.end = (this.end + i) % this.size;
// recalculate start
this.start = (this.size + this.end - this.length + 1) % this.size;
// return number current number of items in CBuffer
return this.length;
},
// reverse order of the buffer
reverse : function () {
var i = 0,
tmp;
for (; i < ~~(this.length / 2); i++) {
tmp = this.data[(this.start + i) % this.size];
this.data[(this.start + i) % this.size] = this.data[(this.start + (this.length - i - 1)) % this.size];
this.data[(this.start + (this.length - i - 1)) % this.size] = tmp;
}
return this;
},
// rotate buffer to the left by cntr, or by 1
rotateLeft : function (cntr) {
if (typeof cntr === 'undefined') cntr = 1;
if (typeof cntr !== 'number') throw new Error("Argument must be a number");
while (--cntr >= 0) {
this.push(this.shift());
}
return this;
},
// rotate buffer to the right by cntr, or by 1
rotateRight : function (cntr) {
if (typeof cntr === 'undefined') cntr = 1;
if (typeof cntr !== 'number') throw new Error("Argument must be a number");
while (--cntr >= 0) {
this.unshift(this.pop());
}
return this;
},
// remove and return first item
shift : function () {
var item;
// check if there are any items in CBuff
if (this.length === 0) return;
// store first item for return
item = this.data[this.start];
// recalculate start of CBuffer
this.start = (this.start + 1) % this.size;
// decrement length
this.length--;
return item;
},
// sort items
sort : function (fn) {
this.data.sort(fn || defaultComparitor);
this.start = 0;
this.end = this.length - 1;
return this;
},
// add item to beginning of buffer
unshift : function () {
var i = 0;
// check if overflow is set, and if data is about to be overwritten
if (this.overflow && this.length + arguments.length > this.size) {
// call overflow function and send data that's about to be overwritten
for (; i < this.length + arguments.length - this.size; i++) {
this.overflow(this.data[this.end - (i % this.size)], this);
}
}
for (i = 0; i < arguments.length; i++) {
this.data[(this.size + this.start - (i % this.size) - 1) % this.size] = arguments[i];
}
if (this.size - this.length - i < 0) {
this.end += this.size - this.length - i;
if (this.end < 0) this.end = this.size + (this.end % this.size);
}
if (this.length < this.size) {
if (this.length + i > this.size) this.length = this.size;
else this.length += i;
}
this.start -= arguments.length;
if (this.start < 0) this.start = this.size + (this.start % this.size);
return this.length;
},
/* accessor methods */
// return index of first matched element
indexOf : function (arg, idx) {
if (!idx) idx = 0;
for (; idx < this.length; idx++) {
if (this.data[(this.start + idx) % this.size] === arg) return idx;
}
return -1;
},
// return last index of the first match
lastIndexOf : function (arg, idx) {
if (!idx) idx = this.length - 1;
for (; idx >= 0; idx--) {
if (this.data[(this.start + idx) % this.size] === arg) return idx;
}
return -1;
},
// return the index an item would be inserted to if this
// is a sorted circular buffer
sortedIndex : function(value, comparitor, context) {
comparitor = comparitor || defaultComparitor;
var isFull = this.length === this.size,
low = this.start,
high = isFull ? this.length - 1 : this.length;
// Tricky part is finding if its before or after the pivot
// we can get this info by checking if the target is less than
// the last item. After that it's just a typical binary search.
if (low && comparitor.call(context, value, this.data[high]) > 0) {
low = 0, high = this.end;
}
while (low < high) {
var mid = (low + high) >>> 1;
if (comparitor.call(context, value, this.data[mid]) > 0) low = mid + 1;
else high = mid;
}
return !isFull ? low :
// http://stackoverflow.com/a/18618273/1517919
(((low - this.start) % this.length) + this.length) % this.length;
},
/* iteration methods */
// check every item in the array against a test
every : function (callback, context) {
var i = 0;
for (; i < this.length; i++) {
if (!callback.call(context, this.data[(this.start + i) % this.size], i, this))
return false;
}
return true;
},
// loop through each item in buffer
// TODO: figure out how to emulate Array use better
forEach : function (callback, context) {
var i = 0;
for (; i < this.length; i++) {
callback.call(context, this.data[(this.start + i) % this.size], i, this);
}
},
// check items agains test until one returns true
// TODO: figure out how to emuldate Array use better
some : function (callback, context) {
var i = 0;
for (; i < this.length; i++) {
if (callback.call(context, this.data[(this.start + i) % this.size], i, this))
return true;
}
return false;
},
// calculate the average value of a circular buffer
avg : function () {
return this.length == 0 ? 0 : (this.sum() / this.length);
},
// loop through each item in buffer and calculate sum
sum : function () {
var index = this.length;
var s = 0;
while (index--) s += this.data[index];
return s;
},
// loop through each item in buffer and calculate median
median : function () {
if (this.length === 0)
return 0;
var values = this.slice().sort(defaultComparitor);
var half = Math.floor(values.length / 2);
if(values.length % 2)
return values[half];
else
return (values[half-1] + values[half]) / 2.0;
},
/* utility methods */
// reset pointers to buffer with zero items
// note: this will not remove values in cbuffer, so if for security values
// need to be overwritten, run `.fill(null).empty()`
empty : function () {
var i = 0;
this.length = this.start = 0;
this.end = this.size - 1;
return this;
},
// fill all places with passed value or function
fill : function (arg) {
var i = 0;
if (typeof arg === 'function') {
while(this.data[i] = arg(), ++i < this.size);
} else {
while(this.data[i] = arg, ++i < this.size);
}
// reposition start/end
this.start = 0;
this.end = this.size - 1;
this.length = this.size;
return this;
},
// return first item in buffer
first : function () {
return this.data[this.start];
},
// return last item in buffer
last : function () {
return this.data[this.end];
},
// return specific index in buffer
get : function (arg) {
return this.data[(this.start + arg) % this.size];
},
isFull : function (arg) {
return this.size === this.length;
},
// set value at specified index
set : function (idx, arg) {
return this.data[(this.start + idx) % this.size] = arg;