This is an imaginatively named, configurable web server using Fastify atop Node.js.
The aim is to provide a standardized node web server that can be used to serve your web application without the need for duplicating from another example, or starting from scratch.
The intention is that you will extend via configuration, such that this provides the baseline functionality of a Fastify web server, and within your own application you will add on the features, logic, etc unique to your situation.
This module requires Node v10.x.x+.
npm i --save @xarc/fastify-server
Electrode Server comes with enough defaults such that you can spin up a Fastify server at http://localhost:3000
with one call:
require("@xarc/fastify-server")();
Of course that doesn't do much but getting a 404
response from http://localhost:3000
.
To handle your routes, you should create a Fastify plugin to install your handlers.
See below for configuration options on how to register your plugin through @xarc/fastify-server
.
Here is an example with a default route to return a Hello World
string for http://localhost:3000
.
Through a plugin:
require("@xarc/fastify-server")({
plugins: {
routes: {
register: async instance => {
instance.route({
method: "GET",
path: "/",
handler: async () => "Hello World"
});
}
}
}
});
Using deferStart
flag to get a server that hasn't started yet:
//
// fastify doesn't allow adding routes after server started
// so need to set deferStart flag true to be able to add a route and then start the server.
//
require("@xarc/fastify-server")({ deferStart: true }).then(server => {
server.route({
method: "GET",
path: "/",
handler: async () => "Hello World"
});
return server.start();
});
You can pass in a config object that controls every aspect of the Fastify server.
For example, if you want to spin up a server with HTTP compression off at port 9000:
const config = {
connection: {
port: 9000,
compression: false
}
};
require("@xarc/fastify-server")(config);
However, for a more complex application, it's recommended that you use a config composer such as electrode-confippet to manage your app configuration.
Sample of supported options:
const config = {
server: {
// options to be passed to fastify constructor
},
connection: {
// host, port etc
},
plugins: {
// specify fastify plugins to be registered
},
listener: emitter => {
// setup server startup event handlers
},
deferStart: true, // don't start the server, you need to call server.start()
electrode: {
// options specific to Electrode such as logLevel
}
};
All properties are optional (if not present, the default values shown below will be used).
server.app.config
is set to a object that's the combination of your config with @xarc/fastify-server's
defaults applied.
server
(Object)Default:
{
server: {
app: {
electrode: true;
}
}
}
connection
(Object)@xarc/fastify-server
Default:
{
connection: {
host: process.env.HOST,
address: process.env.HOST_IP || "<IP_ADDRESS>",
port: parseInt(process.env.PORT, 10) || 3000,
routes: {
cors: true
}
}
}
plugins
(Object)server.register
Default is just empty object:
{
plugins: {
}
}
electrode
(Object)Configure electrode provided options.
{
electrode: {
eventTimeout: 5000, // milliseconds to wait for server start event listeners to return
}
}
eventTimeout
- optional milliseconds to wait for your server start event listeners to return. default 10000
. Set it to 0
or false
to disable timeout completely.listener
(function)A function to install event listeners for the electrode server startup lifecycle.
The following events are supported:
config-composed
- All configurations have been composed into a single oneserver-created
- Fastify server createdplugins-sorted
- Plugins processed and sorted by priorityplugins-registered
- Plugins registered with Fastifyserver-started
- Server startedcomplete
- Final step before returningTo receive events you must set config.listener
before calling electrodeServer
.
For example:
myConfig.listener = (emitter) => {
emitter.on("server-created", (data, next) => {
// do something
next();
});
});
The data object will contain these: emitter
, server
, config
, and plugins
.
Depending on the stage some may not be present. For example, server
is not available until server-created
event and plugins
is not available until plugins-sorted
event.
These are async events so you have to take and call a next
callback.
NodeJS defaults to 5 seconds keep-alive timeout. fastify-server
defaults to 60 seconds timeout. If you want a custom timeout, use the keepAliveTimeout
option (in milliseconds).
{
"keepAliveTimeout": 60000
}
You can control how much output the Electrode Server logs to the console by setting the logLevel
.
"info"
, "warn"
, "error"
, "none"
."warn"
means only warnning and error messages will be printed."info"
For example, to suppress the banner that is shown when the server starts up:
Fastify server running at http://mypc:4000
set the logLevel to "warn" or "error":
{
electrode: {
logLevel: "warn";
}
}
To keep your environment specific configurations manageable, you can use electrode-confippet.
Once you have your config files setup according to the configuration files setup, you can simply pass the config object to electrode server.
const config = require("electrode-confippet").config;
require("@xarc/fastify-server")(config);
You can have @xarc/fastify-server
register any Fastify plugin that you want
through your configuration file.
{
plugins: {
"<plugin-id>": {
enable: true,
options: {},
register: (fastify, opts, done) => { done() }, // mutual exclusive with module
module: "<plugin-module-name>",
requireFromPath: process.cwd(),
priority: 210,
fastifyPluginDecorate: false
}
}
}
<plugin-id>
- ID for the plugin. Generally the module name for the plugin, which is used to load it for registration.enable
- optional if set to false
then this plugin won't be registered. If it's not set then it's considered to be true
.options
- optional Object that's passed to the plugin's register function.register
- optional The Fastify plugin function. Overrides module
.module
- optional name of the module to load for the plugin instead of the <plugin-id>
requireFromPath
- optional The path from which to call require
to load the plugin modulepriority
- optional integer value to indicate the plugin's registration orderInfinity
if this field is missing or has no valid integer value (NaN
) (string of number accepted)fastifyPluginDecorate
- optional fastify-server auto decorates your plugin with fastify-plugin - set this to false
to disable this behavior. This can also be set to an object to use as options for fastify-plugin.Priority allows you to arrange plugins to be registered in an order you prefer. The plugins with lower priority values are registered first.
If you don't want to use <plugin-id>
to load the module, then you can optionally specify one of the following:
register
- if specified, then treat as the plugin's register
function to pass to Fastify, overides modulemodule
- Only used if register
is not specifiedrequire
for registration.false
then electrode server will not load any module. {
plugins: {
myPlugin: {
module: {
requireFromPath: process.cwd(),
name: "my-plugin-module"
}
}
}
}
Electrode fastify server will try to find your Fastify Plugin from your module by looking through these fields:
mod.fastifyPlugin
mod.default.fastifyPlugin
(ES6 Module)mod.plugin
mod.default
(ES6 Module)mod
itselfExamples:
CommonJS example:
module.exports = myPlugin;
module.exports.fastifyPlugin = myPlugin;
ES6 example:
export default myPlugin;
export fastifyPlugin;
With fastify-plugin
:
const fastifyPlugin = require("fastify-plugin");
module.exports = fastifyPlugin(myPlugin, {
name: "myPlugin"
});
requireFromPath
There are three places you can specify a path to call require
from when loading your plugin modules.
config.plugins.requireFromPath
- The top one used for all pluginsconfig.plugins.<plugin-id>.requireFromPath
- Used for the specific plugin of <plugin-id>
, overrides the one aboveconfig.plugins.<plugin-id>.module.requireFromPath
- Used for the specific plugin of <plugin-id>
, overrides the two aboveFor more information: check out require-from-path
To configure the plugin timeout, use Fastify's pluginTimeout
option.
{
"server": {
"pluginTimeout": 10000
}
}
Uses the Fastify default if none is specified.
fastify-static
Here's an example using the fastify-static
plugin:
First, install the plugin as you normally would from npm
:
npm i --save fastify-static
Then, add your plugin to the config plugins
section.
{
plugins: {
"fastify-static": {
enable: true,
options: {
root: process.cwd()
},
priority: 210,
requireFromPath: process.cwd()
}
}
}
Above config tells @xarc/fastify-server
to require
from CWD
the module by its <plugin-id>
"fastify-static"
and register it as a plugin with Fastify. Options passes in the required root
option to fastify-static
.
The electrode server exports a single API.
electrodeServer(config, [decors], [callback])
config
is the electrode server config
decors
- Optional extra config
or array of config
. In case you have common config you want to put inside a dedicated module, you can pass them in here.
[ decor1, decor2, decor3 ]
then each one is composed into the main config. ie: something similar to _.merge(mainConfig, decor1, decor2, decor3)
.callback
is an optional errback with the signature function (err, server)
server
is the Fastify serverReturns: a promise resolving to the Fastify server if callback is not provided
app
decoratorElecrode server also provides the app
decorator on the server and request objects.
The app
object contains the fully merged final config
.
handler: (request, reply) => {
console.log("Listening on ", request.app.config.connection.port);
};
Make sure you sign the CLA. Checkout the contribution guide
To run tests
% npm i
% clap test
To run tests and coverage
% clap check
To run sample server
% npm run sample
Hit http://localhost:9000
Hit http://localhost:9000/html/hello.html
to test static path.
Copyright 2016-present WalmartLabs
Licensed under the Apache License, Version 2.0.
Generated using TypeDoc


To test differences between gradual thaw and abrupt thaw net ecosystem exchange (Fig. 2b) we used the two-sided Kolmogorov-Smirnov test. We used this test also to compare radiocarbon ages of permafrost soil carbon respiration in gradual thaw versus abrupt thaw environments (Fig. 2c) Radiocarbon statistical analysis was performed on percent modern carbon data. All statistical analyses were performed in R 88.


Contact
I am a recent graduate from the University of Connecticut with a BFA in Digital Media and Design concentrating in Digital Film/Video Production. I have worked on several commercial, narrative, and documentary films throughout my 4 years of undergrad. I am a passionate and hard-working individual who has put in so much dedication in the art of filmmaking.
If you need to contact me, please email me at<EMAIL_ADDRESS>Thanks for visiting my website,
Anthony


DrawerJs standalone toolbar positioning demo page
Position
Outside/inside
Compact type
Hidden
Toggleable
"Drawing Tools"
left
top
right
bottom
custom anchor
outside
inside
multiple
scrollable
Fullscreen mode
left
top
right
bottom
custom anchor
outside
inside
multiple
scrollable
"Tool options"
top
bottom
custom anchor
outside
inside
multiple
scrollable
popup
Fullscreen mode
left
top
right
bottom
custom anchor
outside
inside
multiple
popup
"Drawer Toolbar"
left
top
right
bottom
custom anchor
outside
inside
multiple
scrollable
Fullscreen mode
left
top
right
bottom
custom anchor
outside
inside
multiple
scrollable
here goes some dummy content
Toolbar custom positioning (anchor div):


Since I wrote that I've also ported over some of my other greasemonkey scripts. I still need to polish them up a lot but they're working and that's cool. I'm looking forward to playing with settings pages and auto updates and what not.
I also made a Makefile (my first in about 7 years) to make the .crx file automatically using a python program I found on the intertubes (and modified slightly)
I'm mostly using the dev channel Chrome on Linux and Mac and they just added extensions support, it's really nice and is now my primary browser.


{{ message }}
First name required
Last name required
Must be a valid email
Password is required
Role is required
or login


Loading...
rehashActiveShapes
SpaceManager
rehashShape:
SpaceManager
rehashStaticShapes
SpaceManager
removeAndFreeBody:
SpaceManager
removeAndFreeConstraint:
SpaceManager
removeAndFreeConstraintsOnBody:
SpaceManager
removeAndFreeShape:
SpaceManager
removeBody:
SpaceManager
removeCollisionCallbackBetweenType:otherType:
SpaceManager
removeConstraint:
SpaceManager
removeShape:
SpaceManager
Searching...
No Matches


List out all queries in schema
Show default view for query
Filter by Tag equals blue
Sort by Tag
Hide buttons
RStudio buttons
Hide Edit and Details columns
Set Paging to 3 with config
Set Paging to 2 with API
Parameterized Queries
Regression #25337
Change Page Offset
Keep Removable Filters
Collapse filter clauses
Filter field case insensitive
Hide Paging Count
Show All Rows
Use getBaseFilters
Filter on "Sort" column
Use onRender via ButtonBarOptions
Test data is populated!
Test data is not populated!
Populate test data
Drop schema and clear test data


Testing Practicum in Jasmine
Game Plan
- Getting our feet wet with some simple unit tests
- More advanced unit testing using TDD approach
- Introduction to mocks and spies
- Testing considerations, best practices, reflections, and conclusions
- Q & A
Let’s Develop It!
We already have a JSBin set up to use Jasmine. Use this link to get to it:
Keep this page handy for reference as we work through this practicum.
Before we begin
Jasmine is a BDD (behavior-driven development) testing framework. The language it uses reflects this approach.
What we will be writing are unit tests.
Because we’ll be treating the code under test like a black box, these tests might also be labelled functional tests.

Error: Expected true to be false.
Let’s kick it up a notch
var addMeUp = function(a, b) {
return a + b;
}
What kinds of test cases do we need?
Some possible test cases*
describe('addMeUp', function() {
it('should add two numbers correctly', function() {
expect(addMeUp(1,2)).toBe(3);
expect(addMeUp(100,-100)).toBe(0);
expect(addMeUp(-1,0)).toBe(-1);
expect(addMeUp(0,0)).toBe(0);
});
});
* For demo purposes only. We all know that JS addition works.
Well, sort of…
Oops. Numbers are hard.
describe('addMeUp', function() {
it('should add two numbers correctly', function() {
//<PHONE_NUMBER>740991 == Number.MAX_SAFE_INTEGER
expect(9007199254740991, 1).toBe(9007199254740992);
});
});
Hello, world!
We’re going to create a simple function that returns a string of Hello, world!
Take a stab at writing the function and the test.
Call the function hello so we can add to it later without refactoring the name.
Let’s develop it!
An example implementation
var hello = function() {
return 'Hello, world!';
}
describe('hello', function() {
it('should return "Hello, world!"', function() {
expect(hello()).toBe('Hello, world!');
});
});
Update hello to take a name.
The function should now use that input to return Hello, [name]!
Take a stab at updating the function and the test.
An example implementation
var hello = function(name) {
return 'Hello, ' + name + '!';
}
describe('hello', function() {
it('should greet someone by the given name', function() {
expect(hello('party parrot')).toBe('Hello, party parrot!');
});
});
Let’s make this a little more BDD-like.
BDD me.
var hello = function(name) {
return 'Hello, ' + name + '!';
}
describe('hello', function() {
it('should greet someone by the given name', function() {
// given
var name = 'party parrot'
//when
var actualGreeting = hello(name);
//then
var expectedGreeting = 'Hello, party parrot!';
expect(actualGreeting).toBe(expectedGreeting);
});
});
That’s pretty cool.
But what are some edge cases?
What happens when you try these cases?
hello(null)
hello(undefined)
hello({})
hello([])
hello(1)
hello(NaN)
hello(' ') // ooh, tricksy.
Note: For the purposes of this class, assume that slapping other developers is not an available option.
Let’s develop it!
Assume that if someone doesn’t send in a valid string (with a length of non-whitespace characters greater than 0), that your function will just return Hello!
Take a stab at updating the function.
Hint: You should probably create new test case functions: it('should do the thing', function() {});
Does your code pass these tests?
describe('hello', function() {
var defaultExpectedGreeting = 'Hello!';
it('should greet someone by the given name', function() {
var name = 'party parrot';
var actualGreeting = hello(name);
var expectedGreeting = 'Hello, party parrot!';
expect(actualGreeting).toBe(expectedGreeting);
});
it('should handle whitespace only inputs', function() {
var name = ' ';
var actualGreeting = hello(name);
expect(actualGreeting).toBe(defaultExpectedGreeting);
});
it('should handle null inputs', function() {
var name = null;
var actualGreeting = hello(name);
expect(actualGreeting).toBe(defaultExpectedGreeting);
});
it('should handle undefined inputs', function() {
var name = undefined;
var actualGreeting = hello(name);
expect(actualGreeting).toBe(defaultExpectedGreeting);
});
it('should handle non-string inputs', function() {
expect(hello({})).toBe(defaultExpectedGreeting);
expect(hello([])).toBe(defaultExpectedGreeting);
expect(hello(1)).toBe(defaultExpectedGreeting);
expect(hello(NaN)).toBe(defaultExpectedGreeting);
});
});
If they do, awesome!
If they don’t, welcome to programming! Try again and may the coding gods be with you.
Hint: If your first instinct is to change the tests— stop. You need to update the code under test.
Example implementation of code under test
var hello = function(name) {
var isInputValid = name && typeof name === 'string' && name.trim().length > 0;
if (!isInputValid) {
return 'Hello!';
}
return 'Hello, ' + name + '!';
}
Negating in Jasmine
describe('hello', function() {
it('should handle null inputs', function() {
var name = null;
var actualGreeting = hello(name);
expect(actualGreeting).not.toBe('Hello, null!');
});
});
Testing objects
describe('objects', function() {
it('should equal each other if they have the same stuff in them', function() {
var obj1 = {
foo: 1,
bar: 'doritos'
};
var obj2 = {
foo: 1,
bar: 'doritos'
};
expect(obj1).toBe(obj2);
});
});
Wait, what.
objects should equal each other if they have the same stuff in them.
Expected { foo : 1, bar : 'doritos' } to be { foo : 1, bar : 'doritos' }.
Equality in Jasmine
The matcher toBe compares using the === operator.
That doesn’t work for objects, for example. In these cases, you would use toEqual
Testing objects
describe('objects', function() {
it('should equal each other if they have the same stuff in them', function() {
var obj1 = {
foo: 1,
bar: 'doritos'
};
var obj2 = {
foo: 1,
bar: 'doritos'
};
expect(obj1).toEqual(obj2);
});
});
Some other handy matchers in Jasmine
.toBeDefined()
.toBeNull()
.toBeTruthy()
.toBeFalsy()
.toContain()
.toBeLessThan()
.toBeGreaterThan()
.toThrowError()
Nesting describes in Jasmine
describe('test class', function() {
describe('test function 1', function() {
it('should do the thing', function() {});
});
describe('test function 2', function() {
it('should do the other thing', function() {});
});
});
Let’s develop it!
Without Doubles
Problem Statement
Return the sum of two 6-sided dice rolls, each in the range 1..6. However, if noDoubles is true, if the two dice show the same value, increment one die to the next value, wrapping around to 1 if its value was 6.
Each die value is an integer. The flag noDoubles is a boolean.
Function header:
withoutDoubles(die1, die2, noDoubles)
(Original problem withoutDoubles from codingbat.com)
Without Doubles
Example implementation
var withoutDoubles = function(die1, die2, noDoubles) {
if (noDoubles && die1 === die2) {
if (die1 === 6) {
return die1 + 1;
}
return die1 + die2 + 1;
}
return die1 + die2;
};
Without Doubles
Test cases
// withoutDoubles(2, 3, true) => 5
// withoutDoubles(3, 3, true) => 7
// withoutDoubles(3, 3, false) => 6
// withoutDoubles(2, 3, false) => 5
// withoutDoubles(5, 4, true) => 9
// withoutDoubles(5, 4, false) => 9
// withoutDoubles(5, 5, true) => 11
// withoutDoubles(5, 5, false) => 10
// withoutDoubles(6, 6, true) => 7
// withoutDoubles(6, 6, false) => 12
// withoutDoubles(1, 6, true) => 7
// withoutDoubles(6, 1, false) => 7
Blackjack
Problem Statement
Given the sum of the user’s current hand and 2 possible cards, decide which card the user should take that brings them the closest to 21 without going over. Return 1 if the user should return the first option and 2 if the user should return the second item. Return 0 if both cards take them over 21.
Function header:
blackjack(currentHand, firstCard, secondCard)
Introduction to Test-Driven Development
TDD Approach: Review
-
Step 1: Red
- Write test cases. The tests should fail for the expected reason(s) (e.g., because the implementation is not correct, not compile or runtime errors). At this point, check failure messages to ensure they accurately indicate the problem. Fix wording as necessary.
- Write shell— write enough code to get the tests to compile
-
Step 2: Green
- Write just enough code to get the tests to pass. For a complex problem complex, you might consider taking an iterative approach to the code— e.g. write enough code to get part of the test suite to pass, then work on the next piece.
-
Step 3: Refactor
- Take another pass over the code and refactor as necessary. Re-run the tests to ensure the refactor has not broken functionality.
Macaroon Party
Problem Statement
When squirrels get together for a party, they like to have macaroons. A squirrel party is successful when the number of macaroons is between 40 and 60, inclusive. Unless it is the weekend, in which case there is no upper bound on the number of macaroons. Return true if the party with the given values is successful, or false otherwise.
Do you have questions about the requirements?
(Original problem cigarParty from codingbat.com)
Macaroon Party
Test cases
// weekday, 40 -> true
// weekday, 60 -> true
// weekday, 61 -> false
// weekday, 39 -> false
// weekday, 0 -> false
// weekday, -1 -> false
// weekend, 40 -> true
// weekend, 60 -> true
// weekend, 61 -> true
// weekend, 100 -> true
// weekend, 39 -> false
// weekend, 0 -> false
// weekend, -1 -> false
Let’s develop it!
The first step of TDD is red. We need to create a set of tests that fail as we expect. In order to support that, we also need to write just enough code under test to compile. We’re not implementing any functionality yet.
On your own or with a friend, write the test set for the cases we just came up with.
Macaroon Party
Step 1: Red
var macaroonParty = function(numMacaroons, isWeekend) {
return false;
}
describe('macaroonParty', function() {
it('do the right thing on weekdays', function() {
expect(macaroonParty(40, false)).toBe(true);
expect(macaroonParty(60, false)).toBe(true);
expect(macaroonParty(61, false)).toBe(false);
expect(macaroonParty(39, false)).toBe(false);
expect(macaroonParty(0, false)).toBe(false);
expect(macaroonParty(-1, false)).toBe(false);
});
it('do the right thing on weekends', function() {
expect(macaroonParty(40, true)).toBe(true);
expect(macaroonParty(60, true)).toBe(true);
expect(macaroonParty(61, true)).toBe(true);
expect(macaroonParty(100, true)).toBe(true);
expect(macaroonParty(39, true)).toBe(false);
expect(macaroonParty(0, true)).toBe(false);
expect(macaroonParty(-1, true)).toBe(false);
});
});
Let’s develop it!
Brilliant! Step 1: done and done!
The second step of TDD is green. Here is where we will implement the necessary functionality to cause the tests to pass. By the end of this step, all tests will pass.
On your own or with a friend, write the necessary code to get the tests to pass.
Macaroon Party
Step 2: Green
var macaroonParty = function(numMacaroons, isWeekend) {
if (isWeekend) {
return numMacaroons >= 40;
}
return !isWeekend && numMacaroons >= 40 && numMacaroons <= 60;
};
Let’s develop it!
Party parrot! We did it! 💪
We’re not quite done yet, though. The third step of TDD, refactor, is just as important as the other two. Here is where we have an opportunity to make our code cleaner, more readable, and more maintanable.
Let’s look back over the example implementation. What can we do better?
var macaroonParty = function(numMacaroons, isWeekend) {
if (isWeekend) {
return numMacaroons >= 40;
}
return !isWeekend && numMacaroons >= 40 && numMacaroons <= 60;
};
Macaroon party
Observations
- We only want to write just enough code to get the tests to pass. If we can remove a piece of code, but the tests still pass, then that code is not doing anything but bloating up the codebase. What happens if we remove !isWeekend in the second check?
- It would be nice if we pulled out 40 and 60 into named constants, instead of leaving them as magic numbers in the codebase. That way the next person who reads this piece of code will have a better idea of what those numbers mean. It also helps avoid problems where someone copies a number wrong.
Macaroon Party
Step 3: Refactor
var MIN_MACAROONS_FOR_SUCCESSFUL_PARTY = 40;
var MAX_MACAROONS_FOR_SUCCESSFUL_PARTY_WEEKDAYS = 60;
var macaroonParty = function(numMacaroons, isWeekend) {
if (isWeekend) {
return numMacaroons >= MIN_MACAROONS_FOR_SUCCESSFUL_PARTY;
}
return numMacaroons >= MIN_MACAROONS_FOR_SUCCESSFUL_PARTY &&
numMacaroons <= MAX_MACAROONS_FOR_SUCCESSFUL_PARTY_WEEKDAYS;
};
Yes!
This example is all you. Flag down the TAs if you’ve got questions.
Date Fashion 💁
Problem Statement
You and your date are trying to get a table at a restaurant. The parameter you is the stylishness of your clothes, in the range 0..10, and date is the stylishness of your date’s clothes. The result getting the table is encoded as an int value with 0=no, 1=maybe, 2=yes. If either of you is very stylish, 8 or more, then the result is 2 (yes). With the exception that if either of you has style of 2 or less, then the result is 0 (no). Otherwise the result is 1 (maybe).
(Original problem dateFashion from codingbat.com)
Writing a number formatter
Problem Statement:
Write a function that formats a any number to an abbreviated form like 2K, 5M, 10B, 4T, where the letters represent thousands, millions, billions, and trillions.
Decimals should be rounded to the nearest tenth place (e.g. 2.1M)
What do our test cases look like? Are there any open questions?
Possible test cases
// should return the correct number abbreviation
// 0 -> 0
// 522 -> 522
// 1000 -> 1K
// 1200000 -> 1.2M
//<PHONE_NUMBER>0 -> 16.0B
//<PHONE_NUMBER>000 -> 1.3T
Open Questions
- What kind of rounding?
- Should 1 decimal place always be used or only when necessary?
- What happens if a number is greater than trillions?
- Should negative numbers be formatted?
Open Questions
-
What kind of rounding?
Round half up -
Should 1 decimal place always be used or only when necessary?
Always if abbreviated -
What happens if a number is greater than trillions?
Just go up to trillions. -
Should negative numbers be formatted?
Yes. Abbreviate based on the absolute value.
Possible test cases
// should return the correct number abbreviation
// 0 -> 0
// 522 -> 522
// 1 000 -> 1.0K
// 1 200 000 -> 1.2M
// 15 989 000 000 -> 16.0B
// 1 262 842 000 000 -> 1.3T
// 100 000 000 000 000 000 -> 100000.0T
// -499 -> -499
// -9368 -> -9.4K
// -8 320 000 -> -8.3M
// -28 900 000 000 -> -28.9B
// -6 183 000 000 000 -> -6.2T
// -100 000 000 000 000 000 -> -100000.0T
TDD Approach: Review
- Write test cases
- Write shell— write enough code to get the tests to compile
- All tests should fail for the expected reason(s) (e.g., because the implementation is not correct, not compile or runtime errors). At this point, check failure messages to ensure they accurately indicate the problem. Fix wording as necessary.
- Write enough code to get the tests to pass. For a problem like the one above that is reasonably complex, you might consider taking an iterative approach to the code— e.g. write enough code to get part of the test suite to pass, then work on the next piece.
- Take another pass over the code and refactor as necessary. Re-run the tests to ensure the refactor has not broken functionality.
Step 1: Write the tests
describe("formatNumber", function() {
it("does not format input with abs values of less than a thousand", function() {
expect(formatNumber(0)).toBe('0');
expect(formatNumber(522)).toBe('522');
expect(formatNumber(-499)).toBe('-499');
});
it("correctly formats input with abs values of over a trillion", function() {
expect(formatNumber(100000000000000000)).toBe('100000.0T');
expect(formatNumber(-100000000000000000)).toBe('-100000.0T');
});
it("correctly formats input with abs value of thousands, millions, billions, and trillions", function() {
expect(formatNumber(1000)).toBe('1.0K');
expect(formatNumber(1200000)).toBe('1.2M');
expect(formatNumber(15989000000)).toBe('16.0B');
expect(formatNumber(1262842000000)).toBe('1.3T');
expect(formatNumber(-8320000)).toBe('-8.3M');
expect(formatNumber(-28900000000)).toBe('-28.9B');
expect(formatNumber(-6183000000000)).toBe('-6.2T');
});
});
If we look at the tests now, we should see
ReferenceError: formatNumber is not defined
This is expected because, at this point, we have not yet declared a function called formatNumber. However, although the tests are failing, they are not failing in the way we want. They should say that they are failing because the expectation failed. We’ll fix the ReferenceError in the next step when we create the function shell.
Step 2: Write the shell
Our goal is to write just enough code to get the tests to demonstrate the kind of error message we want to get when the implementation is incorrect.
function formatNumber(input) {
return null;
}
Step 3: Check for failing tests (RED)
Our tests are still failing, but the message looks a lot better, e.g.:
Expected null to be '16.0B'.
In this example, the wording adequately describes the problem if another developer later breaks this functionality, so we’ll move on.
However, if this were not the case, we would want to take some time to make sure that when this test fails in the future, it is obvious to the developer who broke it why that is.
Step 4: The fun part (GREEN)
Finally! The exciting part. We get to solve the problem.
Because this the business problem is somewhat complex, we’ll do the “basic” cases first, then move onto the harder part of the problem.
Step 4a: Basic cases
If the absolute value of given input is less a thousand, we essentially leave it alone.
Try 1
function formatNumber(input) {
if (Math.abs(input) < 1000) {
return input;
}
return null;
}
Oops.
Expected 0 to be '0'.
Even though we’re not formatting the number, we should still return a string for consistency.
function formatNumber(input) {
if (Math.abs(input) < 1000) {
return input.toString();
}
return null;
}
Now the test for does not format input with abs values of less than a thousand passes. The other two tests still fail as expected.
Step 4b: The rest of it
Take a few minutes to come up with a solution to the rest of the problem.
Feel free to work with a partner!
Also, because rounding in Javascript can be a pain, feel free to use the following helper function to correctly do a round half-up.
Helper Rounding Function
function roundBetter(number, precision) {
var factor = Math.pow(10, precision);
var tempNumber = number * factor;
var roundedTempNumber = Math.round(tempNumber);
return roundedTempNumber / factor;
}
Example initial implementation
var MAGNITUDE_TO_LETTER_ABBREVIATION = {
0: '',
1: 'K',
2: 'M',
3: 'B',
4: 'T'
};
function roundBetter(number, precision) { ... }
function recursivelyFormatNumber(input, numRecursions) {
if (Math.abs(input) < 1000) {
return roundBetter(input, 1).toFixed(1).toString() + MAGNITUDE_TO_LETTER_ABBREVIATION[numRecursions];
}
if (numRecursions === 4) {
return roundBetter(input, 1).toFixed(1).toString() + MAGNITUDE_TO_LETTER_ABBREVIATION[numRecursions];
}
return recursivelyFormatNumber(input/1000, numRecursions+1);
}
function formatNumber(input) {
if (Math.abs(input) < 1000) {
return input.toString();
}
return recursivelyFormatNumber(input, 0);
}
Step 5: Refactor
The inital implementation works, but there is a lot of room to clean and DRY up what we did.
In this step, we clean up our working code, using our tests as a safety net.
Take a few minutes to look over your code and make any desired refactors.
Feel free to work with a partner!
Example refactored implementation
var DIVISOR = 1000;
var NUM_DECIMAL_PLACES = 1;
var MAX_RECURSIONS_ALLOWED = 4;
var MAGNITUDE_TO_LETTER_ABBREVIATION = {
0: '',
1: 'K',
2: 'M',
3: 'B',
4: 'T'
};
function roundBetter(number, precision) { ... }
function formatNumberStr(input, numRecursions) {
var numAsStr = roundBetter(input, NUM_DECIMAL_PLACES).toFixed(NUM_DECIMAL_PLACES).toString();
return numAsStr + MAGNITUDE_TO_LETTER_ABBREVIATION[numRecursions]
}
function recursivelyFormatNumber(input, numRecursions) {
if (Math.abs(input) < DIVISOR || numRecursions === MAX_RECURSIONS_ALLOWED) {
return formatNumberStr(input, numRecursions);
}
return recursivelyFormatNumber(input/DIVISOR, numRecursions+1);
}
function formatNumber(input) {
if (Math.abs(input) < DIVISOR) {
return input.toString();
}
return recursivelyFormatNumber(input, 0);
}
Let’s develop it!
Given a list of


#!/usr/bin/env node
'use strict';
#!/usr/bin/env node
'use strict';
This article will assume a basic familiarity with the selenium-webdriver API for Node.js.
Legion’s support for webdriver consists of a very small layer that provides a Driver instance for every virtual user and instruments most webdriver calls.
This binding is an optional component. If you wish, you can forgo the binding and use vanilla selenium-webdriver with sections ((TODO: link to sections article)). You can even switch between the binding and vanilla using ‘Driver().chain(driver => {})’. Everything inside the chain will have access to the vanilla Driver instance.
const L = require('legion');
const delay = require('legion-io-delay');
const obstacle = require('legion-obstacle-course').http;
Importing the binding looks very similary to importing vanilla webdriver:
const webdriver = require('legion-selenium-webdriver');
const By = webdriver.By;
const Driver = webdriver.Driver;
To use the binding, first create a testcase that uses it. This binding also uses the Obstacle Course.
L.create()
.using(obstacle)
.using(webdriver.init(new webdriver.Builder().forBrowser('firefox')))
Then, use a Driver() to get the Driver instance for your virtual user. You can make ordinary selenium API calls.
If you want to take the result an API call, use ‘chain’ instead of ‘then’:
.withTestcase(L.of()
.chain(delay(5,10))
.chain(Driver.get(obstacle.host + '/static'))
.chain(delay(5,10))
.chain(Driver.findElement(By.linkText('Meep')).click())
.chain(delay(5,10))
.chain(Driver.findElement(By.id('left')).click())
.chain(Driver.findElement(By.id('left')).getText())
.chain(assertEquals('meep!'))
.chain(Driver.findElement(By.id('right')).getText())
.chain(assertEquals('Right'))
.chain(delay(5,10)))
.main();
function assertEquals(x) {
return s => {
if( x !== s )
throw new Error('expected ' + x + ' but found ' + s);
};
}
As of this writing, selenium-webdriver uses a “promise manager.” Among other things, the manager might force all selenium calls to operate in sequence, even if that isn’t explicitly spelled out in your script, and even if the calls are made by different virtual users. This will mess up all of your results if it means that calls from one virtual user have to wait for another virtual user to release control. You can work around this with ((TODO: there’s an environment or global variable or something)).
If you don’t like that solution, you can also just run one Legion process per virtual user anyway. The overhead from running multiple instances of node is considerably less than the overhead of running multiple instances of your browser.


This class can be used to model Diagonal Gaussian Mixture Models.
Inheritance:
Public Fields
-
int n_gaussians
- number of Gaussians in the mixture
-
real prior_weights
- prior weights of the Gaussians, used in EM to give a small prior on each Gaussian
-
EMTrainer* initial_kmeans_trainer
- optional initializations if nothing is given, then random calling by reset(), at your own risks or model loaded by the user.
-
MeasurerList* initial_kmeans_trainer_measurers
- as well as a measurer of this trainer
-
real* log_weights
- the pointers to the parameters
-
real* dlog_weights
- the pointers to the derivative of the parameters
-
real* var_threshold
- this contains the minimal value of each variance
-
Sequence* log_probabilities_g
- for each frame, for each gaussian, keep its log probability
-
int best_gauss
- gaussian that maximize the observed frame
-
Sequence* best_gauss_per_frame
- gaussian that maximize the observed frame
-
real* sum_log_var_plus_n_obs_log_2_pi
- in order to faster the computation, we can do some "pre-computation" pre-computed sum_log_var + n_obs * log_2_pi
-
real** minus_half_over_var
- pre-computed -05 / var
-
real** means_acc
- accumulators for EM
Public Methods
-
DiagonalGMM(int n_inputs_, int n_gaussians_, EMTrainer* initial_kmeans_trainer_ = NULL)
-
virtual void reset()
- This methods have to call by the user to initialized the random parameters
-
virtual void setDataSet(DataSet* data_)
- If the KmeanTrainer has been given to the constructor, Kmeans algorithm is perform
-
virtual void setVarThreshold(real* var_threshold_)
- Set the minimum value for the variances
-
virtual void eMIterInitialize()
- Methods used to initialize the model at the beginning of each EM iteration
-
virtual void iterInitialize()
- Methods used to initialize the model at the beginning of each gradient descent iteration
-
virtual real frameLogProbability(int t, real* inputs)
- Returns the log probability of a frame of a sequence
-
virtual real viterbiFrameLogProbability(int t, real* inputs)
- Returns the log probability of a frame of a sequence on viterbi mode
-
virtual real frameLogProbabilityOneGaussian(int g, real* inputs)
- this method returns the log probability of the "g" Gaussian
-
virtual void sequenceInitialize(Sequence* inputs)
- Methods used to initialize the model at the beginning of each example during gradient descent training
-
virtual void eMSequenceInitialize(Sequence* inputs)
- Methods used to initialize the model at the beginning of each example during EM training
-
virtual void frameEMAccPosteriors(int t, real* inputs, real log_posterior)
- The backward step of EM for a frame
-
virtual void frameViterbiAccPosteriors(int t, real* inputs, real log_posterior)
- The backward step of Viterbi for a frame
-
virtual void eMUpdate()
- The update after each iteration for EM
-
virtual void update()
- The update after each iteration for gradient
-
virtual void frameBackward(int t, real* f_inputs, real* beta_, real* f_outputs, real* alpha_)
- Same as backward, but for one frame only
-
virtual void frameDecision(int t, real* decision)
- Returns the expected value in decision
Public Fields
-
real log_probability
-
Sequence* log_probabilities
Public Methods
-
virtual real logProbability(Sequence* inputs)
-
virtual real viterbiLogProbability(Sequence* inputs)
-
virtual void eMAccPosteriors(Sequence* inputs, real log_posterior)
-
virtual void viterbiAccPosteriors(Sequence* inputs, real log_posterior)
-
virtual void decode(Sequence* inputs)
-
virtual void eMForward(Sequence* inputs)
-
virtual void viterbiForward(Sequence* inputs)
-
virtual void viterbiBackward(Sequence* inputs, Sequence* alpha)
Public Members
-
Returns the decision of the distribution
Public Fields
-
int n_inputs
-
int n_outputs
-
Parameters* params
-
Parameters* der_params
-
Sequence* beta
Public Methods
-
virtual void forward(Sequence* inputs)
-
virtual void backward(Sequence* inputs, Sequence* alpha)
-
virtual void setPartialBackprop(bool flag=true)
-
virtual void frameForward(int t, real* f_inputs, real* f_outputs)
-
virtual void loadXFile(XFile* file)
-
virtual void saveXFile(XFile* file)
Inherited from Machine:
Public Fields
-
Sequence* outputs
Inherited from Object:
Public Fields
-
Allocator* allocator
Public Methods
-
void addOption(const char* name, int size, void* ptr, const char* help="")
-
void addIOption(const char* name, int* ptr, int init_value, const char* help="")
-
void addROption(const char* name, real* ptr, real init_value, const char* help="")
-
void addBOption(const char* name, bool* ptr, bool init_value, const char* help="")
-
void addOOption(const char* name, Object** ptr, Object* init_value, const char* help="")
-
void setOption(const char* name, void* ptr)
-
void setIOption(const char* name, int option)
-
void setROption(const char* name, real option)
-
void setBOption(const char* name, bool option)
-
void setOOption(const char* name, Object* option)
-
void load(const char* filename)
-
void save(const char* filename)
-
void* operator new(size_t size, Allocator* allocator_=NULL)
-
void* operator new(size_t size, Allocator* allocator_, void* ptr_)
-
void operator delete(void* ptr)
Documentation
This class can be used to model Diagonal Gaussian Mixture Models.
They can be trained using either EM (with EMTrainer) or gradient descent
(with GMTrainer).
- int n_gaussians
- number of Gaussians in the mixture
- real prior_weights
- prior weights of the Gaussians, used in EM to give
a small prior on each Gaussian
- EMTrainer* initial_kmeans_trainer
- optional initializations
if nothing is given, then random calling by reset(),
at your own risks or model loaded by the user.
one can give a initial trainer containing a kmeans
- MeasurerList* initial_kmeans_trainer_measurers
- as well as a measurer of this trainer
- real* log_weights
- the pointers to the parameters
- real* dlog_weights
- the pointers to the derivative of the parameters
- real* var_threshold
- this contains the minimal value of each variance
- Sequence* log_probabilities_g
- for each frame, for each gaussian, keep its log probability
- int best_gauss
- gaussian that maximize the observed frame
- Sequence* best_gauss_per_frame
- gaussian that maximize the observed frame
- real* sum_log_var_plus_n_obs_log_2_pi
- in order to faster the computation, we can do some "pre-computation"
pre-computed sum_log_var + n_obs * log_2_pi
- real** minus_half_over_var
- pre-computed -05 / var
- real** means_acc
- accumulators for EM
- DiagonalGMM(int n_inputs_, int n_gaussians_, EMTrainer* initial_kmeans_trainer_ = NULL)
- virtual void reset()
-
This methods have to call by the user to initialized the
random parameters
- virtual void setDataSet(DataSet* data_)
-
If the KmeanTrainer has been given to the constructor, Kmeans algorithm
is perform
- virtual void setVarThreshold(real* var_threshold_)
-
Set the minimum value for the variances
- virtual void eMIterInitialize()
- Methods used to initialize the model at the beginning of each
EM iteration
- virtual void iterInitialize()
- Methods used to initialize the model at the beginning of each
gradient descent iteration
- virtual real frameLogProbability(int t, real* inputs)
- Returns the log probability of a frame of a sequence
- virtual real viterbiFrameLogProbability(int t, real* inputs)
- Returns the log probability of a frame of a sequence on viterbi mode
- virtual real frameLogProbabilityOneGaussian(int g, real* inputs)
- this method returns the log probability of the "g" Gaussian
- virtual void sequenceInitialize(Sequence* inputs)
- Methods used to initialize the model at the beginning of each
example during gradient descent training
- virtual void eMSequenceInitialize(Sequence* inputs)
- Methods used to initialize the model at the beginning of each
example during EM training
- virtual void frameEMAccPosteriors(int t, real* inputs, real log_posterior)
- The backward step of EM for a frame
- virtual void frameViterbiAccPosteriors(int t, real* inputs, real log_posterior)
- The backward step of Viterbi for a frame
- virtual void eMUpdate()
- The update after each iteration for EM
- virtual void update()
- The update after each iteration for gradient
- virtual void frameBackward(int t, real* f_inputs, real* beta_, real* f_outputs, real* alpha_)
- Same as backward, but for one frame only
- virtual void frameDecision(int t, real* decision)
- Returns the expected value in decision
- Direct child classes:
- MAPDiagonalGMM
KMeans
- Author:
- Samy Bengio<EMAIL_ADDRESS>Johnny Mariethoz<EMAIL_ADDRESS>Alphabetic index HTML hierarchy of classes or Java
This page was generated with the help of DOC++.


|
nrf51AdvLogger
1.0
|
Bluetooth Low Energy advertisement packets observer. More...
Files | |
| file | observer.c |
| File containing the implementation of the BLE advertisement packets observer. | |
| file | observer.h |
| File to declare the global functions of the BLE observation routine. | |
Macros | |
| #define | SET_BIT(n) (1UL << n) |
| Return 2^n, used for setting nth bit as 1. | |
| #define | MAX_PDU_SIZE 40 |
| Maximum PDU size of Adv packets is 39 octets, defined as 40 to make it word alligned. | |
| #define | LOGGER_NUMBER 20 |
| Maximum number of packets logged in a scan interval. | |
| #define | SCAN_WINDOW 750 |
| Period (ms) in which the radio is on and scanning on a particular channel during SCAN_INTERVAL. | |
| #define | SCAN_INTERVAL 1000 |
| Total time in a cycle where the radio is on and off. | |
Functions | |
| static void | obsvr_interval (void) |
| Handler of the repetitive timer with an interval of SCAN_INTERVAL. More... | |
| static void | obsvr_window (void) |
| Handler of the single shot timer started in obsvr_interval with interval of SCAN_WINDOW. More... | |
| static void | collect_packet (void) |
| Collect the data from pdu array at the end of every received packet. More... | |
| static void | print_collected (uint8_t *packet_to_print) |
| Print the packets collected during the SCAN_INTERVAL. More... | |
| static void | obsvr_req (uint8_t *ptr) |
| Handler which is called when a string is sent through UART. More... | |
| static void | adv_seg_print (uint8_t *ptr, uint32_t len) |
| Prints the information about the various segments of an advertisement packet. More... | |
| void | RADIO_IRQHandler () |
| Function for handling the Radio interrupts. More... | |
| void | obsvr_radio_init (void) |
| Initialize the radio peripheral to be used for sniffing advertisement packets. More... | |
| void | obsvr_begin (void) |
| Start the packet observation procedure. | |
Variables | |
| static uint8_t | pdu [MAX_PDU_SIZE] |
| Packet data unit, the array where the radio dumps the data it receives. | |
| static uint8_t | packets [LOGGER_NUMBER][MAX_PDU_SIZE+8] |
| Two dimensional array of packets received in one SCAN_WINDOW. More... | |
| static uint32_t | rssi = 0 |
| Variable to store the signal strength of the received packet in the Interrupt routine. | |
| static uint32_t | packet_count = 0 |
| Number of packets received in the last SCAN_WINDOW. | |
Bluetooth Low Energy advertisement packets observer.
|
static |
Prints the information about the various segments of an advertisement packet.
| ptr | pointer to the payload of an advertisement packet |
| len | length of the payload of an advertisement packet |
Definition at line 207 of file observer.c.
Referenced by print_collected().
|
static |
Collect the data from pdu array at the end of every received packet.
Called from the interrupt to copy the received data from pdu.
Definition at line 192 of file observer.c.
References LOGGER_NUMBER, MAX_PDU_SIZE, packet_count, packets, pdu, read_time_us(), and rssi.
Referenced by RADIO_IRQHandler().
|
static |
Handler of the repetitive timer with an interval of SCAN_INTERVAL.
This function configures the radio to scan in one of the advertising channel and starts a single shot timer with interval of SCAN_WINDOW
Definition at line 527 of file observer.c.
References LED_RGB_RED, leds_on(), MS_TIMER1, obsvr_window(), packet_count, RTC_TICKS, SCAN_WINDOW, SINGLE_CALL, and start_ms_timer().
Referenced by obsvr_req().
| void obsvr_radio_init | ( | void | ) |
Initialize the radio peripheral to be used for sniffing advertisement packets.
The code for this function is modified code from the MIT licensed code from this tread of Nordic Developer Zone.
Definition at line 383 of file observer.c.
References MAX_PDU_SIZE, pdu, and SET_BIT.
Referenced by main().
|
static |
Handler which is called when a string is sent through UART.
Used for initiating and terminating the BLE advertisement packet observation.
| ptr | The unsigned character pointer to the string received through UART |
Definition at line 564 of file observer.c.
References is_ms_timer_on(), MS_TIMER0, MS_TIMER1, obsvr_interval(), REPEATED_CALL, RTC_TICKS, SCAN_INTERVAL, start_ms_timer(), and stop_ms_timer().
Referenced by obsvr_begin().
|
static |
Handler of the single shot timer started in obsvr_interval with interval of SCAN_WINDOW.
This function disables the radio and prints the information about the collected packets.
Definition at line 496 of file observer.c.
References LED_RGB_RED, leds_off(), packet_count, packets, and print_collected().
Referenced by obsvr_interval().
|
static |
Print the packets collected during the SCAN_INTERVAL.
| packet_to_print |
Definition at line 308 of file observer.c.
References adv_seg_print(), MAX_PDU_SIZE, and printfcomma().
Referenced by obsvr_window().
| void RADIO_IRQHandler | ( | ) |
Function for handling the Radio interrupts.
Definition at line 178 of file observer.c.
References collect_packet(), and rssi.
|
static |
Two dimensional array of packets received in one SCAN_WINDOW.
The number of packets that can be stored is LOGGER_NUMBER.
Definition at line 111 of file observer.c.
Referenced by collect_packet(), and obsvr_window().


Located on the northern coast of the island, Castelsardo is about 20nm east of Port Torres. Is is an attractive, historic town dominated by the castle on the headland.
Position 40°55′N, 8°43′E.
Docking
Porto di Castelsardo
Località Porto Turistico,
, Castelsardo, Sardinia, Italy
Opening hours: 09:00-14:00, 15:00-21:00 (high season, less other times)
500 berths, max LOA 25m, Depths 1-5m. All facilities, fuel, laundry, most repairs. WiFi, large supermarket, small chandlery. Haulout with 50 ton travel hoist, 10 ton crane, repairs.


Bayesian FilteringOverview of Bayesian filtering with the Filtering Classes |
<EMAIL_ADDRESS>Centre for Field Robotics |
Documentation generated by DoxygenFilter hierarchy |
Project Summary and Download
GIT Repository
|
Bayesian Filtering is a probabilistic technique for data fusion. The technique combines a concise mathematical formulation of a system with observations of that system. Probabilities are used to represent the state of a system, likelihood functions to represent their relationships. In this form Bayesian inference can be applied and further related probabilities deduced. See Wikipedia for information on Probability theory, Bayes theorem, Bayesian Inference.
For discrete systems the Bayesian formulation results in a naturally iterative data fusion solution. For dynamic systems there is a class of solutions, discrete filters, that combine observed outputs of the system with the system's dynamic model. An estimator computes a estimate of the systems state with each observation of the system. Linear estimators such as the Kalman Filter are commonly applied.
Bayes++ is an open source library of C++ classes. These classes represent and implement a wide variety of numerical algorithms for Bayesian Filtering of discrete systems. The classes provide tested and consistent numerical methods and the class hierarchy explicitly represents the variety of filtering algorithms and system model types.
This is very simple example; for those who have never used the Bayesian Filtering Classes before. If you wish to see how simple it is to use Bayes++ then View the Source.
The example shows how two classes are created. The first is the prediction model, the second the observation model. In this example they represent a simple linear problem with only one state variable and constant model noises. A filter fuses the results of prediction and observation.
See the Bayesian Filtering classes for a description of the classes used and all three examples provided with Bayes++.
First download and extract Bayes++ and also the Boost library. Boost is used to provide compiler independence, and a common build system. Two Boost header libraries are used: uBLAS for linear algebra, and random for the PV and QuadCalib examples. The Boost headers can be placed anywhere relative to Bayes++, but it is easy if you follow this structure:
Using the Boost Build system version 2 is the best way to compile the
examples. Use the b2 (Boost jam) program to build Bayes++ in
a single step. The documentation in your
downloaded copy of Boost explains how to obtain and install the latest
version of the Boost Build system yourself. For everything to work execute b2
with the required toolset, and the location where you installed Boost.
To build Bayes++ and the examples with GCC simply execute: (Bayes++ should be the current directory)
b2 toolset=gcc link=static cxxflags=-Wno-unused-local-typedefs -sBOOST_ROOT="../boost_1_55_0"
OR for Visual C++ execute:
b2 toolset=msvc link=static -sBOOST_ROOT="../boost_1_55_0"
It is possible to work without the BOOST_ROOT variable by either creating a build_build.jam file in sourceDirectory (or above) or by setting it as an environment variable.
The executables for the three examples will be placed inside a directory hierarchy named target. Static libraries for debug and release builds of the BayesFilter library are placed in target/BayesFilter. The target directory and its subdirectories are created automatically.
For Visual C++ 2008 etc, you can also use the Bayes++.sln solution and the active configuration uBLAS Debug. The compiler options must be set so the Boost include files can be found. That is, the include path must contain the base directory of Boost. In this case the local boost directory. In VC7.1 you should do this by choosing the Tools/Options/Projects/VC++ Directories option.
Visual C++ 7.0 requires the use of Boost version 1_32_0. Visual C++ 7.1 (or later) requires Boost version 1_33_0 (or later).I
All Bayes++ source code files are copyright with the license conditions as given here. The copyright notice is that of the MIT license. This in no way restricts any commercial use you may wish to make using our source code. As long as you respect the copyright and license conditions, Michael Stevens and the Australian Centre for Field Robotics are happy to for you to use it in any way you wish.
Bayes++ the Bayesian Filtering Library
Copyright (c) 2003,2004,2005,2006,2011,2012,2014 Michael Stevens, Copyright (c) 2002 Michael Stevens and Australian Centre for Field Robotics
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.
SLAM is one of the most interesting problems in Bayesian filtering. It's structure implies that it cannot be correctly solved without using stochastic approach. This is due to mapped states being dependent on other mapped states and the localization state. This dependence also make the problem complex, therefore a simple approach such as representing all correlations is not tractable for large numbers of states.
Bayes++ has been used to implement various simple and some more advanced SLAM solutions. In particular a full implementation of FastSLAM has been implemented. This technique is described in the paper "FastSLAM : Factored Solution to the Simultaneous Localization and Mapping Problem", M. Montemerlo, S. Thrun S, D. Koller, B. Wegbreit, Proceedings of the AAAI National Conference on Artificial Intelligence 2002.
The Bayes++ implementation of FastSLAM and a very simple Kalman (full correlation) SLAM implementation is available as part of the most recent download.
These mathematical tools are particularly useful for visualising filtering results. However they are all rather slow, and it is very easy to produce very poorly implemented filters in their programming languages. Fortunately all these tools provide mechanisms for extension with external programs. Example interface code is provided in the Bayes++ GIT repository for Matlab.
Bayes++ only makes use of ISO standard C++. The source code uses moderately advance C++ constructs. It only makes restricted use of the C++ template system directly. However the Boost libraries used (in particular uBLAS) make extensive use of template techniques. Boost also includes many workarounds for compiler deficiencies. Therefore with few alterations Bayes++ should work with any modern C++ compiler supported by Boost.
Bayes++ is tested with: GCC 4.x, and VisualC++ 2008
Later versions of GCC 3.x and GCC 4.x should also run Bayes++ with ease. However GCC 3.3.0 is know to be incompatible with uBLAS and to produce incorrect code with -O2 optimization.
VisualC++ 7.1 often requires the /Zm option to be used so it can compile complex headers.
This releases is validated using the compilers and Boost versions listed above using the following tests.
Build system: Compatibility with Boost Build version 2.
Successfully complete build of default
libraries and examples.
Successfully complete build of
SLAM system.
Test examples: simpleExample, PV, QuadCalib
Compile debug
and release builds (using Boost Build version 2) :- with no errors
and no warnings.
Execution output :- Identical to expected
reference results.
Numerical tests: rtheta - Range angle observer.
A
non-linear range angle observer test. The observer moves in a 2
dimensional state space. Motion prediction occurs with a linear
model with additive noise. The two states are coupled both in the
model and in additive noise. Range and angle of a fixed target is
observed. The target is placed so discontinues angles are
observed.
Both the state and the observations have additional non
observed (singular) states. Model sizes, coupling parameters and
model types can be varied for additional tests. All schemes are
tested over 5 iterations of the model. The SIR scheme is
tested with 1000 samples.
Because the different numerical
implementations results are not expected to be identical between
Schemes. Therefore testing requires:
Regression testing :-
Changed in output for any Scheme from the previous
release.
Consistency testing :- Comparison of the output for
Scheme pairs know to produce numerically similar results.
SLAM test: testFastSLAM
Consistency testing :- Comparison
of FastSLAM result with 1,000,000 samples with Kalman SLAM.
Deviations of state and covariance expected to be approx 1/1000th.
Tested with Boost 1.55.0 and gcc-4.8.
Document that b2
requires link=static
option when compiling examples.
Recommend using cxxflags=-Wno-unused-local-typedefs
for the GCC toolset, to avoid lots of warning text with GCC 4.8.
Renamed all classes which were previously named 'addative' to be called 'additive'.
Tested with Boost 1.49.0.
Cleanup comments in source.
Cleanup documentation and build files to make things build easily.
Support for and requires Boost 1_33_0.
The list of compilers for which Bayes++ is built and tested has been update.
New Documentation and support for Boost 1_32_0.
Sample covariances are now computed using the definition for the Maximum Likelihood (biased) estimate. This estimate simply devides by 1/n the number of samples, rather then 1/(n-1). See Sample Statistics in Wikipedia.
The list of compilers for which Bayes++ is built and tested has been update.
Corrects documentation and support for Boost Build (version 1).
SLAM has been updated from the current development version.
GCC 3.4 requires a couple of typename fixes to uBLAS (Boost_1_31_0 or earlier).
Bayes++ is tested with both Boost-1.30.2 and Boost_1_31_0.
Jens Mauer has been working hard on getting boost::random accepted as part of the future C++ standard library. To this end there have been substantial changes to its interface. The new library is now part of Boost_1_31_0. The Bayes++ examples make use of boost::random. So things migrate smoothly I have added a new "test/random.hpp" header which hides the interface changes.
The very excellent Boost Build system version 2 has advanced a great deal recently. Bayes++ is built with standard Boost Build system. Bayes++ has all the necessary "Jamfiles.v2" to be build with the Boost Build system.
The UD_scheme observe functions have had their numerical capabilities extended. It is now possible to work with singular (zero variance) covariance matrices.
The Unscented_scheme has additional function init_XX() and update_XX() to allow access to an Unscented state representation.
An error in SIR_kalman_schemes covariance calculation has been fixed. This error also effected the Fast_kalman_SLAM implementation. The error was significant for small small sizes.
For efficiency it is important to avoid creating temporary matrix and vector copies. Unless told otherwise it is not possible for uBLAS to determine if the same matrix or vector variable is specified on both the left and right hand side of an assignment operation. If such variable does appear it is said to be an alias. Because assignment involves more then one element, the presence of an alias requires that an assignment first compute a temporary result before the aliased variable is modified.
uBLAS's default behavior is to create such a temporary. If the assignment is know to be free of an alias this should be avoided. Previously such an optimized assignment was specified with the .assign() member functions. To improve the readability of code I have added a new syntax for assignment. Where no aliases of variable assigned to (lvalue) appears in the expression on the right hand side of the assignment use:
noalias(lvalue) = expression;
This new syntax is experimental but will probably be part of a future uBLAS release. At present the implementation introduces a small overhead on the supported compilers. This includes GCC 3.2.
Abstract filters and numeric schemes previously all had names ending in _filter. To make things simpler the naming has been changed to make a clear separation in what is a two level hierarchy.
Filters lie at the base of the hierarchy. Schemes are always derived from one of more filters. Filters represent abstract concepts, such as the statistics of state representation and model interface. Schemes are concrete implementations of a filter with all the numeric details and interfaces completed.
As part of this change the statistics of state representation have been made virtual base classes. This change is designed to allow multiple schemes combined together (using multiple inheritance) and share their representation. The change adds a little more work if you choose to derive from a scheme class. The constructors for the derived class must call the constructors for the virtual base classes directly.
Finally the CI algorithm has been implemented as a Scheme
in Bayes++. CI is interesting as it provides a weaker but more robust
fusion then traditional covariance based method such as the Kalman
filter. It estimates state and an upper bound of what its covariance
could be.
Actually only the matrix algebra associated with CI
has is included. The CI_filter scheme provides a virtual function
where the user must define the actual optimization algorithm to be
used.
The flexibility of the SIR_filter has been greatly improved. A new class Importance_resampler has been added. Whenever SIR_filter need to re-sample it uses and Importance_resampler parameter. Therefore by changing this parameter, different re-samplers can be used.
Two implementation are provided. The Standard_resampler and the Systematic_resampler. See the referenced publications for further discussion of these methods.
The matrix interface has been further improved. These improvement require uBLAS from boost_1_30_0. With this version there is experimental support for using uBLAS gappy matrices and vectors (sparse, compressed, coordinate).
The experimental support makes all of Bayes++ use a selected uBLAS storage type. Check matSupSub.hpp for macro's required to enable this. The algorithms used is Bayes++ are being upgraded to perform better with sparse types.
The mult_SPD products are no longer supported. They are replaced with the prod_SPD interface.
Copyright (c) 2003, 2004, 2005 Michael Stevens. This document is part of the Bayes++ library - see licensing section for copyright license details.


Unfortunately the assistant couldn't fix your problem. Contact our technical support:
Telephone: 0123-456788
Telephone 2: 0123-456789
You can also reach us via Telegram and WhatsApp.
Alternatively via E-Mail:
<EMAIL_ADDRESS>Or ask in our chillout room:
WebEx chillout room
The following code can help our support staff to see what you've tried already:
Code: ---PATHCODE---


--- layout: post title: "the measure of a man" comments: true ---
Data: Is it not true that had you refused to prosecute, Captain Louvois would have ruled summarily against me?
Riker: ...Yes
Data: That action injured you, and saved me. I will not forget it.
Riker: You're a wise man, my friend.
Data: Not yet sir, but with your help, I am learning.


Why do we care about smart contract security?
- Once deployed, immutable and publicly accessible
- Testing can only prove the presence of bugs, not absence
- DAO hack 2016 - US$150 million
- Parity wallet hack - US$150 million
Static Analysis
- Static Analysis is performed by reviewing the source code without running the program
- It is mostly for ensuring proper coding standards, best practices, syntax errors, etc
Static Analysis
Static Analysis
Static analysis
- False Positive on infinite gas for dynamic arrays such as string
Dynamic Analysis
- Analysis is performed by executing the program
- Unit testing is a type of dynamic analysis
Symbolic Analysis
- Symbolic Analysis performs code path analysis on a program and generates test input to verify program
MythX - Remix Plugin
Remix - Detection of Integer underflow
Require and Assert
require
: used as specifications
assert
: used as proof
Solidity with SmtChecker
- Video demo of the use of solidity smtchecker:
- Solidity with z3
Fuzz Testing
- An automated software testing technique that involves providing invalid, unexpected, or random data as inputs to a computer program.
Fuzzer classification
- Fuzzers take a set of program inputs and generate new ones automatically. Fuzzers are based on how much information they collect about a program
- Blackbox fuzzer
- Whitebox fuzzer
- Greybox fuzzer
Blackbox fuzzer
- Black-box fuzzers do not collect any information about the program and typically perform random mutations to an input before running the program with it.
- They are easy to implement and can try millions of different inputs within minutes
- However, they struggle with achieving high code coverage for complex code.
Whitebox fuzzer
- White-box fuzzers symbolically execute each instruction run by a given input and use automated solvers (e.g., SMT/SAT solvers) to find new inputs to cover a new execution path.
- Typically, these tools are very effective at covering new paths.
- This is known as the path explosion problem and most fuzzers use heuristic search strategies to cover “interesting paths”.
Greybox fuzzer
- They use light-weight program instrumentation to record the execution path for each tested input and compute its path identifier.
- Many state-of-the-art tools use sophisticated evolutionary algorithms to select which inputs to fuzz.
- Able to achieve high code coverage even for complex code without using more expensive techniques, such as automated solvers, to reason about the program.
Echidna
- Uses property testing to generate malicious inputs that break smart contracts
Limitations
- All tools still have limitations
- Not all vulnerabilities can be found by analysis
- Not scalable to large or complex programs
- Still need to do manual auditing and testing
Bonus Lab
- Analyze the supplied contract and fix all the errors and warnings if possible


Login Page
Invalid username/password.
×
You are now logged out.
×
Username
We'll never share your details with anyone else.
Password
Check me out
Submit


| Overview | Module | Use | Devguide | Index |
| Elements' Summary | Elements' Details |
| exception JavaInitializationException |
|
|
Copyright © 2013, The Apache Software Foundation, Licensed under the Apache License, Version 2.0. Apache, the Apache feather logo, Apache OpenOffice and OpenOffice.org are trademarks of The Apache Software Foundation. Other names may be trademarks of their respective owners.


Visual Studio
ASP.NET MVC
LINQ
Entity Framework
Debugging Tools
TFS & Git Integration
HTML5
CSS3
bootstrap4
jQuery
MSSQL
LINQ to SQL
Git
TFS
Agile
Scrum Management
I worked as a summer full-stack developer intern on the Blue Ribbons Review website team. Blue Ribbons Review is a
ASP.NET MVC based website where customers can browse deeply-discounted products found on Amazon.com and also leave reviews for them.
As an intern I completed both front- and back-end stories in the Blue Ribbons Review Code First Entity ASP.NET MVC web application. I compiled a detailed account of some of these
stories in the README file on my project GitHub (here)
The Tech Academy* is a licensed career school, focused on teaching computer programming and web development, located in Portland, OR.
I began courses in early January and plan to complete the program in late-May 2018.
During the course of the program I will be learning: HTML, CSS, databases and SQL, JavaScript, Visual Studio, C# and ASP.NET, Agile and Scrum management, and be completing a live project.
*Voted Best Boot Camp in Portland, Best Boot Camp in Seattle and 7th Best Boot Camp in the world by SwitchUp.org
My time at PPS began working as clerical support in the Human Resources Dept., before I quickly moved up into a role as an HR Associate in the Benefits Dept.
As a Benefits Associate I worked as a part of a close team to administer and organize benefits programs for 6000+ employees.
I performed technical work inputing a variety of employee benefits data into our HRMS and verifying the accuracy of input and output data.
I also assisted with the implementation of a new Peoplesoft Benefits Administration module (for online enrollment), helping with testing and user-friendliness of the system.
In addition to my technical duties I also worked in a customer service capacity to help explain district benefits, respond to inquiries, and assist and advise employees with benefit plan selection.
As a Guest Services Ambassador I managed affairs at a stadium entry (Gate 5), assisting with directions and ingress and egress for thousands of fans.
I also worked to resolve unexpected issues (ticketing problems, customer complaints, medical and other emergencies) and helped to train many fellow employees working at stadium entry.
Employee of the Year, Guest Services - 2015
Employee of the Month, Guest Services -
May 2015
I graduated summa cum laude with a bachelors degree from Portland State University in 2015. Studying history and social science helped me work to become an accomplished analytical writer and critical thinker. I also spent time learning about local/global systems and the basics of ArcGIS as a geography minor.


Storage
Manage the stored queries on the system.
| ID | Type | Time Range | Generated | Database | Measurement | Field | Tag | Aggregate |
|---|
{% extends "base.html" %} {% set page_title = 'storage' %} {% block content %}
Manage the stored queries on the system.
| ID | Type | Time Range | Generated | Database | Measurement | Field | Tag | Aggregate |
|---|


WHERE THE HEART IS RATING: 7 /10 --> Good movie
For more reviews and movie screensavers, http://www.joblo.com/
This is the third Saturday night "sneak preview" that I've seen in the past month, and the third "audience-friendly" flick of the bunch. Of course, it only makes sense to preview movies which will most likely have the Jones' recommending it to their co-workers come Monday morning water cooler time, and such tactics certainly didn't hurt either KEEPING THE FAITH or RETURN TO ME, which both received great word of mouth (also known as "free advertising" in the marketing world). So will the masses enjoy this one? Read on...
 The resourceful girl manages to live inside the market for about six weeks, ends up delivering the baby at the store and must ultimately learn to survive despite the cavalcade of obstacles which continue to be thrown her way.
CRITIQUE: The white-trash feel good hit of the year! Harumph...okay seriously, although many will ultimately dismiss this film as the grand-daddy TV movie of the week, I enjoyed much of it based solely on the excellent performances put forth by five great actresses. Natalie Portman, leaving Queen Amidala in the dust, with a subdued performance, just begging people to love her even more than they do now. Ashley Judd, looking sexy without even trying, with a great supporting role as the surrogate big sister to Portman, a woman who probably needs more help than anyone in this film. Stockard Channing, Rizzo to me always, with not a whole lot of time on the screen, but certainly a lot of punch in her few moments. Joan Cusack, a woman who can't help but deliver great performances one after the other, with another cool and funny character, not as goofy as usual, but entertaining just the same. And Sally Field, a woman who spends no more than five minutes in this film, with a dead-on manifestation of the ultimate white-trash mommy dearest. And the men you may ask?
Well, it's probably better if you didn't ask, since the world in which these women live apparently doesn't provide for many decent men. That is, if you don't count the old man who boinks Ms. Channing on the kitchen table every now and again. Granted, the film certainly does play out like the ultimate soap opera, but in the end, nothing really bored me. I had a few laughs here and there, shed a couple of internal "guy-tears", yessiree-bobee, and golly gee, who the heck wouldn't want to watch these two beautiful leading ladies prance around the big screen all day long. I know I sure wouldn't mind. And is it just me, or did Natalie Portman actually start looking like Ashley Judd in a few choice scenes? But enough about that. In the end, most anyone should be appreciative as to the sentiments which carry Portman's character through the tough times, learning as she goes along and ultimately making the best out of what she's been handed. It certainly is a triumph of the spirit (am I quoting Oprah now?).
So piss on me all you want if you think I am recommending this film solely on the extreme appeal of the actresses, but there are many reasons why some movies work and others don't, and a lot of it has to do with the performances.  Of course, I also thought Natalie Portman looked kinda sexy while she was preggers, but that's a subject which only my psychiatrist can explain.  You go, girl!
Little Known Facts about this film and its stars: Unsure about whether or not she wants to continue her career as an actress, Natalie Portman is currently attending Harvard University full-time, studying in psychology. According to her, she will not act in any other films, besides the two Star Wars prequels, over the next four years, so that she could concentrate on her studies. She once said that when she "got older", she would like to be a doctor just like her father. Natalie was born in Jerusalem, Israel, moved to the States at the age of 3, and uses her grandmother's maiden name (Portman), to protect her privacy. She's also fluent in French, Hebrew and Japanese. Boy-oh-boy...is there anything this great girl can't do?! Wow. In case you're like me and wondered where you'd seen the "nice guy" in this movie before, the character of Forney played by James Frain, he recently played Ben Affleck's good friend in REINDEER GAMES. Natalie Portman's character is superstitious about the number 5 in this movie. In the novel on which this movie is based, written by Billie Letts, the lead character is actually superstitious of the number 7. This is the directorial debut of Matt Williams. He is best known as the co-creator of TV's "Roseanne" show and "Home Improvement". This film was originally titled HOME IS WHERE THE HEART IS, which might've been a better idea considering that Paul Newman's WHERE THE MONEY IS was released just last week.
Review Date: April 21, 2000 Director: Matt Williams Writers: Lowell Ganz and Babaloo Mandell Producers: Matt Williams, Patricia Whitcher, David McFadzean and Susan Cartsonis Actors: Natalie Portman as Novalee Nation Ashley Judd as Lexie Coop James Frain as Forney Genre: Drama Year of Release: 2000 ------------------------------------ JoBlo's Movie Emporium http://www.joblo.com/ ------------------------------------ (c) 2000 Berge Garabedian
The review above was posted to the
rec.arts.movies.reviews newsgroup (de.rec.film.kritiken for German reviews).
The Internet Movie Database accepts no responsibility for the contents of the
review and has no editorial control. Unless stated otherwise, the copyright
belongs to the author.
Please direct comments/criticisms of the review to relevant newsgroups.
Broken URLs inthe reviews are the responsibility of the author.
The formatting of the review is likely to differ from the original due
to ASCII to HTML conversion.
Related links: index of all rec.arts.movies.reviews reviews


Principle-based Explanations of Change in QBAFs
#### Idea
* We want to explain change of inference in QBAFs
* What is *change*?
$\rightarrow$ Arguments $a, b$ change rank in the order established by the total strength function:
First: $a \succeq b$ then $b \succ a$ or vice versa
* What are explanations?
$\rightarrow$ All arguments that change (or are added), so that they are more
'favorable' for $b$ than for $a$ in the updated QBAF, in comparison to the initial QBAF
Preference Consistency
Let $Q = (X, R^-, R^+, \tau)$ and $Q' = (X', R^{'-}, R^{'+}, \tau')$ be QABFs and let $\sigma$ be a strength function.
$Q$ and $Q'$ are preference consistent w.r.t. $\sigma$, denoted by $C^{\sigma}_{\succeq}(Q, Q')$ iff the following statements hold true $\forall a, b \in X$, such that $a, b \in X'$:
1. If $\sigma_Q(a) > \sigma_Q(b)$ then $\sigma_{Q'}(a) > \sigma_{Q'}(b)$
2. If $\sigma_Q(a) < \sigma_Q(b)$ then $\sigma_{Q'}(a) < \sigma_{Q'}(b)$
3. If $\sigma_Q(a) = \sigma_Q(b)$ then $\sigma_{Q'}(a) = \sigma_{Q'}(b)$
Similarly, we can say that $a, b$ are preference consistent in $Q$ and $Q'$ w.r.t. $\sigma$: $C^{\sigma}_{\succeq, Q, Q'}(a, b)$
(Somewhat similar to notions in micro-economic theory)
Preference Consistency is:
* Transitive
* Symmetric
* Reflexive
Explaining Inconsistent Preferences I
* Let $Q = (X, R^-, R^+, \tau)$ and $Q' = (X', R^{'-}, R^{'+}, \tau')$ be QABFs and let $\sigma$ be a strength function.
* We need explanations for all $a, b \in Q$, such that $C^{\sigma}_{\succeq, Q, Q'}(a, b)$
* For all $c \in X \cup X'$, we say:
* $c^{a+}$/$c_{b+}$ iff $c$'s support for $a$/$b$ is stronger in $Q'$ than in $Q$
* $c^{a-}$/$c_{b-}$ iff $c$'s support for $a$/$b$ is weaker in $Q'$ than in $Q$
* $c^{a=}$/$c_{b=}$ iff $c$'s support for $a$/$b$ is the same in $Q'$ as in $Q$
Explaining Inconsistent Preferences II
If $a \succeq b$ in $Q$ but $b \succ a$ in $Q'$: explanations in red
| $c^{a+}_{b+}$ |
$c^{a+}_{b=}$ |
$c^{a+}_{b-}$ |
$c^{a+}_{b++}$ |
| $c^{a=}_{b+}$ |
$c^{a=}_{b=}$ |
$c^{a=}_{b-}$ |
- |
| $c^{a-}_{b+}$ |
$c^{a-}_{b=}$ |
$c^{a-}_{b-}$ |
$c^{a--}_{b-}$ |
$b++$ indicates that the argument increases support for $b$ more than it increases support for $a$
$a--$ indicates that the argument decreases support for $a$ more than it decreases support for $b$
#### Explaining Inconsistent Preferences III
* We can do this for different change scenarios
* We can determine $\subseteq$-minimal explanations, given the delta that is needed for the change in rank
#### Path Forward?
1. Work out theory during the next ~3-6 months
2. a. Theory-only, then it can be combined with abstract arg. paper
2. b. Experimental evaluation, then we need dataset, perhaps collaborators


The EvitaWrapper class is handed the TarsqiDocument and loops over all docelement Tags in it, creating an Evita instance for each of them and then procesing the elements one by one. The Evita instance has slots for the TarsqiDocument, the docelement tag and a TarsqiTree instance which contains a document tree for the part of the TarsqiDocument that is being processed. The TarsqiTree instance itself knows what TarsqiDocument it belongs to and what docelement Tag it was created for since these were handed in from the Evita instance. The TarsqiTree instance also has a list of daughters as well as some other attributes that are ignored here because they are not used by Evita.
| components.evita.main.Evita | |||||||||
| tarsqidoc | an instance of docmodel.document.TarsqiDocument | ||||||||
| docelement | an instance of docmodel.document.Tag with name=docelement, the element of the TarsqiDocument that is being processed by Evita | ||||||||
| doctree |
|
Since the TarsqiTree and its elements are the starting point for Evita and Slinket processing we will dwell on them a bit longer. Here is a pretty print of the TarsqiTree for "The dog barked yesterday.".
<Sentence position=0> <NounChunk position=0 checkedEvents=False event=None eid=None> <Token position=0 pos=DT text=The> <Token position=1 pos=NN text=dog> <VerbChunk position=1 checkedEvents=False event=None eid=None> <Token position=0 pos=VBD text=barked> <NounChunk position=2 checkedEvents=False event=None eid=None> <TIMEX3 tid=t1 type=DATE value=20160103> <Token position=0 pos=NN text=yesterday> <Token position=3 pos=. text=.>
A TarsqiTree contains sentences, chunks, tokens and event and time constituents. It is created from a TarsqiDocument and a Tag by the create_tarsqi_tree() method in components.common_modules.tree. This method uses the intermediary Node object to create a tree hierarchy and then replaces all Node objects with instances of Sentence, NounChunk, VerbChunk, Token, AdjectiveToken, EventTag and TimexTag (all defined in submodules of components.common_modules). These tree elements are all subclasses of Constituent and have the following instance variables:
| components.common_modules.constituent.Constituent | |
| tree | contains the TarsqiTree instance at the top of the tree, through this tree a constituent also has access to the TarsqiDocument and the Tag |
| parent | a reference to the parent, which is an instance of TarsqiTree or one of the subclasses of Constituent |
| position | an integer reflecting the constituent's position in the dtrs list of the parent |
| dtrs | a list of daughters, this is the empty list for leaf nodes |
| begin | the beginning offset in the SourceDoc |
| end | the ending offset in the SourceDoc |
The TarsqiTree is used by Tarsqi components as a common data structure to process over. For example, Evita and Slinket both run patterns over elements of this tree and major parts of the Evita and Slinket code are expressed as methods on constituents. Components may update elements of the tree, but it is important to note that those changes are local and will not be handed over to a next component in the pipeline. Instead, results from processing have to be exported to the TagRepository on the TarsqiDocument, as in the following figure.
Components import the TarsqiDocument and for each Tag create a TarsqiTree using the TarsqiDocument's data. They then use this sequence of trees one by one as input to processing and export the resulting tags back into the TagRepository. The next component in the pipeline will start afresh with a new set of TarsqiTrees which will be created from the updated TarsqiDocument.
Back to Evita...
The EvitaWrapper takes the TarsqiDocument on initialization and its process() method loops over all document elements, creating an Evita instance for each of them and then running the process_element() method. The process_elements() method loops through all Sentence instances in the TarsqiTree in Evita's doctree variable, and then loops through all daughters of the Sentence. For each daughter it attempts to create an event with the createEvent() method, which is implemented on the NounChunk and VerbChunk classes.
As an illustration, below is a fragment from the code in the Evita class in components.evita.main. Note that the code is slightly simplified and edited and that it is not well-formed Python code anymore, this is true for all code fragments shown in this document.
components.evita.main.Evita process_element(): self.doctree = create_tarsqi_tree(self.tarsqidoc, self.docelement) for sentence in self.doctree: for node in sentence: if not node.checkedEvents: node.createEvent()
Nominal events are created with createEvent() on NounChunk and verbal and adjectival events are created with createEvent() on VerbChunk. Adjectival events are initially dealt with by VerbChunk because they are created only if preceded by certain verb groups, which is recognized by VerbChunk. The following three sections give details on how the three kinds of events are created.
Most of the code that deals with nominal events is expressed on the NounChunk class, which is a sublass of Chunk and Constituent. Recall that Constituent defines instance variables tree, parent, position, dtrs, being and end. These are all filled in during TarsqiTree construction by create_tarsqi_tree(), as mentioned earlier in this section. Several other instance variables are defined on chunks. The table below has just the variables added by NounChunk that are relevant for Evita.
| components.common_modules.chunks.NounChunk | |||||||||||||
| phraseType | the chunktype, basically the chunk tag generated by the chunker, always 'ng' for noun chunks | ||||||||||||
| head | an integer reflecting the position of the head token in the chunk's dtrs variable, always set to -1 for noun chunks, picking out the last element | ||||||||||||
| gramchunk |
|
||||||||||||
| gramchunks | the empty list for noun chunks, but can be non-empty for verb chunks | ||||||||||||
| checkedEvents | a flag indicating whether the chunk has already been checked for events, initially set to False; if set to True, createEvent() will never be run for the chunk |
The GramNChunk instance in the gramchunk variable contains the grammatical features for the noun chunk. This instance has a pointer back to the NounChunk it is in and four grammatical features. Three of them are typically 'NONE' for nouns, and it may sound a wee bit odd for nouns to have tense, aspect or modality, but in some cases the nominal will inherit these from a governing verb, for example, with phrases like "This would be a tragedy". When the verb chunk "be" tries to create an event it will recognize that the actual event is the nominal following it, it will then try to create an event on that nominal and hand it the verb chunk features. This is explanined further below in the section on verbal events.
The top-level of the createEvent() code for nominals looks as follows:
components.common_modules.chunks.NounChunk createEvent(self, gramvchunk=None): self.gramchunk = GramNChunk(self, gramvchunk) if self.isEventCandidate(): self._conditionallyAddEvent()
GramNChunk creation for the NounChunk is a simple affair, setting the defaults and then leting them be overwritten if features were handed in from the governing verb. The main work occurs in the isEventCandidate() method on the chunk, which first checks whether the noun chunk is syntactically able to be an event, which is the case if the chunk has a head, the head is a common noun and the chunk is not a time expression. Next, it checks whether the noun chunk can semantically be an event. It does this by looking up the head token in Wordnet and by running a simple Bayesian classifier. This is where the heavy lifting occurs. The general logic is as follows:
The exact application of this logic is driven by settings in the components.evita.settings module, which has a couple of variable that determine whether the Bayesian classifier is used and how WordNet lookup determines event-hood.
components.evita.settings EVITA_NOM_DISAMB = True EVITA_NOM_CONTEXT = True EVITA_NOM_WNPRIMSENSE_ONLY = True
The first variable determines whether the classifier will actually apply and the second whether the classifier will take into account contextual features (as opposed to just the word). The third variable determines the choice to be made in step 3, the default is to decide that a token is an event if its primary sense is.
The resources used by the logic above are in library/evita/dictionaries. Here is a short desciption of the WordNet and classifier resources.
'drawing': [12.0, 2.0], 'negligence': [0, 2.0], 'detail': [33.0, 9.0], 'absorption': [0, 7.0], 'crack': [6.0, 1.0],From this fragment you can read that there were 12 occurrences where 'drawing' was not an event and 2 occurrences where it was. (By the way, it is not clear why these numbers are floats, probably a historical accident). The file semcorNomEventContextProb.pickle contains probability adjustments for the nominals given a small amount of features (definite versus indefinite and singular versus plural). The numbers are adjustments for the non-event probability and the event probability respectively. Adjustments for two of the nominals above are given below.
'drawing': { 'DEF': (0.1, 0.1), 'INDEF': (0.9, 0.9), 'NN': (0.34, 0.9), 'NNS': (0.66, 0.1) } 'absorption': { 'DEF': (0.5, 0.166666), 'INDEF': (0.5, 0.833333), 'NNS': (0.5, 0.3), 'NN': (0.5, 0.7) }For example, if we take 'drawing', which has a proability of 0.14 of being an event and 0.86 of not being an event, and say that we have the features INDEF and NN, then the adjusted event probability would be 0.14 * 0.9 * 0.9 = 0.11 and the adjusted non-event probability would be 0.86 * 0.9 * 0.34 = 0.20, after which the adjusted chance of not being an event is still bigger. Note that the combined probabilities are not 1 anymore. There is some ancient code in library/evita/nominal_trainer.py which does not work, but which was originally used to create the pickle files. The content of the pickle files is also listed in a friendlier format in files with the .txt extension in the same directory.
Back to the Evita nominal event logic. If the isEventCandidate() method returns true then the _conditionallyAddEvent() method will perform a few last checks and then add an event to the TarsqiDocument by asking the TarsqiTree to do the honours:
components.common_modules.chunks.Chunk _conditionallyAddEvent(self, gramChunk=None): gchunk = self.gramchunk if gramChunk is None else gramChunk if (gchunk.head and gchunk.head.getText() not in forms.be and gchunk.head.getText() not in forms.spuriousVerb and gchunk.evClass): self.tree.addEvent(Event(gchunk))
This method is defined on Chunk and is used by VerbChunks as well. The core is to invoke addEvent() on the TarsqiTree instance in the tree variable, handing it an Event instance which was created from the GramNChunk (or GramVChunk for verb chunks).
components.common_modules.tree.TarsqiTree addEvent(self, event): event_attrs = dict(event.attrs) eid = self.tarsqidoc.next_event_id() eiid = "ei%s" % eid[1:] event_attrs['eid'] = eid event_attrs['eiid'] = eiid token = event.tokens[-1] self.tarsqidoc.add_event(token.begin, token.end, event_attrs)
The TarsqiTree instance is handed most event features (tense and aspect and so on), but it is responsible for generating unique identifiers for the event (which it gets from the TarsqiDocument). Finally, it asks the TarsqiDocument to add the tag to the tags TagRepository, thereby exporting the component results as shown in the picture earlier in this section.


Trainer workout
What are you looking for
Are you a personal trainer ? Claim your personal trainer page now