| Path: | README.rdoc |
| Last Update: | Tue Dec 01 20:40:04 +0000 2009 |
JSpec is a minimalistic JavaScript behavior driven development framework, providing simple installation, extremely low learning curve, absolutely no pollution to core prototypes, async request support, and incredibly sexy syntax, tons of matchers and much more.
Simply download JSpec and include JSpec.css and JSpec.js in your markup. Head over to the downloads section on Github, clone this public repo, or add JSpec as a git submodule with in your project. Alternatively JSpec is also available as a Ruby Gem (though this is not required), which also provides the `jspec` executable. First install [Gemcutter](gemcutter.org/) then execute:
$ sudo gem install jspec
At which point you may:
$ jspec init myproject
By default, the command above will use absolute path for all JSpec library files. This behavior can be a problem when you‘re working across different computers or operating systems. You can freeze the library or symlink it.
$ jspec init myproject --freeze $ jspec init myproject --symlink
JSpec scripts should NOT be referenced via the   ...
You may optionally want to use sources in the /pkg directory for your project, since it includes compressed alternatives generated each release.
Using the bash cheat sheet library found at github.com/visionmedia/ch we can get quick cheat sheets for many aspects of development including JSpec!
$ cd /tmp && git clone git://github.com/visionmedia/ch.git && cd ch && sudo make install && ch jspec
describe 'ShoppingCart' before_each cart = new ShoppingCart end describe 'addProducts' it 'should add several products' cart.addProduct('cookie') cart.addProduct('icecream') cart.should.have 2, 'products' end end describe 'checkout' it 'should throw an error when checking out with no products' -{ cart.clear().checkout() }.should.throw_error EmptyCart end end end
JSpec‘s grammar is optional, you may also use the equivalent grammar-less alternative below using pure JavaScript (when using the JSpec grammar you may also use grammar-less assertions):
JSpec.describe('ShoppingCart', function(){ before_each(function{ cart = new ShoppingCart }) describe('addProducts', function(){ it ('should add several products', function(){ cart.addProducts('cookie') cart.addProducts('icecream') expect(cart).to(have, 2, 'products') }) }) describe('checkout', function(){ it ('should throw an error when checking out with no products', function(){ expect(function(){ cart.clear().checkout() }).to(throw_error, EmptyCart) }) }) })
You may alter the way JSpec operates by assigning options via the JSpec.options hash, by passing string-based option values via the query string, or passing a hash to run(). For example JSpec.options.failuresOnly = true, and ?failuresOnly=1 will both work.
* Core - equal, be === - be_a, be_an have constructor of x - be_an_instance_of instanceof x - be_at_least >= - be_at_most <= - be_null == null - be_empty length < 0 or {} - be_true == true - be_false == false - be_type be type of x - be_greater_than > - be_less_than < - be_undefined check if variable passed is undefined - throw_error should throw an error, optionally supply the error string or regexp for message comparison - have object should have n of property (person.should.have(2, 'pets')) - have_at_least object should have at least n of property - have_at_most object should have a maximum n of property - have_within object should have within n..n of property (person.should.have_within(1..3, 'pets') - have_length length of n - have_prop object should have property x, optionally supplying an expected value - have_property strict version of have_prop - be_within checks if n is within the range passed - include include substring, array element, or hash key - match string should match regexp x - respond_to property x should be a function - eql matches simple literals (strings, numbers) with == However composites like arrays or 'hashes' are recursively matched, meaning that [1, 2, [3]].should_eql([1, 2, [3]]) will be true. * jQuery - have_tag, have_one have exactly one tag - have_tags, have_many have more than one tag - have_child have exactly one child - have_children have more than one child - have_text have plain text - have_attr have an attribute, with optional value - have_type - have_id - have_title - have_alt - have_href - have_rel - have_rev - have_name - have_target - have_value - have_class - have_classes - be_visible - be_hidden - be_enabled - be_disabled - be_selected - be_checked
The javascript mock timers library is available at github.com/visionmedia/js-mock-timers although it is already bundled with JSpec at lib/jspec.timers.js
Timers return ids and may be passed to clearInterval(), however they do not execute in threads, they must be manually scheduled and controlled via the tick() function.
setTimeout(function(){ alert('Wahoo!') }, 400) tick(200) // Nothing happens tick(400) // Wahoo!
setInterval() works as expected, although it persists, where as setTimeout() is destroyed after a single call. As conveyed by the last tick() call below, a large increment in milliseconds may cause the callbacks to be called several times to ‘catch up’.
progress = '' var id = setInterval(function(){ progress += '.' }, 100) tick(50), print(progress) // '' tick(50), print(progress) // '.' tick(100), print(progress) // '..' tick(100), print(progress) // '...' tick(300), print(progress) // '......' clearInterval(id) tick(800) // Nothing happens
You may also reset at any time using resetTimers()
Proxy or ‘Spy’ assertions allow you to assert that a method is called n number of times, with x arguments, returning x value. For example:
person = { getPets : function(species){ return ['izzy'] }} person.should.receive('getPets', 'twice').with_args(an_instance_of(String))and_return(['izzy']) person.getPets('dog') // This will pass person.getPets() // This will fail because we asked an instance of String
This is a useful mechanism for testing the behavior of your object, as well as how other methods may interact with it. Below is another example:
array = ['foo', 'bar'] array.should.receive('toString').and_return('foo,bar') 'array: ' + array // This line causes the spec to pass due to calling toString()
For more examples view spec/spec.matchers.js
JSpec currently provides very simple stubbing support shown below:
person = { toString : function(){ return '<Person>' } } stub(person, 'toString').and_return('Ive been stubbed!')
After each spec all stubs are restored to their original methods so there is no reason to explicitly call destub(). To persist stubs, use a before_each hook:
before_each stub(someObject, 'method').and_return({ some : thing }) end
To destub a method simply call destub() at any time:
destub(person, 'toString')
If you would like to whipe an object clear of stubs simply pass it to destub() without an additional method argument:
destub(person)
Alternatively both these utility functions may be called as methods on any object when using the JSpec grammar:
someObject.stub('method').and_return('whatever') // Converted to stub(someObject, 'method').and_return('whatever')
* Core - an_instance_of used in conjunction with the 'receive' matcher - mockRequest, mock_request mock a request (requires jspec.xhr.js) - unmockRequest, unmock_request unmock requests (requests jspec.xhr.js) * jQuery - sandbox used to generate new DOM sandbox, using jQuery object - element same as invoking jQuery, just reads better and no need to worry about $ collisions - elements alias of element
JSpec‘s support for shared behaviors allows multiple suites or describe blocks to share common functionality. For example an Admin, would inherit all specs of User:
describe 'User' before User = function(name) { this.name = name } user = new User('joe') end it 'should have a name' user.should.have_property 'name' end describe 'Administrator' should_behave_like('User') before Admin = function(name) { this.name = name } Admin.prototype.may = function(perm){ return true } user = new Admin('tj') end it 'should have access to all permissions' user.may('edit pages').should.be_true end end end
NOTE: both User and Administrator‘s before hooks implement the ‘user’ variable
JSpec supports generic Ajax mocking which is usable with any JavaScript framework via ‘jspec.xhr.js’. The API is comprised of two functions, mockRequest() and unmockRequest(). unmockRequest() is automatically called after each specification to restore the default functionality of XMLHttpRequest, so it is uncommon to call unmockRequest() directly. Below is a jQuery example:
it 'should mock requests' mockRequest().and_return('{ foo : "bar" }', 'application/json') $.getJSON('foo', function(response, statusText){ response.foo.should.eql 'bar' }) end
The mockRequest().and_return signature is as follows:
mockRequest().and_return(<data>, [content-type], [response-status-code], [headers-hash])
At the moment mockRequest() itself does not accept any arguments, however in the future this will be used to target specific uris for mocking.
NOTE: works with Rhino as well
Currently the following hooks are supported, and may be utilized any number of times as they are simply pushed to a stack. So for instance you may have two before_each blocks within the same scope, they will both run, but this can help keep your specs readable.
* before run once before the suite is executed * after run once after the suite is executed * before_each run before each specification * after_each run after each specification
Custom contexts can be applied to supply helper methods or properties to all subsequent bodies (other hooks, or specs).
Keep in mind that when replacing the default context you will loose functionality provided by it, unless you manually merge it with your custom context.
To reset the context simply assign null to obtain the original context.
... before JSpec.context = { foo : 'bar' } end after JSpec.context = null end it 'will work ;)' foo.should_equal 'bar' end ...
Currently only jspec.jquery.js supports async requests. JSpec uses jQuery.ajaxSetup and sets all requests to sync, which preserves execution order, and reports correctly.
it 'should load mah cookies (textfile)' $.post('async', function(text){ text.should_eql 'cookies!' }) end
The pre-processing capability of JSpec is extremely powerful. Your JavaScript code is not necessarily what it seems. For example when you seemingly invoke a object‘s prototype like below:
'foobar'.should.include 'bar'
First parens are added:
'foobar'.should.include('bar')
Secondly the matcher invocation is converted to a non-polluting match() call:
JSpec.match('foobar', 'should', 'include', 'bar')
This also means instead of:
var object = { foo : 'bar' } object.should.include 'foo'
We can do:
{ foo : 'bar' }.should.include 'foo'
These are equivalent:
-{ throw 'test' }.should.throw_error function() { throw 'test' }.should.throw_error
The following expands to the array of [1,2,3,4,5]
n.should.be_within 1..5
Any text placed after END is considered irrelevant and is striped out before evaluation. This is sometimes useful for document or code reference while writing specs.
For example when writting regression specs it is sometimes useful to paste the issue ticket‘s comment(s) below this area for reference.
To change a formatter simply alter the options hash like below, assigning a new constructor, or pass it within the hash to run():
JSpec.options.formatter = JSpec.formatters.Console
OR
JSpec .exec('...') .run({ formatter : JSpec.formatters.Terminal }) .report()
The fixture() utility function may be used in order to load arbitrary file contents for use with your specifications. JSpec will resolve fixture(‘data’) in the following manor:
- 'data' - 'spec/data' - 'spec/fixtures/data' - 'spec/fixtures/data.html'
So if the file ‘spec/fixtures/data.html’ exists, we can simply use fixture(‘data’), where as ‘spec/fixtures/xml/data.xml’ must be specified with fixture(‘xml/data.xml’).
If you prefer not to store fixtures in the ‘fixtures’ directory you must be more specific with the path supplied.
When using jQuery testing DOM elements is very easy. Many may think they require specific sandbox divs in their html, however you do not. Using the fixture support mentioned above you may simply load some HTML, and use the ‘elements()’ utility which is an alias of jQuery:
describe 'JSpec DOM testing' describe 'is so easy' before_each list = elements(fixture('users-list')) // or list = jQuery(fixture('users-list')) // or list = $(fixture('users-list')) end it 'should have users' list.should.have_tag 'ul' end end end
You may also use simple strings, since jQuery‘s constructor will convert them to DOM elements:
describe 'Something' before_each html = elements('
Foo
') // or html = $('
Foo
') ... end it 'should do something' html.should.have_text 'Foo' end end
First lets create a simple equality matcher. In the case below JSpec is smart enough to realize this is simply a binary operator, and simply transforms this into ‘actual === expected‘
JSpec.addMatchers({ equal : '===' })
To alias a method to keep your specs readable you may alias them like below:
JSpec.addMatchers({ be : 'alias equal' }) 'foo'.should.equal 'foo' true.should.be true
Matchers with string bodies implicitly return the expression value. The expanded version of the equal matcher would then be:
JSpec.addMatchers({ equal : 'actual === expected' })
Large matchers or those which require several parameters may wish to utilize the hash method:
JSpec.addMatchers({ equal : { match : function(actual, expected){ return actual === expected }} })
To keep JSpec tiny, JSpec will default to generating failure messages for you, how ever this can be explicitly defined:
JSpec.addMatchers({ equal : { match : function(actual, expected){ return actual === expected }, message : function(actual, expected, negate) { return 'a message here' } } })
When defining matchers that are extremely similar in functionality, however require different names, you may use a prefixed list of words like below which defines be_disabled, be_selected, be_checked, and have_type, have_id, etc. Each function must return the matcher body which will be used.
JSpec.addMatchers({ 'be disabled selected checked' : function(attr) { return 'jQuery(actual).attr("' + attr + '")' }, 'have type id title alt href src sel rev name target' : function(attr) { return function(actual, value) { return value ? jQuery(actual).attr(attr) == value: jQuery(actual).attr(attr) } } })
JSpec provides a hook architecture for extending or analyzing various points in its execution, through the use of ‘Modules’. For a Module example view lib/jspec.jquery.js.
The following methods or properties are utilized by JSpec:
- name : module name string - init : called to initialize a module - formatters : hash of formatters merged with JSpec.formatters - utilities : hash of utility functions merged with JSpec.defaultContext - matchers : hash of matchers merged with JSpec's core matchers via JSpec.addMatchers() - DSLs : hash of DSL methods; for example DSLs.snake contains before_each, after_each, etc. Where as DSLs.camel may contain beforeEach, afterEach, etc.
Below is a list of hooks, descriptions, and valid return values which may simply be implemented as module methods. beforeSuite, afterSuite, beforeSpec, and afterSpec have lower precedence than before_each, after_each etc within the specs themselves, allowing them to override or undo anything that has been done by a Module.
- running(options) : started running JSpec with the options passed : returning 'stop' will halt running - loading(file) : loading a file : returning 'stop' will prevent loading - executing(file) : executing a file : returning 'stop' will prevent execution - posting(data, url) : posting data to a url : returning 'stop' will prevent request - preprocessing(input) : before input string is preprocessed : return input string for next hook to preprocess - stubbing(object, method, result) : called when stubbing an object's method, and return value (result). : (no return value) - requiring(dependency, message) : requiring a dependency : (no return value) - beforeAssertion(assertion) : before an assertion has been made : (no return value) - afterAssertion(assertion) : after an assertion has been made : (no return value) - addingMatcher(name, body) : unprocessed matcher name and body : (no return value) - addingSuite(suite) : adding Suite instance to JSpec : (no return value) - beforeSuite(suite) : before running of suite (describe block) : (no return value) - afterSuite(suite) : after running of suite (describe block) : (no return value) - beforeSpec(spec) : before running of spec (it block) : (no return value) - afterSpec(spec) : after running of spec (it block) : (no return value) - reporting(options) : called before reporting : (no return value) - evaluatingBody(dsl, matchers, context, contents) : evaluating body contents, with the given context, matchers and dsl. : (no return value)
For example you may wish to proxy files which are being executed, simply implement the executing method like below. This example will stop execution of any file matching /matchers/.
MyModule = { executing : function(file) { if (file.match(/matchers/)) return 'stop' } } JSpec.include(MyModule)
Immutable values may also be passed to hooks using hookImmutable() internally. This allows for simple numbers, strings, etc to be utilized or altered within a hook implementation. Below is an example module which adds functionality to the JSpec grammar by converting SomeObject.stub(‘method’) to stub(SomeObject, ‘method’):
JSpec.include({ preprocessing : function(input) { return input.replace(/(\w+)\.(stub|destub)\((.*?)\)$/gm, '$2($1, $3)') } })
When installed as a Ruby Gem, the `jspec` executable will become available, allowing you to initialize project templates quickly, as well as auto-testing specifications when a file is altered.
Initialize JSpec-driven project template in directory ‘myproject’:
$ jspec init myproject
Once within ‘myproject’ start testing by executing:
$ jspec
For additional usage execute:
$ jspec help
Or for specific usage:
$ jspec help run
JSpec provides transparent support for Rhino, while using the Terminal formatter. Simply create a JavaScript file with contents similar to below, and then execute the command following it:
load('lib/jspec.js') JSpec .exec('spec/spec.grammar.js') .exec('spec/spec.core.js') .run({ formatter : JSpec.formatters.Terminal, failuresOnly : true }) .report()
Initialize project with:
$ jspec init myproject
Run with:
$ jspec run --rhino
Or bind (automated testing):
$ jspec --rhino
The Ruby JavaScript testing server included with JSpec simply runs the spec suites within each browser you specify, while reporting result back to the terminal. It is essentially the same as using the DOM formatter and auto-testing each browser, however results are centralized to the terminal, removing the need to manually view each browser‘s output.
When utilizing the server if a file named spec/jspec.rb (or jspec/jspec.rb for rails) is present, then it will be loaded before the server is started. This allows you to add Sinatra routes, support additional Browsers, etc.
Run with all supported browsers:
$ jspec run --server
Run with specific browsers:
$ jspec run --browsers Safari,Firefox,Chrome,Explorer
Run with alternative browser names:
$ jspec run --browsers safari,ff,chrome,ie
Browsers supported in core:
Browser::Safari Browser::Chrome Browser::Opera Browser::Firefox Browser::IE
Supplied routes:
/slow/NUMBER /status/NUMBER
For example $.get(’/slow/4’, function(){}) will take 4 seconds to reply, where as $.get(’/status/404’, function(){}) will respond with an 404 status code. Add additional Sinatra routes to the jspec.rb file to add your own functionality.
JSpec provides an interactive shell through Rhino, utilize with:
$ jspec shell
Or to specify additional files to load:
$ jspec shell lib/*.js
Or view additional shell help
$ jspec help shell
No additional gems are required for JSpec to work with rails, although github.com/bhauman/jspec-rails has been created by ‘bhauman’. JSpec supports Rails out of the box, simply execute:
$ jspec init --rails
Then while still in the root directory of your Rails project, run the following command which will bind to, and refresh your browsers automatically when any changes are made to ./public/javascripts/*.js or ./jspec/*.js
$ jspec
Or just like regular JSpec applications, run once:
$ jspec run
Or run via the terminal using Rhino:
$ jspec run --rhino
Browsers below are supported and can be found in server/browsers.rb, however your spec/server.rb file may support additional browsers.
object.stub(‘getContentsOfURL’).and_return(function(url){
return 'html'
})
In cases such as this, you may always revert to utilizing JSpec in a grammar-less form as follows:
stub(object, ‘getContentsOfURL’).and_return(function(url){
return 'html'
})
Many ideas and bug reports were contributed by the following developers, thankyou for making JSpec more enjoyable, and bug free ;)
(The MIT License)
Copyright (c) 2008 - 2009 TJ Holowaychuk<EMAIL_ADDRESS>Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the ‘Software’), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
 IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.


status: Passed, as amended, Jan 89 X3J13Note: some confusion in minutes as to whether COMPLEMENT was added
as part of TEST-NOT-IF-NOT or whether FUNCTION-COMPOSITION was
passed but with only COMPLEMENT preserved.
In any case: TEST-NOT-IF-NOT:FLUSH-ALL as stated here
passed with "Remove" -> "Deprecate". See issue
FUNCTION-COMPOSITION for more details.
Forum: Cleanup
Issue: TEST-NOT-IF-NOT
References: Functions offering a :TEST-NOT keyword:
ADJOIN (p276), ASSOC (p280), COUNT (p257), DELETE (p254),
DELETE-DUPLICATES (p254), FIND (p257),
INTERSECTION (p277), MEMBER (p275), MISMATCH (p257),
NINTERSECTION (p277), NSET-DIFFERENCE (p278),
NSET-EXCLUSIVE-OR (p278), NSUBLIS (p275), NSUBST (p274),
NSUBSTITUTE (p256), NUNION (p276), POSITION (p257),
RASSOC (p281), REMOVE (p253), REMOVE-DUPLICATES (p254),
SEARCH (p258), SET-DIFFERENCE (p278),
SET-EXCLUSIVE-OR (p278), SUBLIS (p274), SUBSETP (p279),
SUBST (p273), SUBSTITUTE (p255), TREE-EQUAL (p264),
UNION (p276);
Functions with "-IF-NOT" in their name:
ASSOC-IF-NOT (p280), COUNT-IF-NOT (p257),
DELETE-IF-NOT (p254), FIND-IF-NOT (p257),
MEMBER-IF-NOT (p275), NSUBST-IF-NOT (p274),
NSUBSTITUTE-IF-NOT (p256), POSITION-IF-NOT (p257),
RASSOC-IF-NOT (p281), REMOVE-IF-NOT (p253),
SUBST-IF-NOT (p273), SUBSTITUTE-IF-NOT (p255);
Related Issue: FUNCTION-COMPOSITION
Category: CHANGE
Edit history: 02-Oct-88, Version 1 by Pitman (just FLUSH-ALL)
05-Oct-88, Version 2 by Pitman (add option FLUSH-TEST-NOT)
01-Dec-88, Version 3 by Masinter (add discussion)
18-Mar-89, Version 4 by Masinter (as amended)
Problem Description:
The -IF-NOT functions are functionally unnecessary.
The :TEST-NOT keywords are not only functionally unnecessary but
also problematic because it's not clear what to do when both :TEST
and :TEST-NOT are provided.
Many people think Common Lisp is more `bloated' than it needs
to be and these aspects of the language are commonly cited
specific examples.
Proposal (TEST-NOT-IF-NOT:FLUSH-ALL):
Deprecate all -IF-NOT functions (named above) from Common Lisp.
Deprecate the :TEST-NOT keyword from the Common Lisp functions which
currently provide them (named above).
Rationale:
This makes the language a bit simpler.
The removal of :TEST-NOT also makes the language easier to explain.
Cost to Implementors:
Very slight.
Some symbols would disappear from the LISP package but could
still be offered in proprietary packages if deemed important
enough.
Implementations could compatibly retain the :TEST-NOT keywords
for an interim period.
Current Practice:
Presumably no one has done this yet.
Cost to Users:
Some rewrites would be needed.
Those rewrites, which are already fairly simple, would be even
more simple if some form of the FUNCTION-COMPOSITION issue is
voted in -- in particular, the COMPLEMENT function which it
proposes would help enormously in this regard.
Cost of Non-Adoption:
Common Lisp would continue to be what some people feel is
"bigger than it needs to be".
Benefits:
The cost of non-adoption would be avoided.
Aesthetics:
Presumably this makes the language easier to teach.
Performance impact:
Very small; removing the :TEST-NOT keywords would
make the simple implementation of the functions that
used to have them slightly faster, but the resulting
code of the inner loop is likely to be much slower.
Discussion:
Many people objected strongly to this proposals --
they might have been a nice idea five years ago, but are
gratuitous incompatibilities now: incompatible changes with
insufficient payback.
Some of those objections might be tempered if some additional
changes were made to Common Lisp: adding a COMPLEMENT
function, or if there were a strategy to declare some parts of the
language "obsolete". Since these conditions haven't been done,
their objections stand.
Steele noted that one main reservation to FLUSH-ALL is that
he uses REMOVE-IF-NOT much more than REMOVE-IF.
This issue is related to FUNCTION-COMPOSITION, but is not
dependent on it. Some support the combination of FLUSH-ALL and
the NEW-FUNCTIONS part of FUNCTION-COMPOSITION in spite of
the incompatible change because of the aesthetic appeal.
Some people expressed their intention to vote for FLUSH-ALL
only if FUNCTION-COMPOSITION:NEW-FUNCTIONS.
It was noted that and
adding a #~ readmacro such that
(FIND-IF-NOT #'ZEROP '(0 0 3))
== (FIND-IF (COMPLEMENT #'ZEROP) '(0 0 3))
== (FIND-IF #~ZEROP '(0 0 3))
The modification of these functions is moot for those who
prefer to use extended LOOP macro/iteration constructs
in lieu of the sequence functions.
Several alternative names for REMOVE-IF-NOT were
suggested: KEEP-IF, ABSTRACT, FILTER. We did not
pursue these suggestions.


Secret of explosive volcanism unlocked
| Source: | Technical University of Munich (TUM) |
| Summary: | When will the next eruption take place? Examination of samples from Indonesia's Mount Merapi show that the explosivity of stratovolcanoes rises when mineral-rich gases seal the pores and microcracks in the uppermost layers of stone. These findings result in new possibilities for the prediction of an eruption. |
When will the next eruption take place? Examination of samples from Indonesia's Mount Merapi show that the explosivity of stratovolcanoes rises when mineral-rich gases seal the pores and microcracks in the uppermost layers of stone. These findings result in new possibilities for the prediction of an eruption.
Mount Merapi on Java is among the most dangerous volcanoes in the world. Geoscientists have usually used seismic measurements which illustrate underground movements when warning the population of a coming eruption in time.
An international team including scientists from the Technical University of Munich (TUM) has now found another indication for an upcoming eruption in the lava from the peak of Mount Merapi: The uppermost layer of stone, the "plug dome," becomes impermeable for underground gases before the volcano erupts.
"Our investigations show that the physical properties of the plug dome change over time," says Prof. H. Albert Gilg from the TUM Professorship for Engineering Geology . "Following an eruption the lava is still easily permeable, but this permeability then sinks over time. Gases are trapped, pressure rises and finally the plug dome bursts in a violent explosion."
Mount Merapi as a model volcano
Using six lava samples, one from an eruption of Mount Merapi in 2006, the others from the 1902 eruption — the researchers were able to ascertain alterations in the stone. Investigation of pore volumes, densities, mineral composition and structure revealed that permeability dropped by four orders of magnitude as stone alteration increased. The cause is newly formed minerals, in particular potassium and sodium aluminum sulfates which seal the fine cracks and pores in the lava.
The cycle of destruction
Computer simulations confirmed that the reduced permeability of the plug dome was actually responsible for the next eruption. The models show that a stratovolcano like Mount Merapi undergoes three phases: First, after an eruption when the lava is still permeable, outgassing is possible; in the second phase the plug dome becomes impermeable for gases, while at the same time the internal pressure continuously increases; in the third phase the pressure bursts the plug dome.
Photographs of Mount Merapi from the period before and during the eruption of May 11, 2018 support the three-phase model: The volcano first emitted smoke, then seemed to be quiet for a long time until the gas found an escape and shot a fountain of ashes kilometers up into the sky.
"The research results can now be used to more reliably predict eruptions," says Gilg. "A measurable reduction in outgassing is thus an indication of an imminent eruption."
Mount Merapi is not the only volcano where outgassing measurements can help in the timely prediction of a pending eruption. Stratovolcanoes are a frequent source of destruction throughout the Pacific. The most famous examples are Mount Pinatubo in the Philippines, Mount St. Helens in the western USA and Mount Fuji in Japan.
make a difference: sponsored opportunity
Story Source:
Materials provided by Technical University of Munich (TUM).
Note: Content may be edited for style and length.
Journal Reference:
- Michael J. Heap, Valentin R. Troll, Alexandra R. L. Kushnir, H. Albert Gilg, Amy S. D. Collinson, Frances M. Deegan, Herlan Darmawan, Nadhirah Seraphine, Juergen Neuberg, Thomas R. Walter. Hydrothermal alteration of andesitic lava domes can lead to explosive volcanic behaviour. Nature Communications, 2019; 10 (1) DOI: 10.1038/s41467-019-13102-8
Cite This Page:
| MLA | Technical University of Munich (TUM). "Secret of explosive volcanism unlocked." ScienceDaily. ScienceDaily, 15 November 2019. <www.sciencedaily.com/releases/2019/11/191115101109.htm>. |
| APA | Technical University of Munich (TUM). (2019, November 15). Secret of explosive volcanism unlocked. ScienceDaily. Retrieved November 17, 2019 from www.sciencedaily.com/releases/2019/11/191115101109.htm |
| Chicago | Technical University of Munich (TUM). "Secret of explosive volcanism unlocked." ScienceDaily. www.sciencedaily.com/releases/2019/11/191115101109.htm (accessed November 17, 2019). |


|
||||||||||
| PREV CLASS NEXT CLASS | FRAMES NO FRAMES | |||||||||
| SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |
java.lang.Object java.awt.event.MouseAdapter domosaics.ui.views.view.components.ZoomController
public class ZoomController
The ZoomController controls the zoom settings for a AbstractView
.
The zoom is represented by an AffineTransform object which must be
applied to the active graphical context in a rendering method.
See AbstractView.render(Graphics)
for details.
The AffineTransforms scale factor is calculated when the mouse wheel is scrolled and its translation is calculated if the mouse is dragged around.
This class additionally provides methods to enable the zoom mode for a view by using toggleZoomMode().
if the view switches into zoom mode all actions are disabled except
those actions which implement the empty interface ZoomCompatible
.
| Constructor Summary | |
|---|---|
ZoomController(View view)
Constructor for the ZoomController |
| Method Summary | |
|---|---|
java.awt.geom.AffineTransform |
getZoomTransform()
Return the calculated zoom transformation. |
boolean |
isZoomMode()
Return whether or not the view is within zoom mode |
void |
mouseDragged(java.awt.event.MouseEvent e)
Calculates the translation of AffineTransform object representing the zoom when mouse is dragged. |
void |
mousePressed(java.awt.event.MouseEvent e)
Indicates that the dragging started |
void |
mouseReleased(java.awt.event.MouseEvent e)
Indicates that the dragging was stopped |
void |
mouseWheelMoved(java.awt.event.MouseWheelEvent e)
Calculates and applies a scale on the AffineTransform object representing the zoom when the mouse wheel is used. |
void |
toggleZoomMode()
Toggles the zoom mode feature for the controlled view. |
| Methods inherited from class java.awt.event.MouseAdapter |
|---|
mouseClicked, mouseEntered, mouseExited, mouseMoved |
| Methods inherited from class java.lang.Object |
|---|
equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait |
| Constructor Detail |
|---|
public ZoomController(View view)
view
- the view being controlled by this Controller| Method Detail |
|---|
public void toggleZoomMode()
public boolean isZoomMode()
public java.awt.geom.AffineTransform getZoomTransform()
public void mouseWheelMoved(java.awt.event.MouseWheelEvent e)
mouseWheelMoved
in interface java.awt.event.MouseWheelListener
mouseWheelMoved
in class java.awt.event.MouseAdapter
public void mouseDragged(java.awt.event.MouseEvent e)
mouseDragged
in interface java.awt.event.MouseMotionListener
mouseDragged
in class java.awt.event.MouseAdapter
public void mousePressed(java.awt.event.MouseEvent e)
mousePressed
in interface java.awt.event.MouseListener
mousePressed
in class java.awt.event.MouseAdapter
public void mouseReleased(java.awt.event.MouseEvent e)
mouseReleased
in interface java.awt.event.MouseListener
mouseReleased
in class java.awt.event.MouseAdapter
|
||||||||||
| PREV CLASS NEXT CLASS | FRAMES NO FRAMES | |||||||||
| SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |


Coverage Summary for Class: SecurityUserServiceImpl (com.lambdaschool.bookstore.services)
| Class | Method, % | Line, % |
|---|---|---|
| SecurityUserServiceImpl | 50% (1/ 2) | 14.3% (1/ 7) |
| SecurityUserServiceImpl$$EnhancerBySpringCGLIB$$ebb95472 | ||
| SecurityUserServiceImpl$$EnhancerBySpringCGLIB$$f227be5e | ||
| total | 50% (1/ 2) | 14.3% (1/ 7) |
1 package com.lambdaschool.bookstore.services;
2
3 import com.lambdaschool.bookstore.exceptions.ResourceNotFoundException;
4 import com.lambdaschool.bookstore.models.User;
5 import com.lambdaschool.bookstore.repository.UserRepository;
6 import org.springframework.beans.factory.annotation.Autowired;
7 import org.springframework.security.core.userdetails.UserDetails;
8 import org.springframework.security.core.userdetails.UserDetailsService;
9 import org.springframework.stereotype.Service;
10 import org.springframework.transaction.annotation.Transactional;
11
12 // make sure the user that is in the import be the one from this application, not core security
13 // import org.springframework.security.core.userdetails.User;
14
15 /**
16 * This implements User Details Service that allows us to authenticate a user.
17 */
18 @Service(value = "securityUserService")
19 public class SecurityUserServiceImpl
20 implements UserDetailsService
21 {
22 /**
23 * Ties this implementation to the User Repository so we can find a user in the database.
24 */
25 @Autowired
26 private UserRepository userrepos;
27
28 /**
29 * Verifies that the user is correct and if so creates the authenticated user
30 *
31 * @param s The user name we are look for
32 * @return a security user detail that is now an authenticated user
33 * @throws ResourceNotFoundException if the user name is not found
34 */
35 @Transactional
36 @Override
37 public UserDetails loadUserByUsername(String s)
38 throws
39 ResourceNotFoundException
40 {
41 User user = userrepos.findByUsername(s.toLowerCase());
42 if (user == null)
43 {
44 throw new ResourceNotFoundException("Invalid username or password.");
45 }
46 return new org.springframework.security.core.userdetails.User(user.getUsername(),
47 user.getPassword(),
48 user.getAuthority());
49 }
50 }


|
|||||||||||
| PREV CLASS NEXT CLASS | FRAMES NO FRAMES | ||||||||||
| SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |
The Lease interface defines a type of object that is returned to the lease holder and issued by the lease grantor. Particular instances of the Lease type will be created by the grantors of a lease, and returned to the holder of the lease as part of the return value from a call that allocates a leased resource. The call that requests a leased resource will typically include a requested duration for the lease. If the request is for a particular duration, the lease grantor is required to grant a lease of no more than the requested period of time. A lease may be granted for a period of time shorter than that requested.
| Field Summary | |
static int |
ABSOLUTE
The serialized form of the lease will contain the time of expiration stored as an absolute time, represented in terms of milliseconds since the beginning of the epoch. |
static long |
ANY
Used by the requestor to indicate that there is no particular lease time desired, and that the grantor of the lease should supply a time that is most convenient for the grantor. |
static int |
DURATION
The serialized form of the lease will convert the time of lease expiration into a duration (in milliseconds) from the time of serialization. |
static long |
FOREVER
Used to request a lease that never expires. |
| Method Summary | |
boolean |
canBatch(Lease lease)
Returns a boolean indicating whether or not the lease given as a parameter can be batched (placed in the same LeaseMap) with the current lease. |
void |
cancel()
Used by the lease holder to indicate that it is no longer interested in the resource or information held by the lease. |
LeaseMap |
createLeaseMap(long duration)
Creates a Map object that can contain leases whose renewal or cancellation can be batched, and adds the current lease to that map. |
long |
getExpiration()
Returns a long that indicates the time that the
lease will expire. |
int |
getSerialFormat()
Returns the format that will be used to serialize the lease. |
void |
renew(long duration)
Used to renew a lease for an additional period of time, specified in milliseconds. |
void |
setSerialFormat(int format)
Sets the format to use when serializing the lease. |
| Field Detail |
public static final long FOREVER
public static final long ANY
public static final int DURATION
public static final int ABSOLUTE
| Method Detail |
public long getExpiration()
long
that indicates the time that the
lease will expire. This time is represented as
milliseconds from the beginning of the epoch, relative to the local
clock.
long
that indicates the time that the
lease will expirepublic void cancel() throws UnknownLeaseException, RemoteException
UnknownLeaseException
- the lease being cancelled is unknown
to the lease grantor
RemoteException
public void renew(long duration) throws LeaseDeniedException, UnknownLeaseException, RemoteException
duration
- the requested duration in milliseconds
LeaseDeniedException
- the lease grantor is unable or
unwilling to renew the lease
UnknownLeaseException
- the lease being renewed is unknown
to the lease grantor
RemoteException
public void setSerialFormat(int format)
format
- DURATION or ABSOLUTEgetSerialFormat()
public int getSerialFormat()
setSerialFormat(int)
public LeaseMap createLeaseMap(long duration)
duration
- the duration to put into a Long and use as the
value for the current lease in the created LeaseMap
public boolean canBatch(Lease lease)
lease
- the Lease to be evaluated
|
|||||||||||
| PREV CLASS NEXT CLASS | FRAMES NO FRAMES | ||||||||||
| SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |


Here we use default bindings. Instead of explicitly telling idleTimer which element to bind to, it assumes document.
Some previous versions had issues mixing default binding with explicit calling on document.
This should no longer be the case. To test I've added 2 sets of buttons to show that they can be mixed.
The background color changes to show that it is returning a jQuery object


Quickstart
Hello World
With InfraBox you can execute a graph of jobs. Each job in the graph can be either a Docker container or multiple container (docker-compose)
In this quickstart quide we will show you some first steps to execute your workflow with InfraBox.
Preparation
-
First you should install infraboxcli:
pip install infraboxcli
You can use it to run your jobs on your local machine or push your workflows to InfraBox to offload work from your local machine:
-
Next create a new empty directory and cd into it:
mkdir tutorial cd tutorial
-
Let's now create a "hello world" project. We would like to execute a workflow which contains only one job and it should echo "hello world". In InfraBox everything runs in a Docker container. So we first have to create a Dockerfile like this:
FROM alpine CMD echo "hello world"
The file is quite simple. All the container does is printing "hello world" when it's started.
-
To be able to use InfraBox or the CLI to run your container you additionally have to create a file named infrabox.json in your root directory. It will contain all the information InfraBox requires to execute your workflow. A simple file with one job could look like this:
{ "version": 1, "jobs": [{ "type": "docker", "name": "example1", "docker_file": "Dockerfile", "build_only": false, "resources": { "limits": { "cpu": 1, "memory": 1024 } } }] }
That's all you need. Now simply execute infrabox run and you will see that first the container is build and then executed. To be honest you could have done that as well with docker build and docker run yourself. The next sections will show you some more complicated examples.
Dependencies
InfraBox becomes quite powerful as soon as you need to run multiple jobs which depend on each other. So let's have a quick look at a producer/consumer example in which one job produces a file and another job reads the file.
Example
Now we need two Dockerfiles, one for the producer (Dockerfile_producer):
FROM alpine
CMD echo "hello world" > /infrabox/output/data.txt
And one for the consumer (Dockerfile_consumer):
FROM alpine
CMD cat /infrabox/inputs/producer/data.txt
As you can see the producer writes the string "hello world" into a file /infrabox/output/data.txt. The directory /infrabox/output is special. Every file a job writes into this directory can be accessed by dependent jobs. The data will be accessible by the dependend jobs at /infrabox/inputs/<job_name>/. For more details how dependencies work see here.
Last thing to do is to tell InfraBox the dependency between the two jobs. For this we create the infrabox.json like this:
{
"version": 1,
"jobs": [{
"type": "docker",
"name": "producer",
"docker_file": "Dockerfile_producer",
"build_only": false,
"resources": { "limits": { "cpu": 1, "memory": 1024 } }
}, {
"type": "docker",
"name": "consumer",
"docker_file": "Dockerfile_consumer",
"build_only": false,
"resources": { "limits": { "cpu": 1, "memory": 1024 } },
"depends_on": ["producer"]
}]
}
As you can see we now have two jobs defined and the consumer depends on the producer. With this you can already model quite complex workflows in which every job can be its own container.
Tutorial: A NodeJS Project
Set up a local project
In this tutorial we will show you some of InfraBox's features. We will set up a simple Node.js project and extend it in the following sections.
git clone TODO
Using infraboxcli
Once you have infraboxcli installed, type infrabox --help. It will show you some basic information on what you can do with infraboxcli.
usage: infrabox [-h] [--host HOST] {push,graph,validate,list,run} ...
positional arguments:
{push,graph,validate,list,run}
sub-command help
push Push a local project to InfraBox
graph Generate a graph of your local jobs
validate Validate infrabox.json
list List all available jobs
run Run your jobs locally
optional arguments:
-h, --help show this help message and exit
--host HOST
If this worked without any problems, you're good to go to create your first InfraBox project.
A simple Node.js application
Now that we have a working version of infraboxcli installed we can continue and create a simple Node.js app. We'll use this only for demo purposes, so it will not have much functionality. To run the code locally make sure you have Node.js installed.
In an empty directory create the file package.json. It contains the relevant information about the Node.js project as well as the dependencies for running. Save the following to package.json.
{
"name": "infrabox-demo",
"version": "1.0.0",
"description": "The project will set up a very simple web server and we will execute some very basic tests.",
"main": "index.js",
"scripts": {
"test": "mocha spec.js"
},
"author": "",
"license": "MIT",
"dependencies": {
"express": "^4.15.2",
"supertest": "^3.0.0"
},
"devDependencies": {
"mocha": "^3.3.0"
}
}
Now run npm install. This will download all the required dependencies and save them to the node_modules directory.
Next step is to write the actual application. Create a file called index.js and copy & paste the below code:
var express = require('express');
var app = express();
app.get('/', function (req, res) {
res.send('Hello World!');
});
var server = app.listen(8080, function () {
console.log('Example app listening on port 8080!');
});
module.exports = server;
The example contains a very simple web server which just returns "Hello World!". If you now run node index.js it should output:
Example app listening on port 8080!
You may now open your browser and go to http://localhost:8080. You should now see the text "Hello World!". Congratulations, you have set up a simple Node.js application. Next we will add some tests to check if our web server really works the way we expect it. Create the file spec.js in the root folder of your project and paste this code:
var request = require('supertest');
describe('loading express', function () {
var server;
beforeEach(function () {
server = require('./index');
});
afterEach(function () {
server.close();
});
it('responds to /', function testSlash(done) {
request(server)
.get('/')
.expect(200, done);
});
it('404 everything else', function testPath(done) {
request(server)
.get('/foo/bar')
.expect(404, done);
});
});
The tests simply start the server and check whether the server returns the status 200 for "/" and 404 for "/foo/bar". You can now run the tests with npm test. Both tests should succeed.
Create a Dockerfile
Next we’re going to create a Dockerfile. InfraBox uses Docker for all jobs. So for everything you want to run on InfraBox you need at least a very simple Dockerfile. If you're already using Docker for your projects you probably need no or only minor adjustments to run them on InfraBox.
If you haven't used Docker containers yet you should have a look at the Docker documentation. For your first steps especially the Docker Getting Started Guide will be very helpful to understand how to set up your project using containers.
Now create an directory infrabox and in this directory create the file Dockerfile and paste this code into it:
# Use nodejs 6
FROM node:6-alpine
# Copies our code into the container
COPY . /project
WORKDIR /project
# Entrypoint of the container
ENTRYPOINT /project/infrabox/entrypoint.sh
As you see in the above Dockerfile we set the entrypoint of the container to a entrypoint.sh. This script will be executed when the container is started by InfraBox. So everything you want to run should be placed in this file. For your example application create the file entrypoint.sh in the infrabox directory next to the Dockerfile like this:
#!/bin/sh
set -e
echo "## Install dependencies"
export NPM_CONFIG_LOGLEVEL=warn # to reduce log output
npm install
echo "## Run tests"
npm test
The script must be executable, so make sure it has the propper permissions and run chmod +x infrabox/entrypoint.sh.
docker build -f infrabox/Dockerfile -t test-app .
And then running it:
docker run test-app
The output should be similar to:
## Install dependencies
npm WARN<EMAIL_ADDRESS>No repository field.
## Run tests
><EMAIL_ADDRESS>test /project
> mocha spec.js
loading express
Example app listening on port 8080!
✓ responds to /
✓ 404 everything else
2 passing (120ms)
As you can see the script installs our dependencies and starts the tests. You can try this yourself locally by first building the container.
Now we have a simple Node.js application which we validate with our simple Mocha tests in a Docker container. Next is to set up the project for using infraboxcli.
Run it with infraboxcli
Now as we can run our project within a Docker container we can use InfraBox to run it for you. As InfraBox needs to know which Docker container to run (you may have multiple in the same project), you have to create a file called infrabox.json in the root directory of your project. It contains all the information about which Docker containers should be run and what their dependencies are. We will talk about job dependencies in a later part. For now paste this code into the file:
{
"version": 1,
"jobs": [{
"name": "tests",
"type": "docker",
"resources": { "limits": { "cpu": 1, "memory": 1024 } },
"docker_file": "infrabox/Dockerfile",
"build_only": false
}]
}
For some more details about the structure of the infrabox.json and all the possible options see here.
That's all you need. You may now run infrabox list to list all the jobs in your project. As we only have one job set up it should only show you "tests".
Note: You can simply use infrabox run to run your jobs. It will build the container we created above and run it. See here for more information about how to run jobs locally.
Push to InfraBox
In the previous step we have set up a local project and used infraboxcli to run it. Now it's time to make use of the InfraBox infrastructure and run the project there. In general there are two possibilities to do this. You can either create a GitHub repository and connect it to InfraBox. Every time you push to the repository InfraBox will get notified about new changes, checkout your code and run all your jobs. See here on how to set up your project with Github. In this tutorial we use the second option without a GitHub Repository. You can simply use infraboxcli to push your jobs to InfraBox. The CLI will zip your local directory, upload it to InfraBox and execute all your jobs defined in infrabox.json.
To be able to push your jobs you first have to create a project in the InfraBox Dashboard. See here on how to do it. Additionally you have to create an Authentication Token which the CLI will use to authenticate your requests. This prevents other people from pushing to your project. You can revoke the tokens at any time. See here on how to create them.
So if you have your project and Authentication Token created you only need to run:
export INFRABOX_CLI_PROJECT_ID=<YOUR_PROJECT_ID>
export INFRABOX_CLI_TOKEN=<YOUR_AUTH_TOKEN>
infrabox push
That's it, you can now offload your jobs to the InfraBox infrastructure. Go to the Dashboard and see your job running. You may also use --show-console to print the console output of your jobs. See here for more details.
Use the cache
InfraBox offers you the possibility to cache some files between runs. This can be very useful for data which changes rarely and is time consuming to install. In our example our node_modules directory is a perfect fit. So we don't have to wait every run to download and install all dependencies.
InfraBox mounts a cache directory /infrabox/cache into every container. Every data which is copied into this directory will be available in the next run of the job. See here for some more details.
We modify our infrabox/entrypoint.sh file to make use of the cache:
#!/bin/sh
set -e
cd project
# Here we load the cached node_modules directory
echo "## Prepare cache"
mkdir -p /infrabox/cache/node_modules
cp -r /infrabox/cache/node_modules /project
echo "## Install dependencies"
export NPM_CONFIG_LOGLEVEL=warn # to reduce log output
npm install
# Copy updated node_modules back to cache
echo "## Copy to cache"
rm -rf /infrabox/cache/node_modules
cp -r /project/node_modules /infrabox/cache/node_modules
echo "## Run tests"
npm test
As you see we simply copy our node_moules directory to /infrabox/cache after we installed it. So we don't have to download all our npm dependencies again in the next run. See here for more details on caching.
Multi Container Tests
So far we started our web server within our tests. So we had one docker container which contains the tests and the server. This image we would usually not deploy to our production infrastructure, because there's not good reason to put test code and all the test dependencies into the container.
To solve the problem we can split our container into two different containers. One which contains only our server and the second one the tests. The first container can now be set up in a way it would also run on a production infrastructure. This way we really test what we run later on.
But for testing it we now have to start two containers. For this InfraBox offers the possibility to run docker-compose jobs. With this you can create a docker-compose file and run it like one job. See TODO for more details.
TODO the code is available here...
First we create a second Dockerfile in the root directory of our project. With this we build our image for the server without any tests. This image could later also be used in a production environment and should therefore contain only minimal dependencies to run the server.
# Use nodejs 6
FROM node:6-alpine
# Copy only necessary files
COPY package.json /project/package.json
COPY entrypoint.sh /project/entrypoint.sh
COPY index.js /project/index.js
WORKDIR /project
# Entrypoint of the container
ENTRYPOINT /project/entrypoint.sh
For running the web server we only need a few files. Be careful, we also use a second entrypoint.sh for starting a server. This file should be located in the root directory of the project and look like this (we did not add caching to keep the example simpler):
#!/bin/sh
set -e
echo "## Install dependencies"
export NPM_CONFIG_LOGLEVEL=warn # to reduce log output
npm install
echo "## Start web server"
node index.js
Now we have got a container which starts our web server, but we also need a second container which contains the tests. We use infrabox/entrypoint.sh as the entrypoint for our tests container. For this we'll modify it slightly (we remove the caching to simplify the example):
#!/bin/sh
set -e
echo "## Install dependencies"
export NPM_CONFIG_LOGLEVEL=warn # to reduce log output
npm install
# Wait until the web server is up and running before we start our tests
until $(curl --output /dev/null --silent --head --fail http://server:8080/); do
>&2 echo "Web server host is unavailable - sleeping"
sleep 1
done
echo "## Run tests"
npm test
As we now run the web server in a separate container we have to wait until the container has started up and the server is able to serve requests. After this is the case we can start our tests.
Obviously we also have to modify our tests to connect to the web server instead of starting the server in the tests. The modified tests in spec.js now look like this:
var request = require('supertest');
var server = request.agent('http://server:8080')
describe('loading express', function () {
it('responds to /', function testSlash(done) {
server
.get('/')
.expect(200, done);
});
it('404 everything else', function testPath(done) {
server
.get('/foo/bar')
.expect(404, done);
});
});
With the previous changes we now have two containers, one for the web server and one for the tests. Last step is to bring them together with the help of docker-compose. For more details about docker-compose please look here. Create a file infrabox/docker-compose.yml like this:
version: "2"
services:
server:
build:
context: ..
dockerfile: Dockerfile
test:
build:
context: ..
dockerfile: infrabox/Dockerfile
links:
- server
As you can see we use our two Dockerfiles for the server and the tests. The test service also needs a link to the server so the tests are able to access the server at http://server:8080.
We are almost done. Last step is to modify infrabox.json in a way that it does not start our old docker container anymore, but now uses docker-compose to run both our containers.
{
"version": 1,
"jobs": [{
"name": "tests",
"type": "docker-compose",
"resources": { "limits": { "cpu": 1, "memory": 1024 } },
"docker_compose_file": "infrabox/docker-compose.yml"
}]
}
We changed the type of the job to docker-compose and instead of docker_file we use docker_compose_file.
This is it. We can now run our tests again with either infrabox run on our local machine or with infrabox push on the InfraBox infrastructure.
Builds & Configuration
Workflow Configuration
If you want to run jobs on InfraBox you have to create a file called infrabox.json in the root directory of your project. It tells InfraBox what jobs are part of the project and which dependencies between the jobs exist. The basic structure of the file is as follows:
{
"version": 1,
"jobs": [
...
]
}
| Name | Required | Type | Description |
|---|---|---|---|
| version | true | number | Currently only valid value is 1. |
| jobs | true | array of job types | A list of the actual jobs to run. It can be either |
docker
The job type docker is one of the most important jobs. You can use it to run any Docker container you like.
{
"type": "docker",
"name": "build",
"docker_file": "infrabox/build-and-test/Dockerfile"
"resources": { "limits": { "cpu": 1, "memory": 1024 } },
"build_only": false,
"depends_on": ["other_job_name"],
"environment": { ... },
"security": {
"scan_container": false
}
}
| Name | Required | Type | Description |
|---|---|---|---|
| type | true | string | Has to be "docker" to run a single Docker container |
| name | true | string | Name of the job |
| docker_file | true | string | Path to the Dockerfile |
| resources.limits.cpu | true | integer | Specify the number of CPUs to be used for the job. Value must be an integer. |
| resources.limits.memory | true | integer | Specify the number of MiB of RAM to be used for the job. Value must be an integer and at least 128. |
| timeout | false | integer | Timeout in seconds after which the job should be killed. Timeout starts when the job is set to running. Default is 3600 (1 hour) |
| build_only | true | boolean | If set to true the container will only be build but not run. Use it if you only want to build a container and push it to a registry. See here for how to push to a docker registry. |
| depends_on | false | array of job names | Jobs may have dependencies. You can list all jobs which should finish before the current job may be executed. |
| environment | false | object | Can be used to set environment variables for the job. See Environment Variables for more details. |
When InfraBox builds a docker container the docker context is always the directory in which the infrabox.json is stored. So when you copy files in your Dockerfile the path must be relative to the infrabox.json file.
Suppose we have the following files in our project:
/project/
-
src/
Dockerfile
test.py
infrabox.json
And our Dockerfile looks like this:
FROM alpine:3.4
COPY src/test.py /usr/bin/test.py
CMD /usr/bin/test.py
As you can see the COPY uses src/test.py and is therefore relative to the root directory of the project and not the Dockerfile.
docker-compose
Sometimes it's useful to run multiple Docker containers, i.e. if you want to test your web application you may want to start the database, web server and the actual tests in separate Docker containers. For this docker-compose jobs can be used. Instead of specifying only one Docker container you can give an entire docker-compose file.
The job ends as soon as one of the container stops. If it stops with an error code other than 0 the job is considered to be failed, else it finished succesfully.
An example docker-compose job definition:
{
"type": "docker-compose",
"name": "test",
"docker_file": "infrabox/test/docker-compose.yml"
"resources": { "limits": { "cpu": 1, "memory": 1024 } },
"depends_on": ["other_job_name"],
"environment": { ... }
}
| Name | Required | Type | Description |
|---|---|---|---|
| type | true | string | Has to be "docker-compose" to run multiple containers |
| name | true | string | Name of the job |
| docker_compose_file | true | string | Path to the docker-compose.yaml |
| resources.limits.cpu | true | integer | Specify the number of CPUs to be used for the job. Value must be an integer. |
| resources.limits.memory | true | integer | Specify the number of MiB of RAM to be used for the job. Value must be an integer and at least 128 |
| timeout | false | integer | Timeout in seconds after which the job should be killed. Timeout starts when the job is set to running. Default is 3600 (1 hour) |
| depends_on | false | array of job names | Jobs may have dependencies. You can list all jobs which should finish before the current job may be executed. See here for more details about using dependencies |
| environment | false | object | Can be used to set environment variables for the job. See Environment Variables for more details. |
git
It's not necessary to have all your job definitions in your own project. With the git job type you can include job definitions for any accessible git repository.
An example git job definition:
{
"type": "git",
"name": "some-external-jobs",
"git_url": "https://github.com/InfraBox/examples.git",
"commit": "master",
"depends_on": ["other_job_name"]
}
| Name | Required | Type | Description |
|---|---|---|---|
| type | true | string | Has to be "git" to include a workflow from a repository |
| name | true | string | Name of the job |
| clone_url | true | string | The url used to clone the repository. |
| commit | true | string | Can be any identifier which git can checkout. So a branch name, commit sha1 or tag. |
| depends_on | false | array of job names | Jobs may have dependencies. You can list all jobs which should finish before the current job may be executed. See here for more details about using dependencies |
| environment | false | object | Can be used to set environment variables for the job. See Environment Variables for more details. |
workflow
If you have many jobs you might want to structure them in different files.
An example job definition:
{
"type": "workflow",
"name": "deploy",
"infrabox_file": "deployments.json",
"depends_on": ["test"]
}
| Name | Required | Type | Description |
|---|---|---|---|
| type | true | string | Has to be "workflow" to include a workflow from a repository |
| name | true | string | Name of the job |
| infrabox_file | true | string | Path to another infrabox.json file in the local project |
| depends_on | false | array of job names | Jobs may have dependencies. You can list all jobs which should finish before the current job may be executed. See here for more details about using dependencies |
| environment | false | object | Can be used to set environment variables for the job. See Environment Variables for more details. |
Job Dependencies
With InfraBox you may execute arbitray complex job graphs.
Define Dependencies
To model dependencies between jobs you simply use depends_on in the job description. As an example we create tree jobs A, B and C. C depends on A and B.
{
"version": 1,
"jobs": [{
"name": "A",
...
}, {
"name": "B",
...
}, {
"name": "C",
...
"depends_on": ["A", "B"]
}]
}
Jobs A and B would start in parallel and C would only start if A and B succeeded successfully. If either of the parent jobs failed C would not be started at all. You may use dependencies with all available job types.
Transfer data between jobs
If you have defined dependencies between your jobs you can also transfer data between them. The parent job may produce some output which the child job may access.
Every InfraBox job has automatically an output folder mounted under /infrabox/output. All data which is written into this directory will be accessible by the direct child jobs. The data is made accessible in the child in the /infrabox/inputs/<parent_job_name> directory.
Suppose we have the following job definition
{
"version": 1,
"jobs": [{
"name": "parent",
...
}, {
"name": "child",
...
"depends_on": ["parent"]
}]
}
If the the parent job would create the file /infrabox/output/hello_world.txt then the child job would be able to access it under /infrabox/inputs/parent.
Environment Variables
With InfraBox you have two ways of setting environment variables for your jobs. The easiest way is to add it to your job definition like this:
{
"type": "docker",
...
"environment": {
"ENV_VAR_1": "some value",
"ENV_VAR_2": "some other value
}
}
You may use this approach to store values which don't contain and secret information like passwords, because everybody could read it in you repository.
If you want to store secret values you should add them first in the InfraBox Dashboard:
-
Login to the InfraBox Dashboard
-
Click on projects on the top
-
Click on the project for which you wan to set an environment variable
-
Click on "Edit Project"
-
Navigate to the "Environment" tab
-
Insert a name and value
-
Click on the "+" sign
With this you now have created an environment variable which you can use in your jobs without writing the value into a text file.
To use it in your job reference it in your job definition like this:
{
"type": "docker",
...
"environment": {
"ENV_VAR_1": { "$secret": "NAME_OF_ENV_VAR_IN_DASHBOARD" }
}
}
In your job the secret value will then be available as the environment variable ENV_VAR_1.
Using Image Registries
The docker images which have been build can also be pushed to a docker registry by InfraBox. You would add a deployment to your job:
{
"type": "docker",
...
"deployments": [{
"type": "docker-registry",
"host": "<my_registry>:5000",
"repository": "repo-name",
"username": "your_username",
"password": { "$secret": "SECRET_NAME_FOR_YOUR_PASSWORD" }
}]
}
Deployments are currently only supported for docker job types. username and password are optional if you don't have any authentication setup for your registry.
Caching on InfraBox
Sometimes it's useful to keep some data from one run of a container to the next one. Maybe you have a nodejs project and don't want to install your dependencies every time. For such uses cases InfraBox mounts the directory /infrabox/cache into every container. Everything which you store in this directory will be available at the same place in the next run. So for your nodejs project you could simply copy your node_modules directory in there.
Create Badges
With InfraBox you can easily create one or mutiple badges like or with your custom information. To create a badge simply create a json file like this:
{
"subject": "build",
"status": "failed",
"color": "red"
}
and save it to /infrabox/upload/badges/badge.json. You can also save multiple files with different names in this directory. For every file a separate badge will be created.
Dynamic Workflows
TODOCreate an Upload Project
Upload project can be used for executing workflows without storing them in a git repository.
-
Login to the InfraBox Dashboard
-
Click on projects on the top
-
Click on "Add New Project"
-
Enter a name of the project
-
Click the "+" button
Now you should see your project in your project list at the top.
To upload workflows to your projects see TODO Upload a workflow to InfraBox.
-
Refresh the page - TODO check if this is still needed
Connect a Github Repository
Connecting a Github Repository is very simple.
-
Login to the InfraBox Dashboard
-
Select Settings at the top
-
Select My Github Repositories
-
Click on the repository you want to connect
After connecting a repository InfraBox will be notified about every new commit. This will automatically trigger a new build for the project.
Create Auth Token
-
Login to the InfraBox Dashboard
-
Select Settings at the top
-
Select Authentication Tokens
-
Click on "Add new token"
-
Give it a name
-
Select the scope
-
Click "Add"
-
You should now see the token next to its name. You may use the token to push workflows or pull jobs


Work Experience
Freelancer designer. I have
worked on various projects
available on my portfolio
Education
BSc in Information Technology.
J.K.U.A.T
2016 - 2020
Secondary in Education
Senior Highway Nyahururu
2011 - 2015
Skills & Expertise
HTML
CSS
Networking
Javascript
Achievements
ALC Android basics
-Andela
Ccna Switching and Routing
-Cisco
Cloud Cloud Computing
-IBM
Contact Info
☎<PHONE_NUMBER>
☎ pwachira900@gmail.com


Getting lambda to work with dynamodb and elasticache
This week I spent so much time trying to get lambda
to work with dynmodb
and elasticache
. Everything worked well with lambda
and dynamodb
until I tried to integrate elasticache
.
While I was working with integrating elasticache
and lambda
, I created a VPC and put lambda
and elasticache
in the same VPC. I didn't realize that's when everything broke.  I was trying to debug why I couldn't connect to redis.
redis_name = os.environ.get('REDIS_NAME')
logger.debug('table name: {0}'.format(table_name))
logger.debug('redis name: {0}'.format(redis_name))
dynamo_client = boto3.resource('dynamodb', region_name=region)
rconn = redis.Redis(host=redis_name, port=6379, db=0)
dynamo_table = dynamo_client.Table(table_name)
I can see redis name
getting logged into cloudwatch logs but then lambda timeout. Finally, I used my brain and decided to comment redis.Redis
from the code. Then it hit me like a ton of bricks, it wasn't redis connection timeout but dynamodb.
After that debugging got easier, because placing lambda
into a VPC caused it to loose connection to the internet. In order to fix it, I had to re-create VPC with internetgateway and NAT so that lambda
can connect to the internet. Apparently, lambda
connects to the dynamodb over the internet. Who knew !


| Barstugan
et al. [
22]
|
Abdominal CT images: 16 × 16 |
− Grey-level co-occurrence matrix (GLCM)
− Local directional pattern (LDP)
− Grey-level run length matrix (GLRLM)
− Grey-level size zone matrix (GLSZM)
− Discrete wavelet transform (DWT)
|
Support vector machine (SVM) |
99.68 |
|
32 × 32 |
|
|
99.37 |
|
48 × 48 |
|
|
99.64 |
|
64 × 64 |
|
|
97.28 |
| Basu
et al. [
23]
|
Chest X-ray images |
Domain extension transfer learning (DETL) |
Machine learning (ML)
Deep learning (DL)
|
95.3% ± 0.02 |
| Ozturk
et al. [
24]
|
Raw chest X-ray images: |
DarkCovidNet model |
Deep learning (DL) |
98.08 |
|
− Binary classification (COVID versus no-findings) |
|
|
|
|
− Multi-class classification (COVID versus no-findings versus pneumonia) |
|
|
87.02 |
| Elasnaoui
et al. [
25]
|
X-ray and CT images |
Models: Inception_ResNet_V2 |
Multilayer perceptron classifier |
92.18 |
|
DenseNet201 |
|
|
88.09 |
|
Resnet50 |
|
|
87.54 |
|
MobileNet_V2 |
|
|
85.47 |
|
Inception_V3 |
|
|
88.03 |
|
VGG16 |
|
|
74.84 |
|
VGG19 |
|
|
72.52 |
| Proposed study |
DNA sequences: |
− Discrete Fourier transform |
K-nearest neighbor algorithm
|
100 |
|
|
− Discrete cosine transform |
|
|
|
− COVID-19 versus SARS-CoV |
− Seven moment invariants |
|
|
|
− COVID-19 versus MERS-CoV |
|
|
100 |
|
− COVID-19 versus SARS-CoV versus MERS-CoV |
|
|
100 |
|
− COVID-19 versus SARS-CoV |
|
Trainable cascade-forward back propagation neural network |
100 |
|
− COVID-19 versus MERS-CoV |
|
|
98.34 |
|
− COVID-19 versus SARS-CoV versus MERS-CoV |
|
|
98.89 |


---
title: Home
photos:
- image: /uploads/2020-09.jpg
title: "Mindset: The New Psychology of Success"
caption: "2020 #9"
captionfull: "\
| Characteristic |
Fixed Mindset |
Growth Mindset |
| Fundamental Assumption |
Intelligence is static |
Intelligence can be developed |
| Impact |
Leads to a desire to look smart and therefore tendencies to... |
Leads to a desire to learn and therefore tendencies to... |
| Challenges |
Avoid challenges |
Embrace challenges |
| Obstacles |
Get defensive or give up easily |
Persist in the face of setbacks |
| Effort |
See effort as fruitless or worse |
See effort as the path to mastery |
| Criticism |
Ignore useful negative feedback |
Learn from criticism |
| Success of Others |
Feel threatened by the success of others |
Find lessons and inspiration in the success of others |
| As a result... |
May plateau early and achieve less than their full potential |
Reach ever-higher levels of achievement |
To adopt a growth mindset:
- Embrace your fixed mindset. We are a mix of growth and fixed mindsets.
- Be aware of your fixed-mindset triggers. When does it surface? When you're pressured? When you're challenged?
- Give your fixed-mindset persona a name. This helps with internal communication.
- Educate your fixed-mindset persona. Acknowledge him/her when he/she emerges, then show him/her the growth-mindset way of doing things.
"
- image: /uploads/2020-08.jpg
title: "Measure What Matters: How Google, Bono, and the Gates Foundation Rock the World with OKRs"
caption: "2020 #8"
captionfull: "\
- OKRs stand for Objectives and Key Results. Objectives are tangible and unambiguous goals, and Key Results are measurable milestones that will advance objectives. They are used by successful companies like Google, Intel, Amazon, and Facebook.
- OKRs are shared publicly. This (a) encourages ownership and commitment, (b) creates alignment to top-level objectives, (c) promotes cross-departmental interaction, and (d) enables the company to learn what all frontliners think is important for the company.
- There are two types of OKRs. Committed OKRs are goals that must be achieved, while Aspirational OKRs are super-stretch goals that allow you to dream big.
- OKRs work hand-in-hand with continuous performance management (CPM), which enable real-time tracking of progress and real-time feedback.
- The tool for CPM is CFRs: Conversations, Feedback, and Recognition. This entails (a) 360-degree feedback, (b) performance based and horizontal recognition to crowdsource meritocracy, and (c) conversations on (i) goal setting/reflection, (ii) two-way coaching, (iii) career discussions, and (iv) lightweight performance reviews.
FYI, the Resources section has a lengthier summary and a decent guide on implementing OKRs in your organisation."
- image: /uploads/2020-07.jpg
title: "slide:ology: The Art and Science of Creating Great Presentations"
caption: "2020 #7"
captionfull: "\
- We don’t train ourselves in design, but most of us are assessed and even promoted based on our ability to communicate visually.
- Create audience personas and keep them to remember who you’re connecting with.
- Don’t brainstorm with your presentation software. It isn't built for that. Throw out as many ideas as possible on paper, then cut mercilessly - you only need one good one.
- Effective slide design hinges on three things: Arrangement (Contrast, Flow, Hierarchy, Unity, Proximity, and Whitespace), Visual Elements (Background, Colour, Text, and Images), and Movement (Timing, Pace, Distance, Direction, and Eye Flow).
- The three types of slides:
- Documents: Slides that contain more than 75 words, and are really meant for reading, not presenting.
- Teleprompters: Slides that contain 50 or so words. Presenters typically read off them in an unengaging fashion.
- Presentations: Slides that focus on the presenter, and the ideas and concepts they want to communicate. The slides reinforce the presenter's content visually instead of creating a distraction.
- Use template slides to govern alignment to your brand across the company. The broad categories:
- Segue: Branded Walk-ins, Titles, Transitions, and Q&A
- Content: Text, Text with Graphics, Quotes, and Charts & Tables
- Components: Grid, Colour Palette, Component Style, and Images Overview
- The Five Theses of the Power of a Presentation:
- Treat Your Audience As King
- Spread Ideas and Move People
- Help Them See What You're Saying
- Practice Design, Not Decoration
- Cultivate Healthy Relationships (with slides and the audience)
"
- image: /uploads/2020-06.jpg
title: "Scrum: The Art of Doing Twice the Work in Half the Time"
caption: "2020 #6"
captionfull: "\
Scrum, an approach that:
- Focuses on delivering value incrementally through regular product demos to key stakeholders for feedback.
- Works in Sprints, cycles of fixed duration to achieve tasks chosen by the team.
- Employs small teams (3-9 pax) that decide how many things they will do, and how they will do them.
- Emphasises process improvement to enhance team performance, not individual performance.
- Can be applied in any endeavour to improve performance and results.
Check out the Appendix for a detailed guide on implementing Scrum."
- image: /uploads/2020-05.jpg
title: "Raising an Amazing Child The Montessori Way"
caption: "2020 #5"
captionfull: "\
- Intelligence is not rare among human beings. It is found in children at birth. With the right stimulation, the development of reasoning and problem-solving skills can be nurtured in young children.

- Children should be encouraged to develop a high degree of independence and autonomy.
- Academic competition and accountability are not effective ways to motivate students to become well educated. They learn more effectively when school is seen as a safe, exciting, and joyful experience.
- There is a direct link between children’s sense of self-worth, empowerment, and self-mastery, and their ability to learn and retain new skills and information.
- Children learn best through hands-on experience, real-world application, and problem solving, rather than through rote learning and testing.
This book had many recommendations on parenting activities. Strongly recommended."
- image: /uploads/2020-04.jpg
title: "The Hundred-Page Machine Learning Book"
caption: "2020 #4"
captionfull: "\
Not so much a summary, but some thoughts:
- Understanding the theory of how machine learning algorithms work is essential for data scientists.
- Understanding the math enables a data scientist to go further - to design custom algorithms, which is increasingly important for solving complex problems.
- Machine learning isn't all about algorithms. Feature engineering is arguably more important.
- Don't stop at model evaluation and recommendation. Operationalise your models by learning how to deploy and scale them for effective and pervasive use.
"
- image: /uploads/2020-03.jpg
title: "The Chief Data Officer Handbook for Data Governance"
caption: "2020 #3"
captionfull: "\
- Data governance is the formulation of policy to optimise, secure, and leverage information as an enterprise asset by aligning the objectives of multiple functions.
- Successful data governance requires:
- Strong business ownership with IT support.
- Focus on critical data elements.
- Emphasis on data artifacts like business terms, business rules, policies, standards, and processes.
- Alignment around metrics and policy enforcement
- Celebration of quick wins with alignment around the long-term roadmap.
- Policies, Standards, and Processes must be articulated clearly.
- Policies are high-level statements on how data should be handled.
- Standards are detailed rules to implement a policy.
- Processes are specific instructions to implement a standard.
"
- image: /uploads/2020-02.jpg
title: "The Organized Mind: Thinking Straight in the Age of Information Overload"
caption: "2020 #2"
captionfull: "\
This book was full of little facts grouped (quite poorly) into a number of categories: home, social world, time, decision making, and business. These same facts were presented in a much more organised and holistic fashion in other books on psychology. If there was one theme that was common throughout the book, it was: externalise your memory, because your brain does not have enough RAM to remember everything. Put things like contacts, to-do lists, your schedule, decision making checklists, and so on into a cloud-enabled storage for access anywhere, anytime."
- image: /uploads/2020-01.jpg
title: "The Art of Running Faster: Improve Technique, Training, and Performance"
caption: "2020 #1"
captionfull: "\
\
- The six components of fitness are speed, suppleness, strength, stamina, skills, and psychology.
\
- Good technique: Run tall, relaxed, and balanced, falling into the next step; keep your head straight and still; pull with your arms; reach forward with your knees; keep your feet quick and quiet, landing on your forefeet.
\
- Vary your training routine with a long run, fartleks, intervals, and recovery runs.
\
- When nearing a race, train for feeling, not for fitness.
\
"
- image: /uploads/2019-28.jpg
title: "The Most Important Thing: Uncommon Sense for the Thoughtful Investor"
caption: "2019 #28"
captionfull: "\
\
- Paying below value lowers risk and increases return.
\
- Look for good buys, not good assets.
\
- Exploit the big swings: economies, markets, and emotions.
\
- Risk aversion and skepticism is healthy for markets.
 Focus on risk control.
\
- Practice defensive investing. Avoid the losers, and the winners will take care of themselves.
\
"
- image: /uploads/2019-27.jpg
title: "The Fitness Mindset: Eat for energy, Train for tension, Manage your mindset, Reap the results"
caption: "2019 #27"
captionfull: ""
- image: /uploads/2019-26.jpg
title: "What I Talk About When I Talk About Running"
caption: "2019 #26"
captionfull: ""
- image: /uploads/2019-25.jpg
title: "Nudge: Improving Decisions About Health, Wealth, and Happiness"
caption: "2019 #25"
captionfull: "\
\
- As a choice architect, you can influence behaviour. You can nudge.
\
- People need nudges for decisions that are difficult and rare, for which they don't get prompt feedback, and when they have trouble understanding the situation.
\
- In designing choices, we should structure incentives well, understand the relation between choices and outcomes, provide good defaults, give feedback on decisions, expect errors, and structure complex choices.
\
"
- image: /uploads/2019-24.jpg
title: "The Terrible and Wonderful Reasons Why I Run Long Distances"
caption: "2019 #24"
captionfull: "This was a cartoon book that was rather cynical about health and fitness. There wasn't much practical advice in it. Not recommended."
- image: /uploads/2019-23.jpg
title: "Born to Run: A Hidden Tribe, Superathletes, and the Greatest Race the World Has Never Seen"
caption: "2019 #23"
captionfull: "\
From the Tarahumara, we learn that:
\
\
- Running is in our blood. We run to survive, to feel, and to live.
\
- When we re-discover our love for running, we run well.
\
- Running barefoot (or close to it) is best for our legs/feet.
\
"
- image: /uploads/2019-22.jpg
title: "The CEO's Secret Weapon: How Great Leaders and Their Assistants Maximize Productivity and Effectiveness"
caption: "2019 #22"
captionfull: "\
This book is about how to be the best secretary possible. I read it to (1) acquire perspectives on being my own secretary to manage myself better and (2) learn how to serve others better. Here are the key roles to play:
The Ultimate PR Person
\
- Make your boss look good
- Reflect the boss' values in action
- Be service oriented
- Always be discreet
- Be diplomatic
- Practice good communication, with authority, competence, and clarity
- Be scrupulous about details
- Maintain a professional demeanor
- Upkeep good general knowledge (for small talk, when required)
The High-Performance Administrator
- Be good at general secretarial skills
- Organise yourself well
- Plan the boss' schedule carefully
- Be responsible and close the loop
- Learn to supervise well
- Understand company protocol and procedures
- Use your creativity
The Expert Executor
- Anticipate the boss' own needs
- Be resourceful
- Make decisions effectively
- See the big picture
- Understand the boss' intent
- Maintain high energy
- Be focused
- Be persistent and resilient
- Be versatile and adaptable
\
"
- image: /uploads/2019-21.jpg
title: "The Art of Data Science: A Guide for Anyone Who Works with Data"
caption: "2019 #21"
captionfull: "\
The Epicycle of Analysis:
- Stating and Refining the Question
- Exploring the Data
- Building Formal Statistical Models
- Interpreting the Results
- Communicating the Results
The Three Core Activities (applicable to all activities above):
- Setting expectations
- Collecting or generating information
- Matching expectations to the information/data. If there is a mismatch, either the expectations, model, or interpretations were wrong.
"
- image: /uploads/2019-20.jpg
title: "Understanding the Chief Data Officer : How Leading Businesses Are Transforming Themselves with Data"
caption: "2019 #20"
captionfull: "A good introductory read. It's pretty short, so there won't be a summary of this."
- image: /uploads/2019-19.jpg
title: "Hadoop Illuminated"
caption: "2019 #19"
captionfull: ""
- image: /uploads/2019-18.jpg
title: "Big Data Now: 2012 Edition"
caption: "2019 #18"
captionfull: ""
- image: /uploads/2019-17.jpg
title: "The Minto Pyramid Principle: Logic in Writing, Thinking, & Problem Solving"
caption: "2019 #17"
captionfull: ""
- image: /uploads/2019-16.jpg
title: "The Power of Full Engagement: Managing Energy, Not Time, Is the Key to High Performance and Personal Renewal"
caption: "2019 #16"
captionfull: ""
- image: /uploads/2019-15.jpg
title: "Hyperfocus: How to Be More Productive in a World of Distraction"
caption: "2019 #15"
captionfull: ""
- image: /uploads/2019-14.jpg
title: "The Circadian Code: Lose Weight, Supercharge Your Energy, and Transform Your Health from Morning to Midnight"
caption: "2019 #14"
captionfull: ""
- image: /uploads/2019-13.jpg
title: "When: The Scientific Secrets of Perfect Timing"
caption: "2019 #13"
captionfull: ""
- image: /uploads/2019-12.jpg
title: "Brief Answers to the Big Questions"
caption: "2019 #12"
captionfull: ""
- image: /uploads/2019-11.jpg
title: "The Whole-Brain Child: 12 Revolutionary Strategies to Nurture Your Child's Developing Mind, Survive Everyday Parenting Struggles, and Help Your Family Thrive"
caption: "2019 #11"
captionfull: ""
- image: /uploads/2019-10.jpg
title: "Buyology: Truth and Lies About Why We Buy and the New Science of Desire"
caption: "2019 #10"
captionfull: ""
- image: /uploads/2019-09.jpg
title: "The Dictator's Handbook: Why Bad Behavior is Almost Always Good Politics"
caption: "2019 #9"
captionfull: ""
- image: /uploads/2019-08.jpg
title: "Essentialism: The Disciplined Pursuit of Less"
caption: "2019 #8"
captionfull: ""
- image: /uploads/2019-07.jpg
title: "Brain Rules for Baby: How to Raise a Smart and Happy Child from Zero to Five"
caption: "2019 #7"
captionfull: ""
- image: /uploads/2019-06.jpg
title: "New Frontiers in Technical Analysis: Effective Tools and Strategies for Trading and Investing"
caption: "2019 #6"
captionfull: ""
- image: /uploads/2019-05.jpg
title: "Intermarket Trading Strategies"
caption: "2019 #5"
captionfull: ""
- image: /uploads/2019-04.jpg
title: "Algorithmic Trading: Winning Strategies and Their Rationale"
caption: "2019 #4"
captionfull: ""
- image: /uploads/2019-03.jpg
title: "Fundamentals of the Futures Market"
caption: "2019 #3"
captionfull: ""
- image: /uploads/2019-02.jpg
title: "A Complete Guide to Volume Price Analysis"
caption: "2019 #2"
captionfull: ""
- image: /uploads/2019-01.jpg
title: "Quantitative Trading: How to Build Your Own Algorithmic Trading Business"
caption: "2019 #1"
captionfull: ""
---
{% for photo in page.photos %}
- " }}')">
{% endfor %}


JavaScript is disabled on your browser.
Skip navigation links
Overview
Package
Class
Use
Tree
Deprecated
Index
Help
Prev
Next
Frames
No Frames
All Classes
Hierarchy For All Packages
Package Hierarchies:
algorithms
,
algorithms.cycles
,
algorithms.paths
,
algorithms.trees
,
data
,
entities
,
entities.cycles
,
entities.paths
,
entities.trees
,
experiments
,
factorization
,
util
Class Hierarchy
java.lang.
Object
factorization.
Band
factorization.
Binary_Partitioning
experiments.
BinaryStar_Equijoin
util.
Common
algorithms.
Configuration
data.
Database_Query_Generator
data.
BinaryRandomPattern
data.
Cycle_HeavyLightPattern
util.
DatabaseParser
algorithms.paths.
DP_Anyk_Iterator
algorithms.paths.
DP_Part
algorithms.paths.
DP_All
algorithms.paths.
DP_Eager
algorithms.paths.
DP_Lazy
algorithms.paths.
DP_Quick
algorithms.paths.
DP_Take2
algorithms.paths.
DP_Recursive
algorithms.paths.
Path_Batch
algorithms.paths.
Path_BatchHeap
algorithms.paths.
Path_BatchSorting
entities.paths.
DP_Decision
(implements java.lang.
Comparable
<T>)
entities.paths.
DP_DecisionSet
entities.paths.
DP_Problem_Instance
entities.paths.
DP_Path_Equijoin_Instance
entities.paths.
DP_Path_ThetaJoin_Instance
entities.paths.
DP_Solution
entities.paths.
DP_Prefix_Solution
(implements java.lang.
Comparable
<T>)
entities.paths.
DP_Suffix_Solution
(implements java.lang.
Comparable
<T>)
entities.paths.
Path_Query_Solution
(implements java.lang.
Comparable
<T>)
algorithms.paths.
DP_Solution_Iterator
entities.paths.
DP_State_Node
factorization.
Equality
entities.
Join_Predicate
util.
Measurements
factorization.
Multiway_Partitioning
algorithms.cycles.
NPRR
algorithms.cycles.
NPRR_Sort
experiments.
Path_Equijoin
entities.paths.
Path_Equijoin_Query
experiments.
Path_Inequalities
experiments.
Path_Inequalities_Disjunction
entities.paths.
Path_ThetaJoin_Query
entities.
Relation
factorization.
Shared_Ranges
algorithms.cycles.
SimpleCycle_Anyk_Iterator
experiments.
SimpleCycle_Equijoin
entities.cycles.
SimpleCycle_Equijoin_Query
entities.trees.
Star_Equijoin_Query
algorithms.trees.
TDP_Anyk_Iterator
algorithms.trees.
TDP_Part
algorithms.trees.
TDP_All
algorithms.trees.
TDP_Eager
algorithms.trees.
TDP_Lazy
algorithms.trees.
TDP_Take2
algorithms.trees.
TDP_Recursive
algorithms.trees.
Tree_Batch
algorithms.trees.
Tree_BatchSorting
entities.trees.
TDP_Decision
(implements java.lang.
Comparable
<T>)
entities.trees.
TDP_DecisionSet
entities.trees.
TDP_Problem_Instance
entities.trees.
TDP_BinaryStar_Equijoin_Instance
entities.trees.
TDP_Star_Equijoin_Instance
entities.trees.
TDP_Solution
entities.trees.
TDP_Prefix_Solution
(implements java.lang.
Comparable
<T>)
entities.trees.
TDP_Subtree_Solution
(implements java.lang.
Comparable
<T>)
entities.trees.
Tree_Query_Solution
(implements java.lang.
Comparable
<T>)
entities.trees.
TDP_State_Node
entities.trees.
TDP_Subtree_Collection
entities.
Tuple
(implements java.lang.
Comparable
<T>)
Skip navigation links
Overview
Package
Class
Use
Tree
Deprecated
Index
Help
Prev
Next
Frames
No Frames
All Classes
Copyright © 2021. All rights reserved.


| Placebo | Xanomeline Low Dose |
Xanomeline High Dose |
||
|---|---|---|---|---|
| colRES1label | colRES2label | |||
| _ALL_ | _ALL_ / count | 281 | 412 | 433 |
| _ALL_ | _ALL_ / countdistinct | 65 | 77 | 76 |
| CARDIAC DISORDERS | _ALL_ / countdistinct | 12 | 13 | 15 |
| CARDIAC DISORDERS | _ALL_ / count | 26 | 30 | 30 |
| CARDIAC DISORDERS | ATRIAL FIBRILLATION / countdistinct | 1 | 1 | 3 |
| CARDIAC DISORDERS | ATRIAL FIBRILLATION / count | 1 | 1 | 5 |
| CARDIAC DISORDERS | MYOCARDIAL INFARCTION / countdistinct | 4 | 2 | 4 |
| CARDIAC DISORDERS | MYOCARDIAL INFARCTION / count | 4 | 4 | 8 |
| CARDIAC DISORDERS | SINUS BRADYCARDIA / countdistinct | 2 | 7 | 8 |
| CARDIAC DISORDERS | SINUS BRADYCARDIA / count | 2 | 10 | 12 |
| CARDIAC DISORDERS | SUPRAVENTRICULAR EXTRASYSTOLES / countdistinct | 1 | 1 | 1 |
| CARDIAC DISORDERS | SUPRAVENTRICULAR EXTRASYSTOLES / count | 2 | 2 | 1 |
| EAR AND LABYRINTH DISORDERS | _ALL_ / countdistinct | 1 | 2 | 1 |
| EAR AND LABYRINTH DISORDERS | _ALL_ / count | 2 | 2 | 1 |
| EYE DISORDERS | _ALL_ / countdistinct | 2 | 2 | 1 |
| EYE DISORDERS | _ALL_ / count | 5 | 2 | 2 |
| GASTROINTESTINAL DISORDERS | _ALL_ / countdistinct | 17 | 14 | 20 |
| GASTROINTESTINAL DISORDERS | _ALL_ / count | 26 | 22 | 36 |
| GASTROINTESTINAL DISORDERS | ABDOMINAL PAIN / countdistinct | 1 | 3 | 1 |
| GASTROINTESTINAL DISORDERS | ABDOMINAL PAIN / count | 1 | 3 | 2 |
| GASTROINTESTINAL DISORDERS | DIARRHOEA / countdistinct | 9 | 4 | 4 |
| GASTROINTESTINAL DISORDERS | DIARRHOEA / count | 10 | 5 | 4 |
| GASTROINTESTINAL DISORDERS | NAUSEA / countdistinct | 3 | 3 | 6 |
| GASTROINTESTINAL DISORDERS | NAUSEA / count | 3 | 5 | 13 |
| GASTROINTESTINAL DISORDERS | VOMITING / countdistinct | 3 | 3 | 7 |
| GASTROINTESTINAL DISORDERS | VOMITING / count | 3 | 4 | 9 |
| GENERAL DISORDERS AND ADMINISTRA | _ALL_ / countdistinct | 21 | 47 | 40 |
| GENERAL DISORDERS AND ADMINISTRA | _ALL_ / count | 46 | 118 | 124 |
| GENERAL DISORDERS AND ADMINISTRA | APPLICATION SITE DERMATITIS / countdistinct | 5 | 9 | 7 |
| GENERAL DISORDERS AND ADMINISTRA | APPLICATION SITE DERMATITIS / count | 9 | 15 | 12 |
| GENERAL DISORDERS AND ADMINISTRA | APPLICATION SITE ERYTHEMA / countdistinct | 3 | 12 | 15 |
| GENERAL DISORDERS AND ADMINISTRA | APPLICATION SITE ERYTHEMA / count | 3 | 20 | 23 |
| GENERAL DISORDERS AND ADMINISTRA | APPLICATION SITE IRRITATION / count | 7 | 18 | 16 |
| GENERAL DISORDERS AND ADMINISTRA | APPLICATION SITE IRRITATION / countdistinct | 3 | 9 | 9 |
| GENERAL DISORDERS AND ADMINISTRA | APPLICATION SITE PRURITUS / countdistinct | 6 | 22 | 22 |
| GENERAL DISORDERS AND ADMINISTRA | APPLICATION SITE PRURITUS / count | 10 | 32 | 35 |
| GENERAL DISORDERS AND ADMINISTRA | APPLICATION SITE VESICLES / countdistinct | 1 | 4 | 6 |
| GENERAL DISORDERS AND ADMINISTRA | APPLICATION SITE VESICLES / count | 2 | 5 | 6 |
| GENERAL DISORDERS AND ADMINISTRA | CHILLS / countdistinct | 1 | 1 | 1 |
| GENERAL DISORDERS AND ADMINISTRA | CHILLS / count | 3 | 2 | 1 |
| GENERAL DISORDERS AND ADMINISTRA | FATIGUE / countdistinct | 1 | 5 | 5 |
| GENERAL DISORDERS AND ADMINISTRA | FATIGUE / count | 2 | 5 | 5 |
| GENERAL DISORDERS AND ADMINISTRA | OEDEMA PERIPHERAL / countdistinct | 2 | 1 | 2 |
| GENERAL DISORDERS AND ADMINISTRA | OEDEMA PERIPHERAL / count | 3 | 1 | 3 |
| INFECTIONS AND INFESTATIONS | _ALL_ / countdistinct | 16 | 9 | 13 |
| INFECTIONS AND INFESTATIONS | _ALL_ / count | 35 | 16 | 20 |
| INFECTIONS AND INFESTATIONS | INFLUENZA / countdistinct | 1 | 1 | 1 |
| INFECTIONS AND INFESTATIONS | INFLUENZA / count | 2 | 1 | 1 |
| INFECTIONS AND INFESTATIONS | NASOPHARYNGITIS / countdistinct | 2 | 4 | 6 |
| INFECTIONS AND INFESTATIONS | NASOPHARYNGITIS / count | 4 | 9 | 8 |
| INFECTIONS AND INFESTATIONS | UPPER RESPIRATORY TRACT INFECTIO / countdistinct | 6 | 1 | 3 |
| INFECTIONS AND INFESTATIONS | UPPER RESPIRATORY TRACT INFECTIO / count | 12 | 2 | 5 |
| INJURY, POISONING AND PROCEDURAL | _ALL_ / countdistinct | 4 | 5 | 5 |
| INJURY, POISONING AND PROCEDURAL | _ALL_ / count | 9 | 12 | 8 |
| INJURY, POISONING AND PROCEDURAL | CONTUSION / countdistinct | 1 | 1 | 2 |
| INJURY, POISONING AND PROCEDURAL | CONTUSION / count | 1 | 3 | 3 |
| INJURY, POISONING AND PROCEDURAL | EXCORIATION / countdistinct | 2 | 1 | 1 |
| INJURY, POISONING AND PROCEDURAL | EXCORIATION / count | 3 | 2 | 1 |
| INJURY, POISONING AND PROCEDURAL | FALL / count | 2 | 2 | 1 |
| INJURY, POISONING AND PROCEDURAL | FALL / countdistinct | 1 | 2 | 1 |
| INVESTIGATIONS | _ALL_ / countdistinct | 10 | 6 | 6 |
| INVESTIGATIONS | _ALL_ / count | 19 | 7 | 8 |
| INVESTIGATIONS | ELECTROCARDIOGRAM T WAVE INVERSI / countdistinct | 2 | 1 | 1 |
| INVESTIGATIONS | ELECTROCARDIOGRAM T WAVE INVERSI / count | 3 | 1 | 1 |
| METABOLISM AND NUTRITION DISORDE | _ALL_ / countdistinct | 6 | 1 | 2 |
| METABOLISM AND NUTRITION DISORDE | _ALL_ / count | 8 | 1 | 4 |
| MUSCULOSKELETAL AND CONNECTIVE T | _ALL_ / countdistinct | 4 | 7 | 7 |
| MUSCULOSKELETAL AND CONNECTIVE T | _ALL_ / count | 6 | 10 | 10 |
| MUSCULOSKELETAL AND CONNECTIVE T | ARTHRALGIA / countdistinct | 1 | 2 | 1 |
| MUSCULOSKELETAL AND CONNECTIVE T | ARTHRALGIA / count | 1 | 4 | 1 |
| MUSCULOSKELETAL AND CONNECTIVE T | BACK PAIN / countdistinct | 1 | 1 | 3 |
| MUSCULOSKELETAL AND CONNECTIVE T | BACK PAIN / count | 2 | 1 | 4 |
| NERVOUS SYSTEM DISORDERS | _ALL_ / count | 11 | 40 | 41 |
| NERVOUS SYSTEM DISORDERS | _ALL_ / countdistinct | 8 | 20 | 25 |
| NERVOUS SYSTEM DISORDERS | DIZZINESS / count | 3 | 13 | 15 |
| NERVOUS SYSTEM DISORDERS | DIZZINESS / countdistinct | 2 | 8 | 11 |
| NERVOUS SYSTEM DISORDERS | HEADACHE / count | 3 | 4 | 8 |
| NERVOUS SYSTEM DISORDERS | HEADACHE / countdistinct | 3 | 3 | 5 |
| NERVOUS SYSTEM DISORDERS | SOMNOLENCE / count | 3 | 5 | 1 |
| NERVOUS SYSTEM DISORDERS | SOMNOLENCE / countdistinct | 2 | 3 | 1 |
| PSYCHIATRIC DISORDERS | _ALL_ / count | 12 | 14 | 11 |
| PSYCHIATRIC DISORDERS | _ALL_ / countdistinct | 10 | 10 | 8 |
| PSYCHIATRIC DISORDERS | AGITATION / countdistinct | 2 | 2 | 1 |
| PSYCHIATRIC DISORDERS | AGITATION / count | 2 | 2 | 1 |
| PSYCHIATRIC DISORDERS | CONFUSIONAL STATE / countdistinct | 2 | 3 | 1 |
| PSYCHIATRIC DISORDERS | CONFUSIONAL STATE / count | 2 | 3 | 1 |
| RENAL AND URINARY DISORDERS | _ALL_ / countdistinct | 4 | 3 | 3 |
| RENAL AND URINARY DISORDERS | _ALL_ / count | 5 | 3 | 4 |
| RENAL AND URINARY DISORDERS | MICTURITION URGENCY / countdistinct | 1 | 1 | 1 |
| RENAL AND URINARY DISORDERS | MICTURITION URGENCY / count | 1 | 1 | 2 |
| RESPIRATORY, THORACIC AND MEDIAS | _ALL_ / count | 12 | 14 | 22 |
| RESPIRATORY, THORACIC AND MEDIAS | _ALL_ / countdistinct | 8 | 9 | 10 |
| RESPIRATORY, THORACIC AND MEDIAS | COUGH / countdistinct | 1 | 5 | 5 |
| RESPIRATORY, THORACIC AND MEDIAS | COUGH / count | 1 | 7 | 7 |
| RESPIRATORY, THORACIC AND MEDIAS | DYSPNOEA / count | 1 | 1 | 1 |
| RESPIRATORY, THORACIC AND MEDIAS | DYSPNOEA / countdistinct | 1 | 1 | 1 |
| RESPIRATORY, THORACIC AND MEDIAS | NASAL CONGESTION / countdistinct | 3 | 1 | 3 |
| RESPIRATORY, THORACIC AND MEDIAS | NASAL CONGESTION / count | 3 | 1 | 4 |
| SKIN AND SUBCUTANEOUS TISSUE DIS | _ALL_ / countdistinct | 20 | 39 | 40 |
| SKIN AND SUBCUTANEOUS TISSUE DIS | _ALL_ / count | 45 | 111 | 104 |
| SKIN AND SUBCUTANEOUS TISSUE DIS | ERYTHEMA / countdistinct | 8 | 14 | 14 |
| SKIN AND SUBCUTANEOUS TISSUE DIS | ERYTHEMA / count | 12 | 22 | 22 |
| SKIN AND SUBCUTANEOUS TISSUE DIS | HYPERHIDROSIS / countdistinct | 2 | 4 | 8 |
| SKIN AND SUBCUTANEOUS TISSUE DIS | HYPERHIDROSIS / count | 2 | 5 | 10 |
| SKIN AND SUBCUTANEOUS TISSUE DIS | PRURITUS / countdistinct | 8 | 21 | 26 |
| SKIN AND SUBCUTANEOUS TISSUE DIS | PRURITUS / count | 11 | 31 | 38 |
| SKIN AND SUBCUTANEOUS TISSUE DIS | RASH / countdistinct | 5 | 13 | 9 |
| SKIN AND SUBCUTANEOUS TISSUE DIS | RASH / count | 9 | 18 | 15 |
| SKIN AND SUBCUTANEOUS TISSUE DIS | SKIN IRRITATION / countdistinct | 3 | 6 | 5 |
| SKIN AND SUBCUTANEOUS TISSUE DIS | SKIN IRRITATION / count | 4 | 13 | 8 |
| SURGICAL AND MEDICAL PROCEDURES | _ALL_ / countdistinct | 2 | 1 | 2 |
| SURGICAL AND MEDICAL PROCEDURES | _ALL_ / count | 2 | 1 | 2 |
| VASCULAR DISORDERS | _ALL_ / countdistinct | 3 | 3 | 1 |
| VASCULAR DISORDERS | _ALL_ / count | 7 | 3 | 1 |


Zip Code
Log In | Register
Shop by Category
Jet Wholesale Store
FREE SHIPPING OVER $35
How Jet Works
Welcome back!
Email address
Password
Show
Log In
Forgot your password?
New to Jet?
Create Account


DRAFT
{% if banner_class == 'draft_only' %}
(draft only): There is currently no published copy of this Module.
{% elif banner_class == 'draft_dirty' %}
(pending changes): This draft is currently published, but there have been changes since most recent
Published Copy.
{% elif banner_class == 'draft_clean' %}
(up to date): This draft is currently up to date with the
Published Copy.
{% endif %}