(function(window) {
(function(window) {
var sudo = {
delegates: {},
The sudo.extensions namespace holds the objects that are stand alone modules
which
can be implemented
(mixed-in) in sudo Class Objects
namespace
extensions: {},
Extract a value located at path
relative to the passed in object
param
{String} path
. The key in the form of a dot-delimited path.
param
{object} obj
. An object literal to operate on.
returns
{*|undefined}. The value at keypath or undefined if not found.
getPath: function getPath(path, obj) {
var key, p;
p = path.split('.');
for (key; p.length && (key = p.shift());) {
if(!p.length) return obj[key];
else obj = obj[key] || {};
}
return obj;
},
Inherit the prototype from a parent to a child.
Set the childs constructor for subclasses of child.
Subclasses of the library base classes will not
want to use this function in most use-cases. Why? User Sudo Class Objects
possess their own constructors and any call back to a superclass
constructor
will generally be looking for the library Object's constructor.
param
{function} parent
param
{function} child
inherit: function inherit(parent, child) {
child.prototype = Object.create(parent.prototype);
child.prototype.constructor = child;
},
Notice there is no need to extrinsically instruct how to make the sandwich, just the elegant single command.
returns
{string}
makeMeASandwich: function makeMeASandwich() {return 'Okay.';},
Method for assuring a Namespace is defined.
param
{string} path
. The path that leads to a blank Object.
namespace: function namespace(path) {
if (!this.getPath(path, window)) {
this.setPath(path, {}, window);
}
},
The premier object takes precedence over all others so define it at the topmost level.
type
{Object}
premier: null,
Traverse the keypath and get each object (or make blank ones) eventually setting the value at the end of the path
param
{string} path
. The path to traverse when setting a value.
param
{*} value
. What to set.
param
{Object} obj
. The object literal to operate on.
setPath: function setPath(path, value, obj) {
var p = path.split('.'), key;
for (key; p.length && (key = p.shift());) {
if(!p.length) obj[key] = value;
else if (obj[key]) obj = obj[key];
else obj = obj[key] = {};
}
},
Some sudo Objects use a unique integer as a tag
for identification.
(Views for example). This ensures they are indeed unique.
uid: 0,
An integer used as 'tags' by some sudo Objects as well as a unique string for views when needed
param
{string} prefix. Optional string identifier
unique: function unique(prefix) {
return prefix ? prefix + this.uid++ : this.uid++;
},
Remove a key:value pair from this object's data store
located at
param
{String} path
param
{Object} obj
The object to operate on.
unsetPath: function unsetPath(path, obj) {
var p = path.split('.'), key;
for (key; p.length && (key = p.shift());) {
if(!p.length) delete obj[key];
this can fail if a faulty path is passed. using getPath beforehand can prevent that
else obj = obj[key];
}
}
};
While getting a new XMLHttpRequest is standardized now, we are still going to provide this syntactic sugar to allow the setting of global headers (will be set on each request) as well as the onload, onerrer, and onloadend callbacks to be set with one call. Does not have a default for params.url all others are: { verb: 'GET', responseType: 'text', url: mandatory, params: optional, onload: $.noop, onerrer: optional, onloadend: optional, user: optional, password: optional } If the verb is 'GET' and params is truthy it will be appended to the url as a queryString (after being serialized if a hash -- assumed to be a string if not). This method does not call send() so do that once you have the xhr back, remember to set any pertinant MIME types if sending data via setRequestHeader (unless its already in the sudo.xhrHeaders).
param
{object} attributes for the XHR
returns
{object} the xhr object
sudo.getXhr = function getXhr(params) {
var xhr = new XMLHttpRequest(), keys = Object.keys(sudo.xhrHeaders),
len = keys.length, i;
params.verb || (params.verb = 'GET');
check if we need a QS
if(params.verb === 'GET' && params.params) {
assumed to be an object literal
if(typeof params.params !== 'string') params.params = Object.serialize(params.params);
params.url += ('?' + params.params);
}
xhr.responseType = params.responseType || 'text';
xhr.open(params.verb, params.url, true, params.user, params.password);
xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
so that some common use-case request headers can be set automagically, for blob, document, buffer and others handle manually after getting the xhr back.
if(xhr.responseType === 'text') {
could be json or plain string TODO expand this to a hash lookup for other types later
if(params.contentType && params.contentType === 'json') {
xhr.setRequestHeader('Accept', 'application/json');
xhr.setRequestHeader('Content-Type', 'application/json');
TODO does this work as expected?
} else {
xhr.setRequestHeader('Accept', 'text/plain');
xhr.setRequestHeader('Content-Type', 'text/plain');
}
}
set any custom headers
if(len) for(i = 0; i < len; i++) xhr.setRequestHeader(keys[i], sudo.xhrHeaders[keys[i]]);
The native xhr considers many status codes a success that we do not, wrap the onload so that we can call success or error based on code
xhr.onload = function(e) {
if(this.status >= 200 && this.status < 300 || this.status === 304) this._onload_(e);
else this.onerror(e);
};
xhr._onload_ = params.onload || $.noop;
xhr.onerror = params.onerror || $.noop;
if(params.timeout) xhr.timeout = params.timeout;
if(params.ontimeout) xhr.ontimeout = params.ontimeout;
if(params.onloadend) xhr.onloadend = params.onloadend;
return xhr;
};// ##Base Class Object
All sudo.js objects inherit base, giving the ability
to utilize delegation, the base
function and the
construct
convenience method.
constructor
sudo.Base = function() {
can delegate
this.delegates = [];
a beautiful and unique snowflake
this.uid = sudo.unique();
};
Push an instance of a Class Object into this object's _delegates_
list.
param
{Object} an instance of a sudo.delegates Class Object
returns
{Object} this
sudo.Base.prototype.addDelegate = function addDelegate(del) {
del.delegator = this;
this.delegates.push(del);
if('addedAsDelegate' in del) del.addedAsDelegate(this);
return this;
};
Lookup the function matching the name passed in and call it with
any passed in argumets scoped to the calling object.
This method will avoid the recursive-loop problem by making sure
that the first match is not the function that called base
.
params
{*} any other number of arguments to be passed to the looked up method
along with the initial method name
sudo.Base.prototype.base = function base() {
var args = Array.prototype.slice.call(arguments),
name = args.shift(),
found = false,
obj = this,
curr;
find method on the prototype, excluding the caller
while(!found) {
curr = Object.getPrototypeOf(obj);
if(curr[name] && curr[name] !== this[name]) found = true;
keep digging
else obj = curr;
}
return curr[name].apply(this, args);
};
A convenience method that alleviates the need to place:
Object.getPrototypeOf(this).consturctor.apply(this, arguments)
in every constructor
sudo.Base.prototype.construct = function construct() {
Object.getPrototypeOf(this).constructor.apply(this, arguments || []);
};
From this object's list of delegates find the object whose _role_
matches
the passed name
and:
meth
is falsy return the delegate.
2 if meth
is truthy bind its method (to the delegate) and return the methodparam
{String} role
The role property to match in this object's delegates list
param
{String} meth
Optional method to bind to the action this delegate is being used for
returns
sudo.Base.prototype.delegate = function delegate(role, meth) {
var del = this.delegates, i;
for(i = 0; i < del.length; i++) {
if(del[i].role === role) {
if(!meth) return del[i];
return del[i][meth].bind(del[i]);
}
}
};
Fetch a delegate whose role property matches the passed in argument.
Uses the delegate
method in its 'single argument' form, included for
API consistency
param
{String} role
'returns' {Object|undefined}
sudo.Base.prototype.getDelegate = function getDelegate(role) {
return this.delegate(role);
};
From this objects delegates
list remove the object (there should only ever be 1)
whose role matches the passed in argument
param
{String} role
returns
{Object} this
sudo.Base.prototype.removeDelegate = function removeDelegate(role) {
var del = this.delegates, i;
for(i = 0; i < del.length; i++) {
if(del[i].role === role) {
no delegator for you
del[i].delegator = void 0;
del.splice(i, 1);
return this;
}
}
return this;
};
private
sudo.Base.prototype.role = 'base';
Model Objects expose methods for setting and getting data, and
can be observed if implementing the Observable Extension
param
{object} data. An initial state for this model.
constructor
sudo.Model = function(data) {
sudo.Base.call(this);
this.data = data || {};
only models are observable
this.callbacks = [];
this.changeRecords = [];
};
Model inherits from sudo.Base
private
sudo.inherit(sudo.Base, sudo.Model);
Returns the value associated with a key.
param
{String} key
. The name of the key
returns
{*}. The value associated with the key or false if not found.
sudo.Model.prototype.get = function get(key) {
return this.data[key];
};
Uses the sudo namespace's getpath function operating on the model's data hash.
returns
{*|undefined}. The value at keypath or undefined if not found.
sudo.Model.prototype.getPath = function getPath(path) {
return sudo.getPath(path, this.data);
};
Assembles and returns an object of key:value pairs for each key contained in the passed in Array.
param
{array} ary
. An array of keys.
returns
{object}
sudo.Model.prototype.gets = function gets(ary) {
var i, obj = {};
for (i = 0; i < ary.length; i++) {
obj[ary[i]] = ary[i].indexOf('.') === -1 ? this.data[ary[i]] :
this.getPath(ary[i]);
}
return obj;
};
private
sudo.Model.prototype.role = 'model';
Set a key:value pair.
param
{String} key
. The name of the key.
param
{*} value
. The value associated with the key.
returns
{Object} this
sudo.Model.prototype.set = function set(key, value) {
NOTE: intentional possibilty of setting a falsy value
this.data[key] = value;
return this;
};
Uses the sudo namespace's setpath function operating on the model's data hash.
param
{String} path
param
{*} value
returns
{Object} this.
sudo.Model.prototype.setPath = function setPath(path, value) {
sudo.setPath(path, value, this.data);
return this;
};
Invokes set()
or setPath()
for each key value pair in obj
.
Any listeners for those keys or paths will be called.
param
{Object} obj
. The keys and values to set.
returns
{Object} this
sudo.Model.prototype.sets = function sets(obj) {
var i, k = Object.keys(obj);
for(i = 0; i < k.length; i++) {
k[i].indexOf('.') === -1 ? this.set(k[i], obj[k[i]]) :
this.setPath(k[i], obj[k[i]]);
}
return this;
};
Remove a key:value pair from this object's data store
param
{String} key
returns
{Object} this
sudo.Model.prototype.unset = function unset(key) {
delete this.data[key];
return this;
};
Uses sudo.unsetPath
operating on this models data hash
param
{String} path
returns
{Object} this
sudo.Model.prototype.unsetPath = function unsetPath(path) {
sudo.unsetPath(path, this.data);
return this;
};
Deletes a number of keys or paths from this object's data store
param
{array} ary
. An array of keys or paths.
returns
{Objaect} this
sudo.Model.prototype.unsets = function unsets(ary) {
var i;
for(i = 0; i < ary.length; i++) {
ary[i].indexOf('.') === -1 ? this.unset(ary[i]) :
this.unsetPath(ary[i]);
}
return this;
};
A container is any object that can both contain other objects and itself be contained.
param
{Array|Object} 'arg'. Optional array or hash
of child objects which the Container will add as child objects
via addChildren
constructor
sudo.Container = function(arg) {
sudo.Base.call(this);
this.children = [];
this.childNames = {};
if(arg) this.addChildren(arg);
};
Container is a subclass of sudo.Base
sudo.inherit(sudo.Base, sudo.Container);
Adds a View to this container's list of children.
Also adds an 'index' property and an entry in the childNames hash.
If addedToParent
if found on the child, call it, sending this
as an argument.
param
{Object} child
. View (or View subclass) instance.
param
{String} name
. An optional name for the child that will go in the childNames hash.
returns
{Object} this
sudo.Container.prototype.addChild = function addChild(child, name) {
var c = this.children;
child.parent = this;
child.index = c.length;
if(name) {
child.name = name;
this.childNames[name] = child.index;
}
c.push(child);
if('addedToParent' in child) child.addedToParent(this);
return this;
};
Allows for multiple children to be added to this Container by passing either an Array or an Object literal.
see addChild
param
{Array|Object} arg
. An array of children to add or an
Object literal in the form {name: child}
returns
{Object} this
sudo.Container.prototype.addChildren = function addChildren(arg) {
var i, keys;
Array?
if(Array.isArray(arg)) {
for (i = 0; i < arg.length; i++) {
this.addChild(arg[i]);
}
} else {
keys = Object.keys(arg);
for (i = 0; i < keys.length; i++) {
this.addChild(arg[keys[i]] , keys[i]);
}
}
return this;
};
By default, bubble
returns the current view's parent (if it has one)
returns
{Object|undefined}
sudo.Container.prototype.bubble = function bubble() {return this.parent;};
Call a named method and pass any args to each child in a container's collection of children
param
{*} Any number of arguments the first of which must be
The named method to look for and call. Other args are passed through
returns
{object} this
sudo.Container.prototype.eachChild = function eachChild(/*args*/) {
var args = Array.prototype.slice.call(arguments),
which = args.shift(), i, len, curr;
for (i = 0, len = this.children.length; i < len; i++) {
curr = this.children[i];
if(which in curr) curr[which].apply(curr, args);
}
return this;
};
If a child was added with a name, via addChild
,
that object can be fetched by name. This prevents us from having to reference a
containers children by index. That is possible however, though not preferred.
param
{String|Number} id
. The string name
or numeric index
of the child to fetch.
returns
{Object|undefined} The found child
sudo.Container.prototype.getChild = function getChild(id) {
return typeof id === 'string' ? this.children[this.childNames[id]] :
this.children[id];
};
Method is called with the index
property of a subview that is being removed.
Beginning at i
decrement subview indices.
param
{Number} i
private
sudo.Container.prototype._indexChildren_ = function _indexChildren_(i) {
var c = this.children, obj = this.childNames, len;
for (len = c.length; i < len; i++) {
c[i].index--;
adjust any entries in childNames
if(c[i].name in obj) obj[c[i].name] = c[i].index;
}
};
Find the intended child from my list of children and remove it, removing the name reference and re-indexing
remaining children. This method does not remove the child's DOM.
Override this method, doing whatever you want to the child's DOM, then call base('removeChild')
to do so.
param
{String|Number|Object} arg
. Children will always have an index
number, and optionally a name
.
If passed a string name
is assumed, so be sure to pass an actual number if expecting to use index.
An object will be assumed to be an actual sudo Class Object.
returns
{Object} this
sudo.Container.prototype.removeChild = function removeChild(arg) {
var i, t = typeof arg, c;
normalize the input
if(t === 'object') c = arg;
else c = t === 'string' ? this.children[this.childNames[arg]] : this.children[arg];
i = c.index;
remove from the children Array
this.children.splice(i, 1);
remove from the named child hash if present
delete this.childNames[c.name];
child is now an orphan
delete c.parent;
delete c.index;
delete c.name;
this._indexChildren_(i);
return this;
};
Remove all children, name references and adjust indexes accordingly. This method calls removeFromParent as each child may have overridden logic there.
see removeChild
param
{bool} keep
Optional arg to instruct the parent to detach
its $el
rather than the default remove
if truthy
returns
{object} this
sudo.Container.prototype.removeChildren = function removeChildren(keep) {
use the child names hash to avoid loop modification errors
var keys = Object.keys(this.childNames), i;
for (i = 0; i < keys.length; i++) {
this.getChild(keys[i]).removeFromParent(keep);
}
return this;
};
Remove this object from its parents list of children. Does not alter the dom - do that yourself by overriding this method or chaining method calls
sudo.Container.prototype.removeFromParent = function removeFromParent() {
will error without a parent, but that would be your fault...
this.parent.removeChild(this);
return this;
};
sudo.Container.prototype.role = 'container';
The call to the specific method on a (un)specified target happens here.
If this Object is part of a sudo.Container
maintained hierarchy
the 'target' may be left out, causing the bubble()
method to be called.
What this does is allow children of a sudo.Container
to simply pass
events upward, delegating the responsibility of deciding what to do to the parent.
TODO Currently, only the first target method found is called, then the bubbling is stopped. Should bubbling continue all the way up the 'chain'?
param
{*} Any number of arguments is supported, but the first is the only one searched for info.
A sendMethod will be located by:
sendMethod
property if it is an object
In the case a specified target exists at this.model.get('sendTarget')
it will be used
Any other args will be passed to the sendMethod after this
returns
{Object} this
sudo.Container.prototype.send = function send(/*args*/) {
var args = Array.prototype.slice.call(arguments),
d = this.model && this.model.data, meth, targ, fn;
normalize the input, common use cases first
if(d && 'sendMethod' in d) meth = d.sendMethod;
else if(typeof args[0] === 'string') meth = args.shift();
less common but viable options
if(!meth) {
passed as a custom data attr bound in events
meth = 'data' in args[0] ? args[0].data.sendMethod :
passed in a hash from something or not passed at all
args[0].sendMethod || void 0;
}
target is either specified or my parent
targ = d && d.sendTarget || this.bubble();
obvious chance for errors here, don't be dumb
fn = targ[meth];
while(!fn && (targ = targ.bubble())) {
fn = targ[meth];
}
sendMethods expect a signature (sender, ...)
if(fn) {
args.unshift(this);
fn.apply(targ, args);
}
return this;
};
Create an instance of a sudo.View object. A view is any object
that maintains its own el
, that being some type of DOM element.
Pass in a string selector or an actual dom node reference to have the object
set that as its el
. If no el
is specified one will be created upon instantiation
based on the tagName
(div
by default). Specify className
, id
(or other attributes if desired)
as an (optional) attributes
object literal on the data
arg.
The view object uses some jbone for dom manipulation
and event delegation etc... A this
reference is located
at this.el
and this.qs
scopes queries to this objects el
, i.e it's
a shortcut for this.el.querySelector(selector)
in addition this.qsa
does the same for the querySelectorAll method
param
{string|element|query} el
. Otional el for the View instance.
param
{Object} data
. Optional data object-literal which becomes the initial state
of a new model located at this.model
. Also can be a reference to an existing sudo.Model instance
constructor
sudo.View = function(el, data) {
sudo.Container.call(this);
allow model instance to be passed in as well
if(data) {
this.model = data.role === 'model' ? data :
this.model = new sudo.Model(data);
}
this.setEl(el);
};
View inherits from Container
private
sudo.inherit(sudo.Container, sudo.View);
Premier functionality provides hooks for behavioral differentiation among elements or class objects.
returns
{Object} this
sudo.View.prototype.becomePremier = function becomePremier() {
var p, f = function() {
this.isPremier = true;
sudo.premier = this;
}.bind(this);
is there an existing premier that isn't me?
if((p = sudo.premier) && p.uid !== this.uid) {
ask it to resign and call the cb
p.resignPremier(f);
} else f(); // no existing premier
return this;
};
the el needs to be normalized before use
private
sudo.View.prototype._normalizedEl_ = function _normalizedEl_(el) {
var _el = typeof el === 'string' ? document.querySelector(el) : el;
if there is not a top level query returned the desired node may be in a document fragment not in the DOM yet. We will check the parent's el if available, or return the empty query
return _el ? _el : (this.parent ? this.parent.qs(el) : _el);
};
Resign premier status
param
{Function} cb
. An optional callback to execute
after resigning premier status.
returns
{Object} this
sudo.View.prototype.resignPremier = function resignPremier(cb) {
var p;
this.isPremier = false;
only remove the global premier if it is me
if((p = sudo.premier) && p.uid === this.uid) {
sudo.premier = null;
}
fire the cb if passed
if(cb) cb();
return this;
};
private
sudo.View.prototype.role = 'view';
A view must have an element, set that here.
Node is always then available as this.el
.
param
{string=|element} el
returns
{Object} this
sudo.View.prototype.setEl = function setEl(el) {
var d = this.model && this.model.data, a, i, k, t;
if(!el) {
normalize any relevant data
t = d ? d.tagName || 'div': 'div';
this.el = document.createElement(t);
if(d && (a = d.attributes)) {
iterate and set the attributes
k = Object.keys(a);
for(i = 0; i < k.length; i++) {
this.el.setAttribute(k[i], a[k[i]]);
}
}
} else this.el = this._normalizedEl_(el);
return this;
};
Return a single Element matching sel
scoped to this View's el.
This is an alias to this.el.querySelector(sel)
.
param
{string} sel
. A DOM compatible selector
returns
{node|null} A 'querified' result matching the selector
sudo.View.prototype.qs = function(sel) {
return this.el.querySelector(sel);
};
Return multiple Elements (a NodeList) matching sel
scoped to this View's el.
This is an alias to this.el.querySelectorAll(sel)
.
param
{string} sel
. A querySelectorAll compatible selector
returns
{Elements | undefined} Results matching the selector (or undefined if not)
sudo.View.prototype.qsa = function(sel) {
return this.el.querySelectorAll(sel);
};
Allow the default {{ js code }}, {{= key }}, and {{- escape stuff }} micro templating delimiters to be overridden if desired
type
{Object}
sudo.templateSettings = {
evaluate: /\{\{([\s\S]+?)\}\}/g,
interpolate: /\{\{=([\s\S]+?)\}\}/g,
escape: /\{\{-([\s\S]+?)\}\}/g
};
Certain characters need to be escaped so that they can be put into a string literal when templating.
type
{Object}
sudo.escapes = {};
(function(s) {
var e = {
'\\': '\\',
"'": "'",
r: '\r',
n: '\n',
t: '\t',
u2028: '\u2028',
u2029: '\u2029'
};
for (var key in e) if(e.hasOwnProperty(key)) s.escapes[e[key]] = key;
}(sudo));
sudo.htmlEscapes = {
'&': '&',
'<': '<',
'>': '>',
'"': '"',
"'": ''',
'/': '/'
};
sudo.escaper = /\\|'|\r|\n|\t|\u2028|\u2029/g;
sudo.htmlEscaper = /[&<>"'\/]/g;
sudo.unescaper = /\\(\\|'|r|n|t|u2028|u2029)/g;
sudo.escape = function(str) {
return str.replace(sudo.htmlEscaper, function(match) {
return sudo.htmlEscapes[match];
});
};
Within an interpolation, evaluation, or escaping, remove HTML escaping that had been previously added.
param
{string} str
sudo.unescape = function unescape(str) {
return str.replace(sudo.unescaper, function(match, escape) {
return sudo.escapes[escape];
});
};
JavaScript micro-templating, similar to John Resig's (and it's offspring) implementation.
sudo templating preserves whitespace, and correctly escapes quotes within interpolated code.
Unlike others sudo.template requires a scope name (to avoid the use of with
) and will spit at you
if it is not present.
param
{string} str
. The 'templated' string.
param
{Object} data
. Optional hash of key:value pairs.
param
{string} scope
. Optional context name of your data object
, set to 'data' if falsy.
sudo.template = function template(str, data, scope) {
scope || (scope = 'data');
var settings = sudo.templateSettings, render, tmpl,
Compile the template source, taking care to escape characters that cannot be included in a string literal and then unescape them in code blocks.
source = "_p+='" + str.replace(sudo.escaper, function(match) {
return '\\' + sudo.escapes[match];
}).replace(settings.escape, function(match, code) {
return "'+\n((_t=(" + sudo.unescape(code) + "))==null?'':sudo.escape(_t))+\n'";
}).replace(settings.interpolate, function(match, code) {
return "'+\n((_t=(" + sudo.unescape(code) + "))==null?'':_t)+\n'";
}).replace(settings.evaluate, function(match, code) {
return "';\n" + sudo.unescape(code) + "\n_p+='";
}) + "';\n";
source = "var _t,_p='';" + source + "return _p;\n";
render = new Function(scope, source);
if (data) return render(data);
tmpl = function(data) {
return render.call(this, data);
};
Provide the compiled function source as a convenience for reflection/compilation
tmpl.source = 'function(' + scope + '){\n' + source + '}';
return tmpl;
};
Create an instance of an Object, inheriting from sudo.View that:
this.model.get('template')
.renderTarget
property in its data store. If so this will be the location
the child injects itself into (if not already in) the DOMrenderTarget
.render
method that when called re-hydrates it's el by passing its
internal data store to its templateconstructor
sudo.DataView = function(el, data) {
sudo.View.call(this, el, data);
implements the listener extension
$.extend(this, sudo.extensions.listener);
dont autoRender on the setting of events,
this.modelChangeBlacklist = {event: true, events: true};
renderOnModelChange types observe their own model
if(this.model.data.renderOnModelChange) {
if(!this.model.observe) $.extend(this.model, sudo.extensions.observable);
}
};
private
sudo.inherit(sudo.View, sudo.DataView);
Container's will check for the presence of this method and call it if it is present.
Options affecting this method are:
renderOnModelChange
: render not called until this view's model is changed via
a set
, sets
or unsets
operation.
renderOnAddedToParent
: render is called from this method.
If neither is set in this view's model it is up to the developer to call render().
Regardless of the rendering options any events in the event(s)
property are bound
param
{object} parent
this view's parent
returns
{object} this
sudo.DataView.prototype.addedToParent = function(parent) {
this.bindEvents();
these two are not necessarily exclusive
if(this.model.data.renderOnModelChange) this.observer = this.model.observe(this.render.bind(this));
if(this.model.data.renderOnAddedToParent) return this.render();
return this;
};
Remove this object from the DOM and its parent's list of children.
Overrides sudo.View.removeFromParent
to unbind events and remove
its $el
returns
{Object} this
sudo.DataView.prototype.removeFromParent = function removeFromParent() {
this.parent.removeChild(this);
this.unbindEvents().el.parentNode.removeChild(this.el);
in the case that this.model is 'foreign'
if(this.observer) {
this.model.unobserve(this.observer);
delete this.observer;
}
return this;
};
(Re)hydrate the innerHTML of this object via its template and data store.
If a renderTarget
is present this Object will inject itself into the target via
this.get('renderMethod')
or defualt to appendChild
. After injection, the renderTarget
is deleted from this Objects data store (to prevent multiple injection).
Event unbinding/rebinding is generally not necessary for the Objects innerHTML as all events from the
Object's list of events (this.get('event(s)'))
are delegated to the $el when added to parent.
param
{object} change
dataviews may be observing their model if renderOnModelChange: true
returns
{Object} this
sudo.DataView.prototype.render = function render(change) {
return early if a blacklisted
key is set to my model
if(change && this.modelChangeBlacklist[change.name]) return this;
var d = this.model.data;
(re)hydrate the innerHTML
if(typeof d.template === 'string') d.template = sudo.template(d.template);
this.el.innerHTML = d.template(d);
am I in the dom yet?
if(d.renderTarget) {
this._normalizedEl_(d.renderTarget)[d.renderMethod || 'appendChild'](this.el);
delete d.renderTarget;
}
return this;
};
private
sudo.DataView.prototype.role = 'dataview';
Abstracts location and history events, parsing their information into a normalized object that is then set to an Observable class instance
constructor
sudo.Navigator = function(data) {
this.started = false;
this.slashStripper = /^\/+|\/+$/g;
this.leadingStripper = /^[#\/]|\s+$/g;
this.trailingStripper = /\/$/;
this.construct(data);
};
Navigator inherits from sudo.Model
sudo.Navigator.prototype = Object.create(sudo.Model.prototype);
Put together a path from the arguments passed in. If you want a hash paramaterized pass it as the last arg.
params
{*} N number of path fragments
returns
{string} /a/completed/path?withParams=ifPresent
sudo.Navigator.prototype.buildPath = function getPath() {
var args = Array.prototype.slice.call(arguments), query;
check if the last arg is a hash
if(typeof args[args.length - 1] === 'object') {
query = this.getQuery(args.pop());
}
return this.data.root + args.join('/') + (query || '');
};
Extend the already existing getUrl type functionality with the ability to append to that path as well as paramaterize a hash
params
{*} N number of path fragments
returns
{string} /a/completed/path?withParams=ifPresent
sudo.Navigator.prototype.buildRelativePath = function getRelativePath() {
var args = Array.prototype.slice.call(arguments);
args.unshift(this.data.fragment);
return this.buildPath.apply(this, args);
};
'Fragment' is defined as any URL information after the 'root' path
including the search
or hash
returns
{String} fragment
returns
{String} the normalized current fragment
sudo.Navigator.prototype.getFragment = function getFragment(fragment) {
var root = this.data.root;
if(!fragment) {
intentional use of coersion
if (this.isPushState) {
fragment = window.location.pathname;
root = root.replace(this.trailingStripper, '');
if(!fragment.indexOf(root)) fragment = fragment.substr(root.length);
} else {
fragment = this.getHash();
}
}
return decodeURIComponent(fragment.replace(this.leadingStripper, ''));
};
Check either the passed in fragment, or the full location.href
for a hash
value
param
{string} fragment
Optional fragment to check
returns
{string} the normalized current hash
sudo.Navigator.prototype.getHash = function getHash(fragment) {
fragment || (fragment = window.location.href);
var match = fragment.match(/#(.*)$/);
return match ? match[1] : '';
};
Take a hash and convert it to a search
query. Reuse
Zepto|jQuery param
method
param
{object} obj
returns
{string} the serialized query string
sudo.Navigator.prototype.getQuery = function getQuery(obj) {
return '?' + ($.param(obj));
};
Check either the passed in fragment, or the full location.href
for a search
value
param
{string} fragment
Optional fragment to check
returns
{String} the normalized current search
sudo.Navigator.prototype.getSearch = function getSearch(fragment) {
fragment || (fragment = window.location.href);
var match = fragment.match(/\?(.*)$/);
return match ? match[1] : '';
};
sudo.Navigator.prototype.getUrl = function getUrl() {
note that delegate(role) returns the deleagte
return this.data.root + this.data.fragment;
};
If the passed in 'fragment' is different than the currently stored one, push a new state entry / hash event and set the data where specified
param
{string} fragment
returns
{*} call to setData
sudo.Navigator.prototype.go = function go(fragment) {
if(!this.started) return false;
if(!this.urlChanged(fragment)) return;
TODO ever use replaceState?
if(this.isPushState) {
window.history.pushState({}, document.title, this.getUrl());
} else if(this.isHashChange) {
window.location.hash = '#' + this.data.fragment;
}
return this.setData();
};
Bound to either the popstate
or hashchange
events, if the
URL has indeed changed then parse the relevant data and set it -
triggering change observers
returns
{*} call to setData
or undefined
sudo.Navigator.prototype.handleChange = function handleChange() {
if(this.urlChanged()) {
return this.setData();
}
};
Parse and return a hash of the key value pairs contained in
the current query
returns
{object}
sudo.Navigator.prototype.parseQuery = function parseQuery() {
var obj = {}, seg = this.data.query,
i, s;
if(seg) {
seg = seg.split('&');
for(i = 0; i < seg.length; i++) {
if(!seg[i]) continue;
s = seg[i].split('=');
obj[s[0]] = s[1];
}
return obj;
}
};
Using the current fragment
(minus any search or hash data) as a key,
use parseQuery
as the value for the key, setting it into the specified
model (a stated Observable
or this.data
)
returns
{object} this
sudo.Navigator.prototype.setData = function setData() {
var frag = this.data.fragment,
data is set in a specified model or in self
observable = this.data.observable || this;
if(this.data.query) {
we want to set the key minus any search/hash
frag = frag.indexOf('?') !== -1 ? frag.split('?')[0] : frag.split('#')[0];
}
observable.set(frag, this.parseQuery());
return this;
};
Gather the necessary information about the current environment and bind to either (push|pop)state or hashchange. Also, if given an imcorrect URL for the current environment (hashchange vs pushState) normalize it and set accordingly (or don't).
returns
{object} this
sudo.Navigator.prototype.start = function start() {
var hasPushState, atRoot, tmp;
if(this.started) return;
hasPushState = window.history && window.history.pushState;
this.started = true;
setup the initial configuration
this.isHashChange = this.data.useHashChange && 'onhashchange' in window ||
(!hasPushState && 'onhashchange' in window);
this.isPushState = !this.isHashChange && !!hasPushState;
normalize the root to always contain a leading and trailing slash
this.data.root = ('/' + this.data.root + '/').replace(this.slashStripper, '/');
Get a snapshot of the current fragment
this.urlChanged();
monitor URL changes via popState or hashchange
if (this.isPushState) {
$(window).on('popstate', this.handleChange.bind(this));
} else if (this.isHashChange) {
$(window).on('hashchange', this.handleChange.bind(this));
} else return;
atRoot = window.location.pathname.replace(/[^\/]$/, '$&/') === this.data.root;
somehow a URL got here not in my 'format', unless explicitly told not too, correct this
if(!this.data.stay) {
if(this.isHashChange && !atRoot) {
window.location.replace(this.data.root + window.location.search + '#' +
this.data.fragment);
return early as browser will redirect
return true;
the converse of the above
} else if(this.isPushState && atRoot && window.location.hash) {
tmp = this.getHash().replace(this.leadingStripper, '');
window.history.replaceState({}, document.title, this.data.root +
tmp + window.location.search);
}
}
TODO provide option to go
from inital start
state?
return this;
};
Is a passed in fragment different from the one currently set at this.get('fragment')
?
If so set the fragment to the passed fragment passed in (as well as any 'query' data), else
simply return false
param
{String} fragment
returns
{bool}
sudo.Navigator.prototype.urlChanged = function urlChanged(fragment) {
var current = this.getFragment(fragment);
nothing has changed
if (current === this.data.fragment) return false;
this.data.fragment = current;
the fragment and the href need to checked here, optimized for the 'go' scenario
this.data.query = (this.getSearch(current) || this.getSearch()) ||
(this.getHash(current) || this.getHash());
return true;
};
Implementaion of the ES6 Harmony Observer pattern.
Extend a sudo.Model
class with this object if
data-mutation-observation is required
sudo.extensions.observable = {
_deliver_: function _deliver_(obj) {
var i, cb = this.callbacks;
for(i = 0; i < cb.length; i++) {
cb[i](obj);
}
},
Iterate through the changeRecords array(emptying it as you go), delivering them to the observers. You can override this method to change the standard delivery behavior.
returns
{Object} this
deliverChangeRecords: function deliverChangeRecords() {
var rec, cr = this.changeRecords;
FIFO
for(rec; cr.length && (rec = cr.shift());) {
this._deliver_(rec);
}
return this;
},
In a quasi-ES6 Object.observe pattern, calling observe on an observable
and
passing a callback will cause that callback to be called whenever any
property on the observable's data store is set, changed or deleted
via set, unset, setPath or unsetPath with an object containing:
{
type:
param
{Function} fn
The callback to be called with changeRecord(s)
returns
{Function} the Function passed in as an argument
observe: function observe(fn) {
this will fail if mixed-in and no callbacks
created so don't do that.
Per the spec, do not allow the same callback to be added
var d = this.callbacks;
if(d.indexOf(fn) === -1) d.push(fn);
return fn;
},
Allow an array of callbacks to be registered as changeRecord recipients
param
{Array} ary
returns
{Array} the Array passed in to observe
observes: function observes(ary) {
var i;
for(i = 0; i < ary.length; i++) {
this.observe(ary[i]);
}
return ary;
},
Overrides sudo.Base.set to check for observers
param
{String} key
. The name of the key
param
{*} value
param
{Bool} hold
Call deliver (falsy) or store the change notification
to be delivered upon a call to deliverChangeRecords (truthy)
returns
{Object|*} this
or calls deliverChangeRecords
set: function set(key, value, hold) {
var obj = {name: key, object: this.data};
did this key exist already
if(key in this.data) {
obj.type = 'updated';
then there is an oldValue
obj.oldValue = this.data[key];
} else obj.type = 'new';
now actually set the value
this.data[key] = value;
this.changeRecords.push(obj);
call the observers or not
if(hold) return this;
return this.deliverChangeRecords();
},
Overrides sudo.Base.setPath to check for observers.
Change records originating from a setPath
operation
send back the passed in path
as name
as well as the
top level object being observed (this observable's data).
this allows for easy filtering either manually or via a
change delegate
param
{String} path
param
{} value
param
{Bool} hold
Call deliver (falsy) or store the change notification
to be delivered upon a call to deliverChangeRecords (truthy)
returns
{Object|} this
or calls deliverChangeRecords
setPath: function setPath(path, value, hold) {
var curr = this.data, obj = {name: path, object: this.data},
p = path.split('.'), key;
for (key; p.length && (key = p.shift());) {
if(!p.length) {
reached the last refinement, pre-existing?
if (key in curr) {
obj.type = 'updated';
obj.oldValue = curr[key];
} else obj.type = 'new';
curr[key] = value;
} else if (curr[key]) {
curr = curr[key];
} else {
curr = curr[key] = {};
}
}
this.changeRecords.push(obj);
call all observers or not
if(hold) return this;
return this.deliverChangeRecords();
},
Overrides Base.sets to hold the call to deliver until all operations are done
returns
{Object|*} this
or calls deliverChangeRecords
sets: function sets(obj, hold) {
var i, k = Object.keys(obj);
for(i = 0; i < k.length; i++) {
k[i].indexOf('.') === -1 ? this.set(k[i], obj[k[i]], true) :
this.setPath(k[i], obj[k[i]], true);
}
if(hold) return this;
return this.deliverChangeRecords();
},
Remove a particular callback from this observable
param
{Function} the function passed in to observe
returns
{Object} this
unobserve: function unobserve(fn) {
var cb = this.callbacks, i = cb.indexOf(fn);
if(i !== -1) cb.splice(i, 1);
return this;
},
Allow an array of callbacks to be unregistered as changeRecord recipients
param
{Array} ary
returns
{Object} this
unobserves: function unobserves(ary) {
var i;
for(i = 0; i < ary.length; i++) {
this.unobserve(ary[i]);
}
return this;
},
Overrides sudo.Base.unset to check for observers
param
{String} key
. The name of the key
param
{Bool} hold
returns
{Object|*} this
or calls deliverChangeRecords
unset: function unset(key, hold) {
var obj = {name: key, object: this.data, type: 'deleted'},
val = !!this.data[key];
delete this.data[key];
call the observers if there was a val to delete
return this._unset_(obj, val, hold);
},
_unset_: function _unset_(o, v, h) {
if(v) {
this.changeRecords.push(o);
if(h) return this;
return this.deliverChangeRecords();
}
return this;
},
Overrides sudo.Base.unsetPath to check for observers
param
{String} path
param
{*} value
param
{bool} hold
returns
{Object|*} this
or calls deliverChangeRecords
unsetPath: function unsetPath(path, hold) {
var obj = {name: path, object: this.data, type: 'deleted'},
curr = this.data, p = path.split('.'),
key, val;
for (key; p.length && (key = p.shift());) {
if(!p.length) {
reached the last refinement
val = !!curr[key];
delete curr[key];
} else {
this can obviously fail, but can be prevented by checking
with getPath
first.
curr = curr[key];
}
}
return this._unset_(obj, val, hold);
},
Override of Base.unsets to hold the call to deliver until done
param
ary
param
hold
returns
{Object|*} this
or calls deliverChangeRecords
unsets: function unsets(ary, hold) {
var i;
for(i = 0; i < ary.length; i++) {
ary[i].indexOf('.') === -1 ? this.unset(ary[i], true) :
this.unsetPath(ary[i], true);
}
if(hold) return this;
return this.deliverChangeRecords();
}
};
Handles event binding/unbinding via an events array in the form:
events: [{
name: eventName
,
sel: an_optional_delegator
,
fn: function name
}, {...
This array will be searched for via this.get('events')
. There is a
single-event use case as well, pass a single object literal in the above form.
with the key event
:
event: {...same as above}
Details about the hashes in the array:
A. name -> DOM compatible event name
B. sel -> Optional DOM compatible selector used to delegate events
D. fn -> If a {String} bound to the named function on this object, if a
function assumed to be anonymous and called with no scope manipulation
sudo.extensions.listener = {
bindEvents: function bindEvents() {
var e;
if((e = this.model.data.event || this.model.data.events)) this._handleEvents_(e, 1);
return this;
},
Use the jQuery on
or 'off' method, optionally delegating to a selector if present
private
_handleEvents_: function _handleEvents_(e, which) {
var i;
if(Array.isArray(e)) {
for(i = 0; i < e.length; i++) {
this._handleEvent_(e[i], which);
}
} else {
this._handleEvent_(e, which);
}
},
helper for binding and unbinding an individual event
param
{Object} e. An event descriptor
param
{String} which. on
or off
private
_handleEvent_: function _handleEvent_(e, which) {
if(which) {
$(this.el).on(e.name, e.sel, typeof e.fn === 'string' ? this[e.fn].bind(this) : e.fn);
} else {
do not send the fn going to off otherwise the unbind will fail because of how we bind the string names, if this is ever an issue we can hash them and look it up, but I don't see that as necessary atm
$(this.el).off(e.name);
}
},
rebindEvents: function rebindEvents() {
return this.unbindEvents().bindEvents();
},
unbindEvents: function unbindEvents() {
var e;
if((e = this.model.data.event || this.model.data.events)) this._handleEvents_(e);
return this;
}
};
A mixin providing restful CRUD operations for a sudo.Model instance.
create : POST read : GET update : PUT or PATCH (configurable) destroy : DELETE
Before use be sure to set an ajax
property {object} with at least
a baseUrl: ...
key. The model's id (if present -- indicating a persisted model)
is appended to the baseUrl (baseUrl/id) by default. You can override this behavior
by simply setting a url: ...
in the ajax
options hash or pass in the same when
calling any of the methods (or override the model.url() method).
Place any other default options in the ajax
hash
that you would want sent to an ajax call. Again, you can also override those
defaults by passing in a hash of options to any method:
this.model.update({patch: true})
etc...
sudo.extensions.persistable = {
Save this model on the server. If a subset of this model's attributes have not been stated (ajax:{data:{...}}) send all of the model's data. Anticipate that the server response will send back the state of the model on the server and set it here (via a success callback).
param
{object} params
Hash of options for the XHR call
returns
{object} The XHR object
create: function create(params) {
return this._sendData_('POST', params);
},
Delete this model on the server
param
{object} params
Optional hash of options for the XHR
returns
{object} Xhr
destroy: function _delete(params) {
return this._sendData_('DELETE', params);
},
Abstracted logic for preparing the options object. This looks at
the set ajax
property, allowing any passed in params to override.
Sets defaults: text
responseType and an onload callback that simply sets()
the
parsed response returned from the server
returns
{object} A normalized params object for the XHR call
_normalizeParams_: function _normalizeParams_(verb, opts, params) {
var self = this;
opts || (opts = $.extend({}, this.data.ajax));
opts.url || (opts.url = this.url(opts.baseUrl));
opts.verb || (opts.verb = verb);
opts.responseType || (opts.responseType = 'text');
used in the sendData to determine a Content-Type header
opts.contentType || (opts.contentType = 'json');
the default success callback is to set the data returned from the server
or just the status as ajaxStatus
if no data was returned
opts.onload || (opts.onload = function() {
try to json parse it by default, pass in an 'onload' to override
if(this.responseText) self.sets(JSON.parse(this.responseText));
else self.sets({ajaxStatus: this.status, ajaxStatusText: this.statusText});
});
allow the passed in params to override any set in this model's ajax
options
return params ? $.extend(opts, params) : opts;
},
In the default state, that is to data is explicitly passed to them, save
type operations will pass this model's data hash here to be cloned and have
the items in the blacklist removed
param
{object} data
returns
{object} A clone of this models data hash minus the blacklisted keys
_prepareData_: function _prepareData_(data) {
var keys = Object.keys(data), len = keys.length, res = {}, i;
for(i = 0; i < len; i++) {
if(!(keys[i] in this.serverDataBlacklist)) res[keys[i]] = data[keys[i]];
}
return res;
},
Fetch this models state from the server and set it here. The
Model.sets()
method is used with the returned data (we are
asssuming the default json dataType). Pass in (via the params arg)
a success function to override this default.
Maps to the http GET method.
param
{object} params
. Optional info for the XHR call. If
present will override any set in this model's ajax
options object.
returns
{object} The XHR object
read: function post(params) {
var opts = this._normalizeParams_('GET', null, params),
xhr = sudo.getXhr(opts);
xhr.send();
return xhr;
},
Convenience method removing the need to know if a model is new (not yet persisted) or has been loaded/refreshed from the server.
param
{object} params
Hash of options for the XHR call
returns
{object} The XHR object
save: function save(params) {
return ('id' in this.data) ? this.update(params) : this.create(params);
},
The Create, Update and Patch methods all send data to the server, varying only in their HTTP method. Abstracted logic is here.
returns
{object} Xhr
_sendData_: function _sendData_(verb, params) {
var opts = this._normalizeParams_(verb, null, params),
xhr = sudo.getXhr(opts);
xhr.send(opts.data || JSON.stringify(this._prepareData_(this.data)));
return xhr;
},
Keys present in this hash will be removed from the object sent to the server on a save type operation if no data was passed explicitly to that method
serverDataBlacklist: {
ajax: true,
renderMethod: true,
renderTarget: true,
template: true
},
If this model has been persisted to/from the server (it has an id
attribute)
send the specified data (or all the model's data) to the server at url
via
the PUT
http verb or PATCH
if {patch: true} is in the ajax options (or the
passed in params)
NOTE: update does not check is this is a new model or not, do that yourself
or use the save()
method (that does check).
param
{object} params
Optional hash of options for the XHR
returns
{object|bool} the Xhr if called false if not
update: function update(params) {
return this._sendData_((this.data.ajax.patch || params && params.patch) ?
'PATCH' : 'PUT', params);
},
Takes the base url and appends this models id if present (narmalizing the trailong slash if needed). Override if you need to change the format of the calculated url.
param
{string} base
the baseUrl set in this models ajax options
url: function url(base) {
could possibly be 0...
if('id' in this.data) {
return base + (base.charAt(base.length - 1) === '/' ?
'' : '/') + encodeURIComponent(this.data.id);
} else return base;
}
};//##Filtered Delegate
sudo.delegates.Filtered = function(data) {
sudo.Model.call(this, data);
};
The filtered delegate
sudo.inherit(sudo.Model, sudo.delegates.Filtered);
Place an entry into this object's hash of filters
param
{string} key
param
{string} val
returns
{object} this
sudo.delegates.Filtered.prototype.addFilter = function addFilter(key, val) {
this.data.filters[key] = val;
return this;
};
Remove an entry from this object's hash of filters
param
{string} key
returns
{object} this
sudo.delegates.Filtered.prototype.removeFilter = function removeFilter(key) {
delete this.data.filters[key];
return this;
};
private
sudo.delegates.Filtered.prototype.role = 'filtered';
Delegates, if present, can override or extend the behavior
of objects. The change delegate is specifically designed to
filter change records from an Observable instance and only forward
the ones matching a given filters
criteria (key or path).
The forwarded messages will be sent to the specified method
on the delegates delegator
(bound to the delegator scope)
param
{Object} data
sudo.delegates.Change = function(data) {
this.construct(data);
};
Delegates inherit from the Filtered Delegate
sudo.delegates.Change.prototype = Object.create(sudo.delegates.Filtered.prototype);
Change records are delivered here and filtered, calling any matching methods specified in `this.get('filters').
returns
{Object} a call to the specified delegator method, passing
a hash containing:
type
of Changename
of the changed propertyoldValue
of the key if presentsudo.delegates.Change.prototype.filter = function filter(change) {
var filters = this.data.filters, name = change.name,
type = change.type, obj = {};
does my delegator care about this?
if(name in filters && filters.hasOwnProperty(name)) {
assemble the object to return to the method
obj.type = type;
obj.name = name;
obj.oldValue = change.oldValue;
delete operations will not have any value so no need to look
if(type !== 'deleted') {
obj.value = name.indexOf('.') === -1 ? change.object[change.name] :
sudo.getPath(name, change.object);
}
return this.delegator[filters[name]].call(this.delegator, obj);
}
};
private
sudo.delegates.Change.prototype.role = 'change';
Delegates, if present, can extend the behavior of objects, lessening the need for subclassing. The data delegate is specifically designed to filter through an object, looking for specified keys or paths and returning values for those if found
param
{Object} data
returns
{*} the value found at the specified key/path if found
sudo.delegates.Data = function(data) {
this.construct(data);
};
inherits from the Filtered Delegate
sudo.delegates.Data.prototype = Object.create(sudo.delegates.Filtered.prototype);
iterates over a given object literal and returns a value (if present) located at a given key or path
param
{Object} obj
sudo.delegates.Data.prototype.filter = function(obj) {
var filters = this.data.filters,
ary = Object.keys(filters), key, i, o, k;
for(i = 0; i < ary.length; i++) {
key = ary[i];
keys and paths need different handling
if(key.indexOf('.') === -1) {
if(key in obj) this.delegator[filters[key]].call(
this.delegator, obj[key]);
} else {
the chars after the last refinement are the key we need to check for
k = key.slice(key.lastIndexOf('.') + 1);
and the ones prior are the object
o = sudo.getPath(key.slice(0, key.lastIndexOf('.')), obj);
if(o && k in o) this.delegator[filters[key]].call(
this.delegator, o[k]);
}
}
};
private
sudo.delegates.Data.prototype.role = 'data';
sudo.version = "0.9.8";
window.sudo = sudo;
if(typeof window._ === "undefined") window._ = sudo;
}).call(this, this);


Example 05 - Simple treatment of image sequence
This example demonstrates the simplest possible treatment of a sequence of PIV images using PIVsuite. These images shows a turbulent flow in a channel below a set of injections nozzles. Images were recorded with a high-speed camera and laser for fired at constant frequency.
Contents
Before running PIVsuite
Initialize the variable pivPar, in which parameters of PIV algorithm (such as interrogation area size) are defined. Initialize also variable pivData, to which results will be stored.
clear; pivPar = []; % variable for settings pivData = []; % variable for storing results
Define image pairs to be treated. It is assumed that the images are stored in a folder: we will get a list of filenames of such images
% Set folder with treated images imagePath = ['..',filesep,'Data',filesep,'Test Tububu']; % get list of images in the folder aux = dir([imagePath, filesep, '*.bmp']); for kk = 1:numel(aux) fileList{kk} = [imagePath, filesep, aux(kk).name]; %#ok<SAGROW> end fileList = sort(fileList);
The images were acquired at constant frequency. The second image in each pair can be used as the first image in the next pair, and the image pair useful for PIV treatment has sequence 1-2, 2-3, 3-4, 4-5 etc. Nevertheless, we will treat image pairs consisting of images 1-2, 5-6, 9-10, ..., 37-38 in this example for reasonable treatment time.
pivPar.seqPairInterval = 4; % set the interval between image pairs pivPar.seqSeqDiff = 1; % the second image in each pair is one frame after the first image % use this command to create a list of files, corresponding to the first and second images in each pair [im1,im2] = pivCreateImageSequence(fileList,pivPar);
Now, we will set other common parameters:
pivPar.iaSizeX = [64 32 32 32 32]; % interrogation area size for five passes pivPar.iaStepX = [32 16 12 12 12]; % grid spacing for five passes pivPar.qvPair = {... % define plot shown between iterations 'Umag','clipHi',3,... % plot displacement magnitude, clip to 3 px 'quiver','selectStat','valid','linespec','-k',... % show valid vectors in black 'quiver','selectStat','replaced','linespec','-w'}; % show replaced vectors in white
Set all other parameters to defaults. Note that defaults are different for sequence than for image pairs
[pivPar, pivData] = pivParams(pivData,pivPar,'defaultsSeq');
figure(1);
Run the analysis
For PIV analysis of an image pair, execute the following command (treatment migth take from seconds to few minutes):
[pivData] = pivAnalyzeImageSequence(im1,im2,pivData,pivPar);
Treating pair 1 of 10 (???)... Accomplished in 9.88 s, last pass 2.41 s, Subpix failure 0.30 %, Median-test rejection 2.60 % Treating pair 2 of 10 (???)... Accomplished in 9.78 s, last pass 2.36 s, Subpix failure 0.16 %, Median-test rejection 2.90 % Treating pair 3 of 10 (???)... Accomplished in 9.84 s, last pass 2.40 s, Subpix failure 0.38 %, Median-test rejection 3.11 % Treating pair 4 of 10 (???)... Accomplished in 9.78 s, last pass 2.36 s, Subpix failure 0.27 %, Median-test rejection 3.25 % Treating pair 5 of 10 (???)... Accomplished in 10.69 s, last pass 2.36 s, Subpix failure 0.48 %, Median-test rejection 3.25 % Treating pair 6 of 10 (???)... Accomplished in 9.83 s, last pass 2.38 s, Subpix failure 0.46 %, Median-test rejection 2.42 % Treating pair 7 of 10 (???)... Accomplished in 9.84 s, last pass 2.36 s, Subpix failure 0.30 %, Median-test rejection 2.90 % Treating pair 8 of 10 (???)... Accomplished in 9.80 s, last pass 2.36 s, Subpix failure 0.35 %, Median-test rejection 2.74 % Treating pair 9 of 10 (???)... Accomplished in 12.42 s, last pass 2.36 s, Subpix failure 0.24 %, Median-test rejection 2.68 % Treating pair 10 of 10 (???)... Accomplished in 9.81 s, last pass 2.36 s, Subpix failure 0.21 %, Median-test rejection 2.63 % Replacing spurious velocity vectors... Finished in 0.01 s.
Visualize the results
Show a movie of velocity field with subtracted mean velocity (velocity field "as seen by the mean flow"):
% compute mean velocity from the bottom-most part of velocity field Vmean = pivData.V(ceil(2/3*size(pivData.V,1)):end,:,:); % velocity in bottom-most third of image Vmean = mean(reshape(Vmean,numel(Vmean),1)); % mean velocity figure(2); for kr = 1:5 % repeat movie three times for kt = 1:pivData.Nt pivQuiver(pivData,'TimeSlice',kt,... % choose data and time to show 'V','subtractV',Vmean,... % vertical velocity, subtract Vmean from it 'clipLo',-1,'clipHi',2.5,... % shown range 'quiver','subtractV',Vmean,... % velocity vectors, subtract mean velocity 'selectStat','valid'); % show only valid velocity vectors drawnow; pause(0.1); end end


Give stars to artists, albums and genres you like
Suggestions are based on the ratings you've given
Enjoy discovering new music suggested by Headbanger


Simple Diff Calculator
With offline support using Local Storage and Service Workers
from
+
%
=
from
to
=
0%


| 020:134 Khan | : |
And if We had destroyed them with a torment before this (i.e. Messenger Muhammad SAW and the Qur'an), they would surely have said: "Our Lord! If only You had sent us a Messenger, we should certainly have followed Your Ayat (proofs, evidences, verses, lessons, signs, revelations, etc.), before we were humiliated and disgraced." |
| 020:134 Maulana | : |
And if We had destroyed them with chastisement before it, they would have said: Our Lord, why didst Thou not send to us a messenger, so that we might have followed Thy messages before we met disgrace and shame? |
| 020:134 Pickthal | : |
And if we had destroyed them with some punishment before it, they would assuredly have said: Our Lord! If only Thou hadst sent unto us a messenger, so that we might have followed Thy revelations before we were (thus) humbled and disgraced! |
| 020:134 Rashad | : |
Had we annihilated them before this, they would have said, "Our Lord, had You sent a messenger to us, we would have followed Your revelations, and would have avoided this shame and humiliation." |
| 020:134 Sarwar | : |
Had We destroyed them with a torment before the coming of Muhammad they would have said, "Lord, would that you had sent us a Messengers so that we could have followed Your revelations before being humiliated and disgraced." |
| 020:134 Shakir | : |
And had We destroyed them with chastisement before this, they would certainly have said: O our Lord! why didst Thou not send to us a messenger, for then we should have followed Thy communications before that we met disgrace and shame. |
| 020:134 Sherali | : |
And if WE had destroyed them with a punishment before the coming of this Messenger, they would have surely said, 'Our Lord, wherefore didst Thou not send to us a Messenger that we might have followed Thy commandments before we were humbled and disgraced?' |
| 020:134 Yusufali | : |
And if We had inflicted on them a penalty before this, they would have said: "Our Lord! If only Thou hadst sent us a messenger, we should certainly have followed Thy Signs before we were humbled and put to shame." |
Concepts/Themes Covered: أركان الإسلام > التوحيد > الكافرون > تعنت الكفار واستعجالهم بالعذاب Pillars of Islam> Islamic> The Disbelievers> The Disbelievers' Stubbornness and their Acceleration to Torture أركان الإسلام > التوحيد > الكافرون > صفات الكفار Pillars of Islam> Islamic> The Disbelievers> The Characteristics of the Disbelievers
This tool uses eight English parallel translations for the Holy Quran imported from Mr. Clay Smith. You can also visit Qurany Concepts for browsing the Quran themes or topics. If you want to search the Holy Quran for keywords, please visit Qurany Keywords.


ShowAxes
Show x,y,z axes
One way to use the axes more efffectively is to use the "pick" command to display the bounding box of the body as well.


Admin Account
Fast-Food-Fast
This is a food delivery service application for a restaurant.
User Register
Login here
Register


About
Rap Analyzer visualizes the way that a rapper rhymes in a given song by color coding groups of words that rhyme. Simply search a song on the homepage or log in with Spotify to analyze your favorite Hip-Hop playlist and recently listened songs. Your searches query our custom database of analyzed lyrics of over 100 artists. Can't find your favorite song or artist? Check back soon! We will adding the ability to update our database on the fly in a coming update!
Lyrics are captured one verse or chorus at a time, allowing RPW to consider both internal and end rhymes while eliminating false positives occurring throughout a verse no matter their position within a given line.
Test it out with these notable examples listed on our homepage, or read into the inner-workings of RPW Below!
Approach
Obtaining Lyrics
We used the LyricsGenius python library to collect lyrics for over 100 artists. This library runs on a combination of the official Genius API and web-scraping tools. Due to Intellectual Property law and licensing, we cannot provide this database for other developers looking to contribute to this project, however, we have provided the scripts which we used to build our database.  For Example: through, rough, and trough share the same '-ough' ending despite being pronounced differently (/THro͞o/, /rəf/, /trôf/). This presents an interesting problem as rhymes cannot be detected via spelling alone. Moreover, rappers frequently coerce pronunciations to force rhymes where they would not normally occur.
To account for these problems, we break words down into a list of phonemes (phonetic syllables which describe how a word is pronounced) using the Python Natural Language Toolkit and the CMU Pronouncing Dictionary (CMUDict) which contains 39 phonemes and three levels of syllabic stress. For example, Cheese
-> CH IY Z
. We compare the ending phonemes of words to look for rhymes and address pronounciation coersion in two ways:
-
Multiple Word Pronunciations
CMUDict contains multiple pronunciations for many words. For Example, we catch a rhyme between
"Business"
and"Witness"
by comparing two pronunciations of"Business"
(B IH1 Z N AH0 S
andB IH1 Z N IH0 S
) with the single pronunciations of"Witness"
(W IH1 T N AH0 S
) -
Rebuilding Truncated Suffixes
Many rappers use a truncated suffix, ending present participle
-ing
words within'
Dodgin' bullets, reapin' what you sow And stackin' up the footage, livin' on the go
Dodgin
andReapin
are not official words listed in the CMUDict, so we rebuild these suffixes toDodging
andReaping
to catch rhymes between words of this form and words with a completeing
endingNote: For words that are not in the CMUDict, direct string equality is used.
Our algorithm considers one verse or chorus at a time to mitigate false positives derived from rhymes detected across sections. In a given section, our algorithm operates as follows:
rhymeNumberList = [-1] * Length of section
rhymeNumber = 0
for A in section:
for B in section[index of A onward]:
if A rhymes with B:
Mark A with rhymeNumber
Mark All instances of B with RhymeNumber
rhymeNumbers[IndexOf(A)] = rhymeNumber
RhymeNumber++
A section's rhyme information is stored as a list of rhyme numbers: word A and word B rhyme if `RhymeList[IndexOf(A)] == RhymeList[IndexOf(B)]`, We use rhyme numbers to determine which color to ascribe to a set of words on the Rap Analyzer Web service.
Spotify Integration
In addition to viewing one song at a time by searching on the RPW Homepage, users can log in with their Spotify account to grant RPW access to their playlists and recently listened songs. Users can then select a playlist or number of recently listened songs they wish to analyze. Highlighted Lyrics are presented to the user with a dropdown menu to switch between songs.
Highlighting Lyrics:
A word's Rhyme Number is used to determine the color of its highlight: Words with the same rhyme number rhyme with each other and are given the same highlight color. A word's rhyme number is mapped to an HSL hue value from 0 to 360. To obtain a set of diverse highlighting colors. Rhyme Numbers and are mapped to hue values as follows:
Rhyme Number Hue
[0,17] [n * 10 for n in range(0,360) if n % 2 == 0] (20,40,60,...360)
[18,36] [n * 10 for n in range(0,360) if n % 2 != 0] (10,30,50,...350)
The brightness value of a color alternates between a light and dark highlight to further differentiate sets of rhymes
A rhyme number of -1 corresponds to no highlighting.
Hosting Lyrics and rhyming information
Web-scraping lyrics using LyricsGenius proved too inefficient to rely on for realtime analysis of more than one song at a time. We opted to build a MongDB database of over 100 artists (most of which had 100-300 songs), their lyrics, and their rhyme information in the following format:
{
Database:
{
'artist1' : [
{'song1': "songName" , 'lyrics' : "lyrics go here", 'rhyme' [[List of Rhyme Numbers]]}
{'song2': "songName" , 'lyrics' : "lyrics go here", 'rhyme' [[List of Rhyme Numbers]]}
]
}
{
'artist2' : [
{'song1': "songName" , 'lyrics' : "lyrics go here", 'rhyme' [[List of Rhyme Numbers]]}
{'song2': "songName" , 'lyrics' : "lyrics go here", 'rhyme' [[List of Rhyme Numbers]]}
]
}
}
Artist and song names were made lowercase and stripped of any special characters. ('.' replaced with '' and '$' replaced with 's' to conform to MongoDB restrictions) MongoDB's Text indexing to allows users to search our database in a case-insensitive manner.
Next Steps
-
Using Rhyme Information to generate Statistics:
We intend to calculate statistics for artists based on rhyming such as their average amount of unique rhymes per song. This information will be merged with the present Spotify page to allow a user to compare artists on their favorites list -
Improving Rhyme Detection
There are many ways to improve our algorithm, including ignoring tense and plural word endings as rappers often coerce rhymes between present and past tense, or single and plural words. Furthermore, we could implement an algorithm that searches for common strings of vowels in words to detect multi-word rhyme schemes. Eventually, we want to apply Machine Learning models to rhyme detection to allow for the coverage of areas where our algorithm falls short.


@(employee : Employee, titles : List[Title], hobbies : List[Hobby]) @doctype.render
Editing @employee.getFullName


BDP — Basic data product base.¶
This module defines the Basic Data Product (BDP) base class.
-
class
admit.bdp.BDP.
BDP
(xmlFile=None, **keyval)[source]¶ Basic Data Product base.
Basic Data Products (BDPs) are data containers used to transport information within ADMIT, as well as deliver it to users in a persistent, well-defined format.
Parameters: xmlFile : str, optional
XML file associated with BDP (for persistence); defaults to
None
.keyval : dict
Dictionary of keyword value pairs.
Attributes
gous (TBD) TBD mous (TBD) TBD sous (TBD) TBD (the official name is sous) project (TBD) TBD xmlFile (str) XML file associated with BDP (for persistence). _baseDir (str) ADMIT project directory (None if unknown). _date (TBD) Date of last edit. _taskid (int) Originating ADMIT task ID number. _type (admit.util.bdp_types) Concrete BDP type. _updated (bool) Whether BDP has been modified since latest XML output. Methods
baseDir
([path])Get/set project base directory. delete
([delfiles])Method to delete the BDP. get
(key)Access an attribute. getdir
()Method to get the subdirectory(s) of the current BDP relative to the ADMIT working directory. getfiles
()Return the filename(s) associated with the basic data in a BDP. haskey
(key)Query if a key exists for an BDP. isequal
(bdp)Tests for equality with another BDP. report
()Report BDP properties in human readable format. setkey
([name, key])Sets keyword value(s). show
()Show the xmlFile name. update
(new_state)Updates BDP state. write
([xmlFile])Writes the BDP to an XML file. -
baseDir
(path=None)[source]¶ Get/set project base directory.
Parameters: path : str, optional
New project base directory (ignored if None).
Returns: Updated project base directory.
Notes
Unless empty, the base directory is guaranteed to end in os.sep.
-
delete
(delfiles=True)[source]¶ Method to delete the BDP. This method will search through all class variables and delete any images since they contain external files, and then deletes the BDP’s XML file.
Parameters: basedir : str, optional
XML file directory; defaults to current directory.
delfiles : bool, optional
Whether or not to delete the actual files on disk; defaults to True.
Notes
It is recommended that any BDP that stores images inside of lists, dictionaries, tuples, etc. override this method with a customized version.
-
get
(key)[source]¶ Access an attribute.
Parameters: key : str
Keyword name.
Returns: varies
Attribute value if keyword is present, else
None
.
-
getdir
()[source]¶ Method to get the subdirectory(s) of the current BDP relative to the ADMIT working directory.
Parameters: None Returns: String containing the current BDPs subdirectory
-
getfiles
()[source]¶ Return the filename(s) associated with the basic data in a BDP.
Parameters: None Returns: List of files Notes
Todo
Really should look for attribute .filename, but normally derived classes should implement these; see e.g. File_AT.
-
haskey
(key)[source]¶ Query if a key exists for an BDP.
Parameters: key : str
Keyword name.
Returns: True if keyword is present, else False.
-
isequal
(bdp)[source]¶ Tests for equality with another BDP.
Parameters: bdp : BDP
The other BDP.
Returns: True if the BDP types and contents match, else False.
-
setkey
(name='', key={})[source]¶ Sets keyword value(s).
Two styles are possible:
- name = {key:val} e.g. setkey({“a”:1})
- name = “key”, key = val e.g. setkey(“a”, 1)
Parameters: name : dict or str, optional
Keyword/values pairs, or single keyword name; defaults to empty string.
key : str, optional
Keyword value; defaults to empty dictionary.
init : bool, optional
Whether keyword is being set for the first time.
-
show
()[source]¶ Show the xmlFile name.
Parameters: None Returns: the xml file name Notes
Todo
Extend functionality to show more.
-
update
(new_state)[source]¶ Updates BDP state.
Parameters: new_state : varies
New BDP state.
Returns: None
-
write
(xmlFile=None)[source]¶ Writes the BDP to an XML file.
Parameters: xmlFile : str, optional
Output XML file name; defaults to eponymous internal attribute.
Notes
Do not edit unless you know what you are doing as all BDP’s rely on this method to work properly. Normally the xmlFile here should be the full path.
-


I was part of a 2005 WVU student team that designed, built, launched, tracked, and recovered small electronics payloads, using helium-filled weather balloons that was used to send their payloads into and beyond the stratosphere. Global positioning (GPS) tracking was used to track the satellite's travel path and to ultimately find and recover the satellite upon return to earth's surface. Altitude was also measured using the GPS.


|
entity - entity handle
vector_x# - vector x vector_y# - vector y vector_z# - vector z axis - axis of entity that will be aligned to vector 1: x-axis 2: y-axis 3: z-axis rate# (optional) - rate at which entity is aligned from current orientation to vector orientation. Should be in the range 0 to 1, 0 for smooth transition and 1 for 'snap' transition. Defaults to 1. |
| Aligns an entity axis to a vector. |


{{ define "sources"}}
Source: Global Ministry of foreign Affairs - Global Immigration Department - Global Tourism Boards
Source: Mainstream media news outlet i.e. CNN, BBC and others and Media Migration Policy.
Source: CDC Yellow Fever and CDC Travel Alerts
Source:


I am a frontend/fullstack developer. I am currently based out of Atlanta, GA.
Here are a few links about me.
Here are a few of my recent projects.
Send me a message.


Vanessa Stevenson
Food enthusiast, photography fan. Add a pinch of raw foodism and that's
pretty much who I am.
SHARE RECIPE
THE BEST FOOD BLOG ON THE WEB.
POSTED ON 13 DEC 2013 / DESSERTS
For the fig-swirl: Melt butter over medium heat in a saucepan. Add brown sugar and stir to dissolve. Halve all of the figs and toss in the saucepan with water and lemon juice. Cook over medium heat, stirring frequently, until you have a chunky-jammy mixture. Add salt with one or two stirs, set aside and let cool completely.
Ice cream: In a small pot over medium heat, combine milk, and granulated sugar until sugar is completely dissolved and the milk is just barely lukewarm. Whisk in the egg yolks. Set mixture in the fridge and wait until the fig mixture is cooled.
Using an ice cream machine, pour liquids into the frozen basin and process according to manufacturer instructions, i.e., let spin and thicken for 20 minutes before adding mascarpone, fig jam mixture, and the nuts. Continue to process for +/-10 minutes. Pour semi-frozen mixture into a pyrex dish or glass tupperware. Freeze for at least two hours before serving.
Food enthusiast, photography fan. Add a pinch of raw foodism and that's
pretty much who I am.
SHARE RECIPE


Flora1
Flora2boceto
Boceto hoff1
Boceto hoff2
Whats app image 2021 03 22 at 1
Whats app image 2021 03 22 at 12
Whats app image 2021 03 22 at 2
Sila1
Untitled


The Soviet invasion of Afghanistan
By: Ray, Connor, And William
Facts
- Soviets kill some 1-Million citizens
- Brutal 10 years
- U.S. aids Mujahdia fighters
- U.S. partners with pakastaie intelligence
- By early 80's Mujahdia were gaining control and fighting soviets
- This battle was just a small part in the cold war
- by 1982 some 2.8 million Afghans had sought asylum in Pakistan, and another 1.5 million had fled to Iran.
Who
- Thousands of Soviets
- Majahedin are afghan guerilla fighters(30)
- Between Soviets and Mujahdia backed by many countries(31)
After The War
- After the war the Taliban government took control of Afghanistan(32)
- Civil war continued afterwords


Build
public struct Build: Codable
Included when the resource is the main response of a request
-
Value uniquely identifying the build
Declaration
Swift
public let id: Int
-
Incremental number for a repository’s builds
Declaration
Swift
public let number: String
-
Current state of the build
Declaration
Swift
public let state: String
-
Wall clock time in seconds
Declaration
Swift
public let duration: Int?
-
Event that triggered the build
Declaration
Swift
public let eventType: String
-
State of the previous build (useful to see if state changed)
Declaration
Swift
public let previousState: String?
-
Title of the build’s pull request
Declaration
Swift
public let pullRequestTitle: String?
-
Number of the build’s pull request
Declaration
Swift
public let pullRequestNumber: Int?
-
When the build started
Declaration
Swift
public let startedAt: Date?
-
When the build finished
Declaration
Swift
public let finishedAt: Date?
-
GitHub user or organization the build belongs to.
Declaration
Swift
public let repository: Embed<MinimalRepository>
-
The branch the build is associated with
Declaration
Swift
public let branch: Embed<MinimalBranch>
-
The commit the build is associated with
Declaration
Swift
public let commit: Embed<MinimalCommit>
-
List of jobs that are part of the build’s matrix
Declaration
Swift
public let jobs: [Embed<MinimalJob>]?
-
The build’s updated_at
Note
This should be a date, but currently the built in iso8601 does not handle this formatDeclaration
Swift
public let updatedAt: String
-
Undocumented
Declaration
Swift
public let createdBy: Embed<MinimalUser>


| Package | Description |
|---|---|
| us.ihmc.euclid.referenceFrame | |
| us.ihmc.euclid.referenceFrame.interfaces | |
| us.ihmc.euclid.referenceFrame.tools |
| Modifier and Type | Method | Description |
|---|---|---|
boolean |
FramePoint2D.epsilonEquals(FramePoint2D other,
double epsilon) |
Tests on a per component basis if this point is equal to the given
other to an
epsilon . |
boolean |
FramePoint2D.geometricallyEquals(FramePoint2D other,
double epsilon) |
Tests if
this and other represent the same point 2D to an epsilon . |
void |
FramePoint2D.set(FramePoint2D other) |
Sets this frame point to
other . |
| Modifier and Type | Method | Description |
|---|---|---|
default FramePoint2D |
FrameLineSegment2DReadOnly.intersectionWith(FrameLine2DReadOnly line) |
Calculates the coordinates of the intersection between this line segment and the given line
and returns the result.
|
default FramePoint2D |
FrameLineSegment2DReadOnly.intersectionWith(FrameLineSegment2DReadOnly other) |
Computes the intersection between this line segment and the given line segment and returns the
result.
|
default FramePoint2D |
FrameLineSegment2DReadOnly.orthogonalProjectionCopy(FramePoint2DReadOnly pointToProject) |
Computes the orthogonal projection of a 2D point on this 2D line segment.
|
| Modifier and Type | Method | Description |
|---|---|---|
static FramePoint2D |
EuclidFrameTools.averagePoint2Ds(java.util.Collection<? extends FramePoint2DReadOnly> points) |
Computes the average 2D point from a given collection of 2D points.
|
static FramePoint2D |
EuclidFrameRandomTools.generateRandomFramePoint2D(java.util.Random random,
ReferenceFrame referenceFrame) |
Deprecated.
|
static FramePoint2D |
EuclidFrameRandomTools.generateRandomFramePoint2D(java.util.Random random,
ReferenceFrame referenceFrame,
double minMax) |
Deprecated.
|
static FramePoint2D |
EuclidFrameRandomTools.generateRandomFramePoint2D(java.util.Random random,
ReferenceFrame referenceFrame,
double min,
double max) |
Deprecated.
|
static FramePoint2D |
EuclidFrameRandomTools.generateRandomFramePoint2D(java.util.Random random,
ReferenceFrame referenceFrame,
double minX,
double maxX,
double minY,
double maxY) |
Deprecated.
|
static FramePoint2D |
EuclidFrameTools.intersectionBetweenLine2DAndLineSegment2D(FramePoint2DReadOnly pointOnLine,
FrameVector2DReadOnly lineDirection,
FramePoint2DReadOnly lineSegmentStart,
FramePoint2DReadOnly lineSegmentEnd) |
Computes the intersection between an infinitely long 2D line (defined by a 2D point and a 2D
direction) and a 2D line segment (defined by its two 2D endpoints).
|
static FramePoint2D |
EuclidFrameTools.intersectionBetweenRay2DAndLineSegment2D(FramePoint2DReadOnly rayOrigin,
FrameVector2DReadOnly rayDirection,
FramePoint2DReadOnly lineSegmentStart,
FramePoint2DReadOnly lineSegmentEnd) |
Computes the intersection between a 2D and a 2D line segment.
|
static FramePoint2D |
EuclidFrameTools.intersectionBetweenTwoLine2Ds(FramePoint2DReadOnly firstPointOnLine1,
FramePoint2DReadOnly secondPointOnLine1,
FramePoint2DReadOnly firstPointOnLine2,
FramePoint2DReadOnly secondPointOnLine2) |
Computes the intersection between two infinitely long 2D lines each defined by two 2D points.
|
static FramePoint2D |
EuclidFrameTools.intersectionBetweenTwoLine2Ds(FramePoint2DReadOnly pointOnLine1,
FrameVector2DReadOnly lineDirection1,
FramePoint2DReadOnly pointOnLine2,
FrameVector2DReadOnly lineDirection2) |
Computes the intersection between two infinitely long 2D lines each defined by a 2D point and a
2D direction.
|
static FramePoint2D |
EuclidFrameTools.intersectionBetweenTwoLineSegment2Ds(FramePoint2DReadOnly lineSegmentStart1,
FramePoint2DReadOnly lineSegmentEnd1,
FramePoint2DReadOnly lineSegmentStart2,
FramePoint2DReadOnly lineSegmentEnd2) |
Computes the intersection between two 2D line segments each defined by their two 2D endpoints.
|
static FramePoint2D |
EuclidFrameRandomTools.nextFramePoint2D(java.util.Random random,
ReferenceFrame referenceFrame) |
Generates a random frame point.
|
static FramePoint2D |
EuclidFrameRandomTools.nextFramePoint2D(java.util.Random random,
ReferenceFrame referenceFrame,
double minMax) |
Generates a random frame point.
|
static FramePoint2D |
EuclidFrameRandomTools.nextFramePoint2D(java.util.Random random,
ReferenceFrame referenceFrame,
double min,
double max) |
Generates a random frame point.
|
static FramePoint2D |
EuclidFrameRandomTools.nextFramePoint2D(java.util.Random random,
ReferenceFrame referenceFrame,
double minX,
double maxX,
double minY,
double maxY) |
Generates a random frame point.
|
static FramePoint2D |
EuclidFrameTools.orthogonalProjectionOnLine2D(FramePoint2DReadOnly pointToProject,
FramePoint2DReadOnly firstPointOnLine,
FramePoint2DReadOnly secondPointOnLine) |
Computes the orthogonal projection of a 2D point on an infinitely long 2D line defined by a 2D
line segment.
|
static FramePoint2D |
EuclidFrameTools.orthogonalProjectionOnLine2D(FramePoint2DReadOnly pointToProject,
FramePoint2DReadOnly pointOnLine,
FrameVector2DReadOnly lineDirection) |
Computes the orthogonal projection of a 2D point on an infinitely long 2D line defined by a 2D
point and a 2D direction.
|
static FramePoint2D |
EuclidFrameTools.orthogonalProjectionOnLineSegment2D(FramePoint2DReadOnly pointToProject,
FramePoint2DReadOnly lineSegmentStart,
FramePoint2DReadOnly lineSegmentEnd) |
Computes the orthogonal projection of a 2D point on a given 2D line segment defined by its two 2D
endpoints.
|
static FramePoint2D |
EuclidFrameTools.triangleBisector2D(FramePoint2DReadOnly A,
FramePoint2DReadOnly B,
FramePoint2DReadOnly C) |
Given a triangle defined by three points (A,B,C), this methods the point X ∈ AC such that the
line (B, X) is the angle bisector of B.
|


This is a Triangle Tracker application used by user
to know whether a triangle is isosceles, equilateral, scalene or NOT a triangle at all.
Enter First number:
Enter Second number:
Enter thrid number:


BMI
Pulse
Height (cm)
Weight (kg)
Result
Run
Age
Birth date
Activity
Min
Max
Max (100%)
Red zone (90-95%)
Endurance (80-90%)
Aerobic (70-80%)
Fat burn (60-70%)
Warm-up (50-60%)
Rest (35-50%)


External command runcher.
Input cmd_params into Kernel#spawn.
Write command’s stdout and stderr to tmp file.
* If Platform is "mswin" or "mingw" , then temp directory is ENV["TEMP"] * If Platform is "linux" or "cygwin" , then temp directory is "/tmp/"
Return hash object including stdout, stderr, and exit status.
require 'rbatch' cmd = RBatch::Cmd("ls") r = cmd.run p r.stdout => "fileA\nfileB\n"
cmd = RBatch::Cmd("ls", {:verbose => true}) r = cmd.run
require 'rbatch' r = RBatch::cmd("ls") p r.stdout => "fileA\nfileB\n"
Cmd instance
cmd_str = Command string. Such ad “ls -l” opt = Option hash object. Hash keys is follows.
:raise (Boolean) = If command exit status is not 0, raise exception. Default is false.
:timeout (Integer) = If command timeout , raise exception. Default is 0 sec ( 0 means disable) .
# File lib/rbatch/cmd.rb, line 46 46: def initialize(cmd_str,opt = nil) 47: raise(CmdException,"Command string is nil") if cmd_str.nil? 48: @cmd_str = cmd_str 49: # parse option 50: @opt = @@def_opt.clone 51: @@def_opt.each_key do |key| 52: if opt != nil && opt[key] != nil 53: # use argument 54: @opt[key] = opt[key] 55: elsif RBatch.common_config != nil && RBatch.common_config["cmd_" + key.to_s] != nil 56: # use config 57: @opt[key] = RBatch.common_config["cmd_" + key.to_s] 58: else 59: # use default 60: end 61: end 62: end
Run command
instance of RBatch::CmdResult
# File lib/rbatch/cmd.rb, line 69 69: def run() 70: stdout_file = Tempfile::new("rbatch_tmpout",RBatch::tmp_dir) 71: stderr_file = Tempfile::new("rbatch_tmperr",RBatch::tmp_dir) 72: pid = spawn(@cmd_str,:out => [stdout_file,"w"],:err => [stderr_file,"w"]) 73: if @opt[:timeout] != 0 74: timeout(@opt[:timeout]) do 75: begin 76: status = Process.waitpid2(pid)[1] >> 8 77: rescue Timeout::Error => e 78: raise(CmdException,"Command timeout (over " + @opt[:timeout] + " sec)" ) 79: end 80: end 81: else 82: status = Process.waitpid2(pid)[1] >> 8 83: end 84: result = RBatch::CmdResult.new(stdout_file,stderr_file,status,@cmd_str) 85: if @opt[:raise] && status != 0 86: raise(CmdException,"Command exit status is not 0. result: " + result.to_s) 87: end 88: return result 89: end
Disabled; run with --debug to generate this.
Generated with the Darkfish Rdoc Generator 1.1.6.


| JIRA | Summary | Priority | Component | Reporter | Contributor |
|---|
| JIRA | Summary | Priority | Component | Reporter | Contributor |
|---|---|---|---|---|---|
| KAFKA-3044 | Consumer.poll doesnot return messages when poll interval is less | Major | clients | Praveen Devarao | Jason Gustafson |
| JIRA | Summary | Priority | Component | Reporter | Contributor |
|---|
| JIRA | Summary | Priority | Component | Reporter | Contributor |
|---|---|---|---|---|---|
| KAFKA-3105 | Use Utils.atomicMoveWithFallback instead of File.rename |
Major | . | Ismael Juma | Ismael Juma |
| KAFKA-3084 | Topic existence checks in topic commands (create, alter, delete) | Major | . | Grant Henke | Grant Henke |
| KAFKA-3077 | Enable KafkaLog4jAppender to work with SASL enabled brokers. | Major | clients | Ashish K Singh | Ashish K Singh |
| KAFKA-3058 | remove the usage of deprecated config properties | Major | core | Jun Rao | Konrad Kalita |
| KAFKA-3043 | Replace request.required.acks with acks in docs | Major | website | Sasaki Toru | |
| KAFKA-3024 | Remove old patch review tools | Major | . | Grant Henke | Grant Henke |
| KAFKA-3019 | Add an exceptionName method to Errors | Major | . | Grant Henke | Grant Henke |
| KAFKA-3002 | Make available to specify hostname with Uppercase at broker list | Minor | clients | Sasaki Toru | |
| KAFKA-2992 | Trace log statements in the replica fetcher inner loop create large amounts of garbage | Minor | core | Cory Kolbeck | |
| KAFKA-2964 | Split Security Rolling Upgrade Test By Client and Broker Protocols | Minor | . | Ben Stopford | Ben Stopford |
| KAFKA-2958 | Remove duplicate API key mapping functionality | Major | . | Grant Henke | Grant Henke |
| KAFKA-2957 | Fix typos in Kafka documentation | Trivial | . | Vahid Hashemian | Vahid Hashemian |
| KAFKA-2929 | Migrate server side error mapping functionality | Major | . | Grant Henke | Grant Henke |
| KAFKA-2881 | Documentation improvement | Major | . | Gwen Shapira | Guozhang Wang |
| KAFKA-2879 | Make MiniKDC test service slightly more generic | Major | . | Gwen Shapira | Gwen Shapira |
| KAFKA-2668 | Add a metric that records the total number of metrics | Major | . | Joel Koshy | Dong Lin |
| JIRA | Summary | Priority | Component | Reporter | Contributor |
|---|---|---|---|---|---|
| KAFKA-3098 | "partition.assignment.strategy" appears twice in documentation | Major | . | Gwen Shapira | David Jacot |
| KAFKA-3095 | No documentation on format of sasl.kerberos.principal.to.local.rules | Major | core | Thomas Graves | Thomas Graves |
| KAFKA-3085 | BrokerChangeListener computes inconsistent live/dead broker list | Major | core | Jun Rao | David Jacot |
| KAFKA-3069 | Fix recursion in ZkSecurityMigrator | Major | security | Flavio Junqueira | Flavio Junqueira |
| KAFKA-3055 | JsonConverter mangles schema during serialization (fromConnectData) | Major | copycat | Kishore Senji | Ewen Cheslack-Postava |
| KAFKA-3009 | Disallow star imports | Major | . | Gwen Shapira | Manasvi Gupta |
| KAFKA-2999 | Errors enum should be a 1 to 1 mapping of error codes and exceptions | Major | . | Grant Henke | Grant Henke |
| KAFKA-2990 | NoSuchMethodError when Kafka is compiled with 1.8 and run on 1.7 | Major | . | Jason Gustafson | Jason Gustafson |
| KAFKA-2973 | Fix leak of child sensors on remove | Major | clients | Ismael Juma | Ismael Juma |
| KAFKA-2965 | Two variables should be exchanged. | Minor | controller | Bo Wang | |
| KAFKA-2928 | system tests: failures in version-related sanity checks | Major | . | Geoff Anderson | Geoff Anderson |
| KAFKA-2927 | System tests: reduce storage footprint of collected logs | Major | . | Geoff Anderson | Geoff Anderson |
| KAFKA-2926 | [MirrorMaker] InternalRebalancer calls wrong method of external rebalancer | Major | tools | Gwen Shapira | Gwen Shapira |
| KAFKA-2915 | System Tests that use bootstrap.servers embedded in jinja files are not working | Major | . | Ben Stopford | |
| KAFKA-2911 | Replace Utils.sleep() with Time.sleep() whenever possible | Major | . | Guozhang Wang | Jason Gustafson |
| KAFKA-2906 | Kafka Connect javadocs not built properly | Major | copycat | Ewen Cheslack-Postava | Ewen Cheslack-Postava |
| KAFKA-2902 | StreamingConfig getConsumerConfiigs uses getRestoreConsumerConfigs instead of getBaseConsumerConfigs | Major | kafka streams | Bill Bejeck | Bill Bejeck |
| KAFKA-2892 | Consumer Docs Use Wrong Method | Major | clients | Jesse Anderson | |
| KAFKA-2886 | WorkerSinkTask doesn't catch exceptions from rebalance callbacks | Major | copycat | Ewen Cheslack-Postava | Jason Gustafson |
| KAFKA-2878 | Kafka broker throws OutOfMemory exception with invalid join group request | Critical | clients | Rajini Sivaram | Rajini Sivaram |
| KAFKA-2874 | zookeeper-server-stop.sh may fail to shutdown ZK and/or may stop unrelated processes | Major | . | Michael Noll | |
| KAFKA-2872 | Error starting KafkaStream caused by sink not being connected to parent source/processor nodes | Major | kafka streams | Bill Bejeck | Bill Bejeck |
| KAFKA-2862 | Incorrect help description for MirrorMaker's message.handler.args | Major | . | Ashish K Singh | Ashish K Singh |
| KAFKA-2859 | Deadlock in WorkerSourceTask | Blocker | copycat | Ewen Cheslack-Postava | Ewen Cheslack-Postava |
| KAFKA-2850 | SslTransportLayerTest.testInvalidEndpointIdentification fails consistently | Major | clients, security | Flavio Junqueira | Rajini Sivaram |
| KAFKA-2826 | Make Kafka Connect ducktape services easier to extend | Minor | copycat | Ewen Cheslack-Postava | Ewen Cheslack-Postava |
| KAFKA-2824 | MiniKDC based tests don't run in VirtualBox | Major | . | Ben Stopford | Ben Stopford |
| KAFKA-2820 | System tests: log level is no longer propagating from service classes | Major | . | Geoff Anderson | Geoff Anderson |
| KAFKA-2815 | unit test failure in org.apache.kafka.streams.processor.internals.KafkaStreamingPartitionAssignorTest | Major | . | Jun Rao | Grant Henke |
| KAFKA-2814 | Kafka Connect system tests using REST interface fail on AWS | Major | copycat, system tests | Ewen Cheslack-Postava | Ewen Cheslack-Postava |
| KAFKA-2803 | Add hard bounce system test for distributed Kafka Connect | Major | copycat | Ewen Cheslack-Postava | Ewen Cheslack-Postava |
| KAFKA-2578 | Client Metadata internal state should be synchronized | Trivial | . | Jason Gustafson | Edward Ribeiro |
| KAFKA-2421 | Upgrade LZ4 to version 1.3 to avoid crashing with IBM Java 7 | Major | . | Rajini Sivaram | Grant Henke |
| KAFKA-2399 | Replace Stream.continually with Iterator.continually | Minor | . | Ismael Juma | Ismael Juma |
| JIRA | Summary | Priority | Component | Reporter | Contributor |
|---|---|---|---|---|---|
| KAFKA-2989 | Verify all partitions consumed after rebalancing in system tests | Major | . | Jason Gustafson | Jason Gustafson |
| KAFKA-2979 | Enable authorizer and ACLs in ducktape tests | Major | system tests | Flavio Junqueira | Flavio Junqueira |
| KAFKA-2949 | Make EndToEndAuthorizationTest replicated | Major | . | Flavio Junqueira | Flavio Junqueira |
| KAFKA-2905 | System test for rolling upgrade to enable ZooKeeper ACLs with SASL | Major | . | Flavio Junqueira | Flavio Junqueira |
| KAFKA-2825 | Add controller failover to existing replication tests | Major | . | Anna Povzner | Anna Povzner |
| KAFKA-2732 | Add test cases with ZK Auth, SASL and SSL | Major | security | Flavio Junqueira | Flavio Junqueira |
| JIRA | Summary | Priority | Component | Reporter | Contributor |
|---|---|---|---|---|---|
| KAFKA-3108 | KStream custom StreamPartitioner for windowed key | Minor | kafka streams | Yasuhiro Matsuda | Yasuhiro Matsuda |
| KAFKA-3081 | KTable Aggregation Implementation | Major | . | Guozhang Wang | Guozhang Wang |
| KAFKA-3078 | Add ducktape tests for KafkaLog4jAppender producing to SASL enabled Kafka cluster | Major | clients | Ashish K Singh | Ashish K Singh |
| KAFKA-3063 | LogRecoveryTest exits with -1 occasionally | Major | . | Guozhang Wang | Ismael Juma |
| KAFKA-3030 | Remove unused scala dependencies | Major | build | Grant Henke | Grant Henke |
| KAFKA-3022 | Deduplicate common project configurations | Major | build | Grant Henke | Grant Henke |
| KAFKA-3021 | Centralize dependency version managment | Major | build | Grant Henke | Grant Henke |
| KAFKA-3020 | Ensure Checkstyle runs on all Java code | Major | build | Grant Henke | Grant Henke |
| KAFKA-3016 | Add KStream-KStream window joins | Major | kafka streams | Yasuhiro Matsuda | Yasuhiro Matsuda |
| KAFKA-2984 | KTable should send old values along with new values to downstreams | Major | kafka streams | Yasuhiro Matsuda | Yasuhiro Matsuda |
| KAFKA-2962 | Add Simple Join API | Major | kafka streams | Yasuhiro Matsuda | Yasuhiro Matsuda |
| KAFKA-2856 | add KTable | Major | kafka streams | Yasuhiro Matsuda | Yasuhiro Matsuda |
| KAFKA-2837 | FAILING TEST: kafka.api.ProducerBounceTest > testBrokerFailure | Major | . | Gwen Shapira | jin xing |
| KAFKA-2811 | Add standby tasks | Major | kafka streams | Yasuhiro Matsuda | Yasuhiro Matsuda |
| KAFKA-2804 | Create / Update changelog topics upon state store initialization | Major | . | Guozhang Wang | Guozhang Wang |
| KAFKA-2763 | Reduce stream task migrations and initialization costs | Major | kafka streams | Yasuhiro Matsuda | Yasuhiro Matsuda |
| KAFKA-2733 | Distinguish metric names inside the sensor registry | Major | . | Guozhang Wang | Guozhang Wang |
| KAFKA-2727 | initialize only the part of the topology relevant to the task | Major | kafka streams | Yasuhiro Matsuda | Yasuhiro Matsuda |
| KAFKA-2707 | Make KStream processor names deterministic | Major | . | Yasuhiro Matsuda | Yasuhiro Matsuda |
| KAFKA-2706 | Make state stores first class citizens in the processor DAG | Major | kafka streams | Yasuhiro Matsuda | Yasuhiro Matsuda |
| KAFKA-2694 | Make a task id be a composite id of a topic group id and a partition id | Major | kafka streams | Yasuhiro Matsuda | Yasuhiro Matsuda |
| KAFKA-2667 | Copycat KafkaBasedLogTest.testSendAndReadToEnd transient failure | Major | copycat | Jason Gustafson | Ewen Cheslack-Postava |
| KAFKA-2654 | Avoid calling Consumer.poll(0) in each iteration | Major | . | Guozhang Wang | Yasuhiro Matsuda |
| KAFKA-2653 | Stateful operations in the KStream DSL layer | Major | . | Guozhang Wang | Guozhang Wang |
| KAFKA-2652 | Incorporate the new consumer protocol with partition-group interface | Major | . | Guozhang Wang | Yasuhiro Matsuda |
| KAFKA-2649 | Add support for custom partitioner in sink nodes | Major | kafka streams | Randall Hauch | Randall Hauch |
| KAFKA-2643 | Run mirror maker tests in ducktape with SSL and SASL | Major | . | Rajini Sivaram | Rajini Sivaram |
| KAFKA-2642 | Run replication tests in ducktape with SSL for clients | Major | . | Rajini Sivaram | Rajini Sivaram |
| KAFKA-2600 | Make KStream interfaces compatible with Java 8 java.util.function | Major | . | Guozhang Wang | Randall Hauch |
| KAFKA-2594 | Add a key-value store that is a fixed-capacity in-memory LRU cache | Major | kafka streams | Randall Hauch | Randall Hauch |
| KAFKA-2593 | KeyValueStores should not require use of the context's default serializers and deserializers | Major | kafka streams | Randall Hauch | Randall Hauch |
| KAFKA-2591 | Remove Persistent Data before Restoringafter a Fault | Major | . | Guozhang Wang | Guozhang Wang |
| KAFKA-2509 | Replace LeaderAndIsr{Request,Response} with org.apache.kafka.common.network.requests equivalent | Major | . | Ismael Juma | Grant Henke |
| KAFKA-2422 | Allow copycat connector plugins to be aliased to simpler names | Minor | copycat | Ewen Cheslack-Postava | Gwen Shapira |
| KAFKA-2072 | Add StopReplica request/response to o.a.k.common.requests and replace the usage in core module | Major | . | Gwen Shapira | David Jacot |
| KAFKA-2070 | Replace OffsetRequest/response with ListOffsetRequest/response from org.apache.kafka.common.requests | Major | . | Gwen Shapira | Grant Henke |
| JIRA | Summary | Priority | Component | Reporter | Contributor |
|---|---|---|---|---|---|
| KAFKA-2896 | System test for partition re-assignment | Major | . | Gwen Shapira | Anna Povzner |
| KAFKA-2845 | Add 0.9 clients vs 0.8 brokers compatibility test | Major | . | Geoff Anderson | Geoff Anderson |
| KAFKA-2830 | Change default fix version to <IP_ADDRESS> in kafka-merge-pr.py | Major | build | Ismael Juma | Ismael Juma |


“Looking at the sky, he suddenly saw that it had become black. Then white again, but with great rippling
circles. The circles were vultures wheeling around the sun. The vultures disappeared, to be replaced by checkers
squares ready to be played on. On the board, the pieces moved around incredibly rapidly, winning dozens of games
every minute. They were scarcely lined up before they started rushing at each other again, banging into each
other, forming fighting combinations, wiping the other side out in the wink of an eye. Then the squares
scattered, giving way to the grille of a crossword puzzle, and here, too, words flashed, drove each other away,
clustered, were erased. They were all very long words, like Catalepsy, Thunderbird, Superrequeteriquísímo and
Anticonstitutionally.”
― Jean-Marie G. Le Clézio, The Book of Flights
A crossword
is a word puzzle that normally takes the form of a square or a rectangular grid of white and black
shaded squares. The goal is to fill the white squares with letters, forming words or phrases, by solving clues which
lead to the answers. In languages that are written left-to-right, the answer words and phrases are placed in the
grid from left to right and from top to bottom. The shaded squares are used to separate the words or phrases.
We will solve a few crosswords which have a lattice-like structure,
with a higher percentage of shaded squares, leaving up to half the letters in an answer unchecked.
For example, if the top row has an answer running all the way across,
there will be no across answers in the second row.
Your program receives a crossword pattern without clues and numbers, and it should determine word positions itself
with
the following rules:
- If a cell is placed in the most left column or neighbour left cell is shaded, and the neighbouring right cell is
empty, then this cell is the beginning of left-to-right word;
- If a cell is placed in the top row or the neighbouring upward cell is shaded, and neighbour down cell is empty,
then this cell is the beginning of up-to-down word.
All words have a length greater than or equal to 3 letters. All empty cells should filled in.
You are given a crossword as a sequence of strings, where "X" is a shaded cell and "." is an empty cell.
You are also given the predefined list of words in lowercase.
(You can find it
here
or
in the default code).
This list is the same for all crosswords and contains about 1500 nouns. You should use only the given words.
You don't need to find all of the possible solutions. It will be enough to find any solution which fills the
crossword puzzle and contains the correct words.
Input: Two arguments. A crossword as a tuple of strings and the words as a tuple of strings.
Output: Any solved variant of the crossword as a tuple/list of strings.
Example:
solver(('.XXX.', '...X.', '.X.X.', '.....'))
How it is used:
This is a classic constraint satisfaction problem and can save you time with the daily crosswords.
Precondition:
3 < len(crossword) ≤ 10
all(3 < len(row) ≤ 10 and len(row) == len(crossword[0]) for row in crossword)