Audience: LEWG, SG14
Document number:
Date: 2016-07-03
Project: Introduction of std::colony to the standard library
Reply-to: Matthew Bentley<EMAIL_ADDRESS>Introduction of std::colony to the standard library
I. Introduction
A colony is a C++ template-based unordered data container which provides
better performance than any std:: library container when:
- Insertions and erasures to the container are occuring frequently in
realtime ie. in performance-critical code, and/or
- Pointers to non-erased container elements must not be invalidated by
insertion or erasure.
It's predominant field of usage is game development, but subsequent reports
from high-performance computing and other domains have suggested it may be more
generically useful. While the benchmarks referenced in the appendix are a
better method for understanding the performance characteristics, the general
speed characteristics are:
- Insertion: better than any std:: library container except some
implementations of deque.
- Erasure: better or equal to any std:: library container.
- Iteration: better than any std:: library container where pointer
validity is important. Where pointer validity is unimportant, better than
any std:: library container except deque and vector.
As explored in the benchmarks there are some vector/deque
modifications/workarounds which can outperform during iteration while
maintaining pointer validity, but at a cost to usability and memory use.
Furthermore, when the ratio of insertions/erasures to iterations is greater
than 1% insertions/erasures per 3600 full iterations over data, Colony tends to
outperform these workarounds. Colony's other other advantages are freeing and
recycling unused memory on-the-fly, the guaranteed stability of
pointers/references to non-erased elements regardless of insertion and erasure
(which makes programming with containers of interrelated data structures faster
and much simpler). Iterators which do not point to end() or erased elements are
also guaranteed to remain stable.
A colony is it's own abstract data type. It is most similar to a "bag",
"bucket-array" or "multiset" ADT, but without key values. As it was initially
developed predominantly for game development, colony favours small and large
struct/class performance over scalar-type performance.
II. Motivation and Scope
When working on video game engines we are predominantly dealing with
collections of data where:
(Note: These requirements match other areas of software development as well,
but to simplify discussion I will focus on video game development)
- Elements within data collections refer to elements within other data
collections (through a variety of methods - indices, pointers, etc). An
example is a game entity referring to both a texture object and collision
blocks, as well as sound data. These references must stay valid throughout
the course of the game/level. For this reason, any container (or use of a
container) which causes pointer or index invalidation can create
difficulties or necessitate workarounds.
- Order is unimportant for the most part. The majority of data collections
are simply iterated over, transformed, referred to and utilized with no
regard to order.
- Storage of small-to-medium-sized classes and structs is the norm. Work
with collections of small scalar types like int, double is far less common.
Sometimes data can be stored in a SoA (Struct of Arrays) configuration, but
these cases are somewhat less common.
- Erasing or otherwise removing or deactivating objects occurs frequently
in-game and in realtime (though often erasures will be implemented to occur
at the end of a frame due to multithreading concerns). An example could be
destroying a wall, or a game enemy. For this reason methods of erasure
which create strong performance penalties are avoided.
- Creating new objects and adding them into the gameworld on-the-fly is
also common - for example, a tree which drops leaves every so often, or a
quadtree.
- We don't always know in advance how many elements there will be in a
container at the beginning of development, or even at the beginning of a
level during playback - an example of this being a MMORPG (massively
multiplayer online role-playing game). In a MMORPG the number of game
entities fluctuates based on how many players are playing, though there may
be maximum capacity limits. Genericized game engines in particular have to
adapt to considerably different user requirements and scopes. For this
reason extensible containers which can expand and contract in realtime are
usually necessary.
- Depending on the complexity and scope of any given game, we can be
dealing with anywhere between 10 and 100000 objects in a given area. We are
not typically dealing with the types of capacities necessitated by
large-scale mathematical or statistical applications.
- For performance reasons, memory storage which is more-or-less contiguous
is preferred. Lists, vectors of pointers to dynamically-allocated objects,
and maps as implemented in the standard library are unusable.
- Memory wastage is avoided, and in particular, any container which
allocates upon initialisation tends to be avoided as this can incur
purposeless memory and performance costs.
std::vector in it's default state does not meet these requirements:
- Poor erasure performance for large amounts of data (even with
remove_if duration is highly variable)
- Poor insertion (non-fll) performance due to reallocation
- Insert invalidates pointers/iterators to all elements
- Erase invalidates pointers/iterators/indexes to all elements
afer the erased element
- Requires single contiguous memory block (typically larger
than cache lines) which increases chance of allocation failures
for large amounts of data on insert
To meet these requirements, game developers tend to either (a) develop their
own custom containers for given scenario or (b) develop workarounds for the
failings of vector. These workarounds are many and varied, but the most common
are probably:
- Using a boolean flag (or similar) to indicate the inactivity of an object
(as opposed to actually erasing from the vector). When erasing, one simply
adjusts the boolean flag, and when iterating, items with the adjusted
boolean flag are skipped. External elements refer to elements within the
container via indexes rather than pointers (which can be invalidated upon
insertion).
Advantages: Fast erasure.
Disadvantages: Slow to iterate due to branching.
- Utilizing a vector of data with a secondary vector of indexes. When
erasing, the erasure occurs in the vector of indexes, not the vector of
data, and when iterating, one iterates over the vector of indexes, then
accessing the data from the vector of data via the index.
Advantages: Faster iteration.
Disadvantages: Erasure still incurs some reallocation cost, can increase
jitter.
- Combining a swap-and-pop mechanism with some form of dereferenced lookup
system to enable contiguous element iteration (known as a 'packed array',
or various other names). This technique allows for standard vector
iteration speed, but decreases lookup and referential performance. Erasure
speed is also fast unless elements are large and/or non-trivially
swappable.
All three techniques have the disadvantage of slow singular insertions, and
the first two will also continually expand memory usage when erasing and
inserting over periods of time. The third deals better with this scenario as it
swaps from the back rather than leaving gaps in the elements vector, however will suffer in performance if elements within the container are heavily referred to by external objects/elements, or if the elements are large and swap/copy is non-trivial.
Colony is an attempt to bring a more generic solution to this domain. It has
the advantage of good iteration speed while maintaining a similar erasure speed
to the boolean technique described above, and without causing pointer
invalidation (to non-erased elements) during erasure or insertion. It's insertion speed is
much faster than a vector's and similar to a good deque implementation's. Memory from erased elements is either reused by
subsequent insertions or released to the OS on-the-fly. It achieves these ends
by via a number of new approaches: a jump-counting
skipfield (instead of a boolean field), a linked chain of
increasingly-large memory blocks (instead of a singular memory block or vector
of blocks), and an internal high-performance stack structure to enable erased memory location re-use.
III. Impact On the Standard
No changes are necessary to the standard, asides from the introduction of the colony container. The reference implementation of colony is available here as
plf::colony.
IV. Design Decisions
There are three necessary aspects to colony which make it function as it
does, and which define any implementation:
- A multiple-memory-block based allocation pattern which allows for the
fast removal of memory blocks when they become empty of elements,
regardless of their location.
- A skipfield to indicate erasures instead of reallocating elements, the
iteration of which should typically not necessitate the use of branching
code.
- A mechanism for reusing erased element locations upon subsequent insertions.
In the case of the reference implementation I utilized a doubly-linked
intrusive list of 'group' structs containing (a) memory blocks, (b) memory
block metadata and (c) skipfields. The linked-list pattern removes the
possibility of non-O(1) operations when freeing empty memory blocks from the
colony structure, compared to a vector of pointers to memory
blocks. A vector of pointers to memory blocks may however enable faster insertions while increasing implementation complexity. Comparitive benchmarks would be necessary to establish overall optimal approach.
For the skipfield a boolean skipfield cannot be used:
- ++ iteration is O(random), iterators require O(1) operations
- Any boolean skipfeld creates branching code in the iterator
- Dependent on CPU branch prediction for performance
- Iterator code complexity
- Waste of 7 bits (and 254 states) per element if aiming for speed
(byte-level addressing- bool or char) rather than storage size
(bitfeld - slower)
For these reasons the reference implementation instead utilizes the jump-counting
skipfield pattern which allows for O(1) time
complexity iterator operations and performs better due to a lack of branching.
Iteration performance of vector with boolean skipfield vs colony with boolean skipfield vs colony with jump-counting skipfield:
For the erased location re-use mechanism, the reference implementation uses a stripped-down custom internal stack class based on plf::stack (plf::stack outperforms other std:: containers in a stack context across compilers).
Time to push all elements + read-and-pop all elements, plf::stack vs std::stack (std::deque) vs std::vector:
V. Technical Specifications
The key features of a colony are as follows:
- Unordered non-associative data container
- Never invalidates pointers to non-erased elements
- Reuses memory from erased elements or frees to OS
- Performance is oriented towards small-large struct/class storage rather
than scalar storage
- In the context of general game data (as described), should be faster than
any unmodified standard library container
- Iterators to non-erased elements guaranteed to stay valid unless iterator == end()
The full list of abstract requirements to support these features are as follows:
- Uses multiple memory-blocks – prevents element reallocation on insertion
Blocks are freed to OS once empty
- Blocks must be removable with low performance cost and without pointers
to elements being invalidated
- Has mechanism for reusing erased element locations upon insertion
- Erased elements recorded in a skipfield, skipped over during iteration -
prevents element reallocation on erasure
- Skipfield design must allow for O(1) ++ and -- iteration
Iterators are bidirectional but additionally support >, <, >= and <= operators for convenience.
ADL overloads for the standard library functions advance(), next(), prev() and distance() are available. These are significantly faster in most cases for colony than the equivalent standard functions.
Details on the chained-group allocation pattern are provided here.
Details on the jump-counting skipfield pattern are provided here, while benchmarks versus boolean skipfields are presented here.
Lastly, plf::stack (on which the colony internal stack implementation is based) is explained in detail here.
The reference implementation of colony is available to download here or via the github repository.
VI. Acknowledgements
Thanks to Jon Blow for initial advice, Mike Acton for influence, Glen Fernandes and Ion Gaztanaga for restructuring advice, Robert Ramey for documentation advice, various Boost and SG14 members for support, suggestions and bug reports including Sean Middleditch, Patrice Roy and Guy Davidson.
VII. References
Reference implementation (plf::colony) benchmarks
Benchmarks for GCC can be found here, while benchmarks for
MSVC can be found here


A person is a product of his experiences, and he seeks experience that paves the path towards his goals.
My natural proclivity is towards creation. Coupled with my curiosity towards sciences and design thinking, I find great purpose in designing, developing, and enabling adoption of complex ML/AI systems that people find useful in their lives. My quest to seek experiences, learn skills, master tools, and explore techniques are all targeted towards preparing myself in to a better, independent creator of ML/AI systems.


Kem chống nắng nivea
i'm a paragraph. Click here to add your own text and edit me. Let your users get to know you.
Mua ngay
Kem chống nắng nivea
i'm a paragraph. Click here to add your own text and edit me. Let your users get to know you.
Mua ngay
Kem chống nắng nivea
i'm a paragraph. Click here to add your own text and edit me. Let your users get to know you.
Mua ngay


Notice: This extension is bundled with Visual Studio Code. It can be disabled but not uninstalled.
This extension supports running npm scripts defined in the
package.json
as
tasks.
Scripts with the name ‘build’, ‘compile’, or ‘watch’ are treated as build
tasks.
To run scripts as tasks, use the Tasks menu.
For more information about auto detection of Tasks, see the documentation.
The Npm Script Explorer shows the npm scripts found in your workspace. The
explorer view is enabled by the setting
npm.enableScriptExplorer
. A script can be opened, run, or
debug from the explorer.
The extension supports to run the selected script as a task when editing
the package.json
file. You can either run a script from the
hover shown on a script or using the command
Run Selected Npm Script
.
The extension supports running a script as a task from a folder in the
Explorer. The command Run NPM Script in Folder...
shown in
the Explorer context menu finds all scripts in
package.json
files that are contained in this folder. You can
then select the script to be executed as a task from the resulting list.
You enable this support with the
npm.runScriptFromFolder
which is false
by
default.
The extension fetches data from https://registry.npmjs.org and https://registry.bower.io to provide auto-completion and information on hover features on npm dependencies.
npm.autoDetect
- Enable detecting scripts as tasks, the
default is on
.
npm.runSilent
- Run npm script with the
--silent
option, the default is false
.
npm.packageManager
- The package manager used to run the
scripts: auto
, npm
, yarn
or
pnpm
, the default is auto
, which detects your
package manager based on your files.
npm.exclude
- Glob patterns for folders that should be
excluded from automatic script detection. The pattern is matched against
the absolute path of the package.json. For example, to
exclude all test folders use ‘**/test/**’.
npm.enableScriptExplorer
- Enable an explorer view for npm
scripts.
npm.scriptExplorerAction
- The default click action:
open
or run
, the default is open
.
npm.enableRunFromFolder
- Enable running npm scripts from
the context menu of folders in Explorer, the default is
false
.
npm.scriptCodeLens.enable
- Enable/disable the code lenses
to run a script, the default is false
.


@Beta
public class Experiment
extends java.lang.Object
| Modifier and Type | Class and Description |
|---|---|
static class |
Experiment.DataSeriesSpec
A class indicating the variable corresponding to a data series in a graph,
as well as its directives (see
Gnuplot ). |
| Modifier and Type | Field and Description |
|---|---|
static java.lang.String[] |
guaranteedPreCommands |
| Constructor and Description |
|---|
Experiment() |
| Modifier and Type | Method and Description |
|---|---|
static void |
experiment(java.lang.Object... arguments)
Runs an experiment and generates a gnuplot with its results.
|
static com.sri.ai.util.experiment.Experiment.PreCommands |
getPreCommands(java.lang.Object... arguments) |
static java.lang.String |
getTitle(java.lang.Object... args) |
static void |
main(java.lang.String[] args) |
static com.sri.ai.util.experiment.Experiment.PreCommands |
preCommands(java.lang.String... preCommands) |
static com.sri.ai.util.experiment.Experiment.Title |
Title(java.lang.String value) |
public static void experiment(java.lang.Object... arguments)
The method works by generating a data matrix (according to RangeOperationsInterpreter
)
with one or two Dimension
s.
The plot may contain one or more data series (shown as lines on the plot).
A Experiment.DataSeriesSpec
object defines which Dimension
is used to define multiple data series,
as well as data series titles and format.
There is a commented example at the end of this documentation block.
Arguments to this method can be of three possible types:
DependencyAwareEnvironment
to be used
by the experiment (via DAEFunction
s -- see below).
RangeOperation
s, which work like for-loops (creating data matrix Dimension
s)
or aggregate operations for a specified variable.
DAEFunction
; this is the main argument since
this function is responsible for computing the experiment's reported results.
It can run whatever code one wishes, including calls to
DependencyAwareEnvironment.get(String)
,
DependencyAwareEnvironment.getOrUseDefault(String, Object)
and
DependencyAwareEnvironment.getResultOrRecompute(DAEFunction)
to gain access to the variables defined by other arguments
(both fixed and iterated by range operations).
The interaction between range operations and a DAEFunction
produces a generalized (multidimensional) matrix (see RangeOperationsInterpreter
for details).
In Experiment
, the range operations and DAEFunction must be structured
so that the resulting matrix is a regular rows-and-columns matrix
in which each row is the data for an individual data series to appear in the plot.
Experiment.DataSeriesSpec
, which declares gnuplot directives for each of
the data series (the several graph lines) in the graph (DataSeries
).
We obtain one data series per value of a variable specified by
the Experiment.DataSeriesSpec
.
The variable on the graph's x-axis is the one specified by the first Dimension
argument
that is not the variable labeling the multiple data series.
The recognized gnuplot parameters are the following:
Dimension
).
Consider the example:
experiment( "file", "false", "title", "The more samples, the less variance", "xlabel", "Number of samples", "ylabel", "Average of Uniform[0,1] + mean - 0.5", "some unused variable that could be used if we wanted to", 10, newHere, some gnuplot parameters and a (unused) variable are introduced. Then ranging operationsDimension
("mean", Util.list(2, 3)), newDimension
("numSamples", 1, 1000, 1), averageOfNumSamplesOfUniformPlusCurrentMeanMinusZeroPointFive,Experiment.DataSeriesSpec
("mean", Util.list( Util.list("title 'mean 2'", "w linespoints"), Util.list("title 'mean 3'", "w linespoints"))));
Dimension
is used to vary variables "mean" and "numSamples"
across a range of values.
The function averageOfNumSamplesOfUniformPlusCurrentMeanMinusZeroPointFive uses them to compute
the elements of a matrix.
The Experiment.DataSeriesSpec
specifies that the "mean" dimension is the one determining
the individual data series for the plot
(and as a consequence the "numSamples" dimension is selected for the x-axis),
and specifies their gnuplot labels and styles as well.
Note that the plot's y-axis does not correspond to any dimensions of the matrix, but to its values
(the ones computed by the DAEFunction
).arguments
- the experiments arguments.public static com.sri.ai.util.experiment.Experiment.PreCommands preCommands(java.lang.String... preCommands)
public static com.sri.ai.util.experiment.Experiment.PreCommands getPreCommands(java.lang.Object... arguments)
public static com.sri.ai.util.experiment.Experiment.Title Title(java.lang.String value)
public static java.lang.String getTitle(java.lang.Object... args)
public static void main(java.lang.String[] args)


Blood Source
Home
How to
Sign Up
Log In
About Us
Search
Blood Group
O+
O-
A+
A-
B+
B-
AB+
AB-
District
Sub District
Search


R/ess_all_rounds.R
This function is deprecated and will be removed in the next release. Use
import_all_rounds
instead.
ess_all_rounds(ess_email = NULL, only_download = FALSE, output_dir = getwd(), format = "stata")
| ess_email | a character vector with your email, such as<EMAIL_ADDRESS>If you haven't registered in the ESS website, create an account at
http://www.europeansocialsurvey.org/user/new. A prefered method is to login
through |
|---|---|
| only_download | whether to only download the files as Stata files. Defaults to FALSE. |
| output_dir | a character vector with the output directory in case you want to only download the files using
the |
| format | the format from which to download the data. Can either be 'stata', 'spss' or 'sas',
with 'stata' as default. When |
if only_download
is set to FALSE it returns a list with all the latest rounds.
If only_download
is set to TRUE and output_dir is a valid directory, it returns the
saved directories invisibly and saves all the rounds in the chosen format
in
output_dir
If only_download
is set to FALSE, the data will be read in the format specified
in format
. 'sas' is not supported because the data formats have changed between
ESS waves and separate formats require different functions to be read. To preserve parsimony
and format errors between waves, the user should use 'spss' or 'stata'.
# NOT RUN {<EMAIL_ADDRESS># Will download all rounds and return a list with each one ess_all_rounds() # Will download all rounds to the directory below # as .dta files and won't return the rounds in R. dl_dir <- file.path(tempdir(), "mydownloads") ess_all_rounds(only_download = TRUE, output_dir = dl_dir) # }


When I code I'm always having to use the internet. I know roughly what I'm trying to achieve, but there's always that thing I did a while back, or that code I know I have in another project that's hard to recall on the spot. That's why I've made this website.
I intend for this website to provide quick answers. Blogs and tutorials are great for learning new concepts and features, but when you kind of know what you're doing all you want is the code.
I'll attempt to keep posts on this website as small as possible and straight to the point. I'll also try my best to keep each post similar in format, with the goal of making content quick and easy to spot.
This is a side project to a side project, so if you find mistakes or would like to contribute, feel free to make a pull request on the GitHub repo.
~ Ross
Built with Jekyll.
Hosted on Github Pages.
Based on the Kactus theme.


Welcome to hopefully the first of a series of posts detailing my battles with technology. Trying to plug all the things together and make them play nice, and hopefully no big explosions. Always remember folks in infrastructure, “If anything exciting happens, we’ve done it wrong”.
We have recently been working on improving our test infrastructure. Previously this was a large bash script (as all the best projects are 😉) running within a single job on a Jenkins CI server. These tests are a mix of integration tests and unit tests, using nose for the backend tests and Jest for the frontend.  Including running the test suite this was taking in the region of 25 minutes, which invariably leads to distracted developers.
The main requirements we had for a new system were:
- It needed to be a drop in replacement in our build pipeline (e.g. there should be minimal changes outside the test infrastructure)
- The testing infrastructure should be easy to update and kept in SCM
- The tests should run in under 10 minutes
Given these restrictions, we decided to go was to keep using Jenkins CI and
use the Workflow plugin Pipeline plugin
to break up the test script into smaller executable chunks. The next part of
the puzzle was to use docker-compose
to manage the running of test services so that multiple instances of the tests
could be run at the same time on one machine without interfering with one
another1. Luckily the service requirements could all be described as
a one-to-many relationship from the test node, which simplified matters somewhat.
Dockerizing the test services
We store this configuration with the code repository, thus the storing the tests and associated configuration not only in one location but in lockstep with each commit of the code.
The next part was relatively straight forward, in fact in most cases we could simply use the images that were contained on the docker registry. Using docker volumes to link to any required configuration:
mongo:
image: mongo:3.0
command: --smallfiles
mysql:
image: mysql:5.6
environment:
- MYSQL_ROOT_PASSWORD=secrets
volumes:
- ./deploy/mysql/conf.d:/etc/mysql/conf.d
For the test node itself this was slightly more complex as it needed to be able
to access the other service containers as well as being built from a specific
Dockerfile
:
test:
image: $2
links:
- mongo:mongo
- mysql:mysql
- redis:redis
- solr:solr
The primary reason for using this method is to prevent the explosion in number of images created on the same box when running multiple instances, and also so when we move to multi-node we can grab the image from our registry rather than building it on each box.
Putting this all together we can construct a simple script to be run in
the checkout stage of the job. Firstly we would build from pre-made
Dockerfile
s the custom images we need and then output the correct
docker-compose file to STDOUT:
#!/bin/bash
short_hash=`git rev-parse --short HEAD`
build_tag="$(date -u +%Y%m%d-%H%M%S)-master-$short_hash"
docker build -t test:$build_tag .
cat <<EOF
mongo:
image: mongo:3.0
command: --smallfiles
mysql:
image: mysql:5.6
environment:
- MYSQL_ROOT_PASSWORD=secrets
volumes:
- ./deploy/mysql/conf.d:/etc/mysql/conf.d
test:
image: test:$build_tag
links:
- mongo:mongo
- mysql:mysql
EOF
Once we had this model in place it was easy enough to run multiple builds concurrently on the same instance without interfering with another test cycle, and relatively little performance impact, so while we could now run parallel builds we were still in the mid-twenty minutes per run range.
Designing a build flow with Jenkins pipeline
Next we needed to get these tests quicker, the one long running script wasn’t cutting the mustard anymore and needed to be sped up. The first part of this was to develop a simple model of how the tests should run:
The basic model shows ideally we would start by checking out all the required code for the test run, building the required docker images to run the tests, run all the tests, then collecting and publishing the results and artifacts.
Using the pipeline model we use the stage
step to separate the
job into sections:
Each stage
will run until all parts of that stage are complete before moving
to the next stage. The pipeline model unfortunately doesn’t have a good way of
fork/joining a job into complex workflows like we have described. So we end up
waiting for parts of the job we are not dependent on. For example, there is no
reason to wait for the frontend tests to complete if the docker images are
already built we should be able to start testing the backend immediately2.
Starting docker from the pipeline
First we have two companion functions to bring up and destroy the containers
using the sh
function and docker-compose
:
def startDockers(project){
// stop and destroy any existing containers
destroyDockers project
sh "docker-compose -p ${project} up -d"
// check that databases are accessible from within the container
timeout(time: 60, unit: 'SECONDS') {
sh "docker exec ${project}_test_1 /bin/bash -c 'while ! /usr/bin/mysql -uroot -psecrets -hmysql -P3306 -t -e \"show databases;\" > /dev/null 2>&1; do sleep 5; done;'"
sh "docker exec ${project}_test_1 /bin/bash -c 'while ! curl http://mongo:27017/; do sleep 5; done;'"
}
}
def destroyDockers(project){
sh "docker-compose -p ${project} stop && sudo docker-compose -p ${project} rm -f"
}
As docker-compose
doesn’t have a concept on waiting on dependent services we
use the timeout
workflow step to check they are up before returning to the
main flow.
So to run a group of the backend tests within a container we can use a node
like:
node {
dir('checkout') {
// where checkout is a frozen git repository
unstash 'checkout'
try {
startDockers 'tests'
// Run the test command within the container
sh "docker exec tests_test_1 /bin/bash -c 'cd /srv/app/; /srv/app-venv/bin/python manage.py test || true'"
// Copy results from the container
sh 'docker cp tests_test_1:/srv/app/nosetests.xml results.xml'
stash name: "results", includes: "results.xml"
} finally {
destroyDockers 'tests'
}
}
}
By using a try
-finally
we can ensure that if the tests fall over or are
aborted externally then the containers are still cleaned up.
While testing we found that docker images and volumes would hang around, unfortunately we still don’t live in a world with infinite disk space and found that fairly frequent cleanup is a necessity. Something like:
docker volume ls -qf dangling=true | sudo xargs -r sudo docker volume rm
docker rmi `sudo docker images -f dangling=true -q --no-trunc`
seems to do the job fairly well, while leaving the core images that don’t change per-build in place.
Again this offered comparable performance with the initial runs still hitting the mid-twenty minute range, however as the pipeline model allows the scripts to be stored in SCM we fulfilled one of the other requirements.
Using Jenkins Pipeline to run tests in parallel
Up until this point all the effort has been into containing the build within its
own isolated environment allowing multiple instances to run concurrently. To
speed up the execution of a single build we can use the parallel
step.
Expanding upon the previous code running within a docker container parallelise
the backend tests by adding:
stage name: 'test backend'
def numOfNodes = 8
// This function is documented below. But it returns a list of lists of
// modules to test. (e.g ["foo bar baz", "quz bam zoo", ...])
def testGroups = groupModulesToTest(readFile("results.xml"), numOfNodes)
tasks = [:]
// Within workflow we have to use this style for-loop because JENKINS-26481
for (int i = 0; i < testGroups.size(); i++) {
String moduleList = testGroups.get(i)
String nodeName = "${env.BUILD_ID}backend${i}"
tasks["test_${nodeName}"] = {
node {
dir('checkout') {
unstash 'checkout'
try {
startDockers nodeName
// Run the test command within the container
sh "docker exec tests_test_1 /bin/bash -c 'cd /srv/app/; /srv/app-venv/bin/python manage.py test ${moduleList} || true'"
sh "docker cp ${nodeName}_test_1:/srv/conversocial/src/nosetests.xml results.xml"
stash name: "${nodeName}_results", includes: 'results.xml'
} finally {
destroyDockers nodeName
}
}
}
}
}
parallel tasks
This will split into numOfNodes
groups (e.g. 8 in this example, should be Set
to the total number of executors to get best parallelism) and run a different
group of tests on each of the nodes.
This blog post won’t go into the details of the best way to get the list of evenly distributed test groups but the following is a start, simply breaking up the tests per top level module:
/**
* Returns groupings of a modules to test.
*
* @param xml String containing the text from a JUnit file.
* @param numGroups Number groups to divide the tests into.
*/
@NonCPS List<String> groupModulesToTest(xml, numGroups){
def testsuite = new XmlSlurper().parseText(xml)
def allModules = testsuite.testcase.collect {
it.@classname.toString().tokenize('.')[0]
}.toSet()
def int numPerGroup = Math.ceil(allModules.size() / numGroups)
allModules.toList().collate(numPerGroup).collect { group ->
group.join(' ')
}
}
The groupModulesToTest
function takes a JUnit test file as input. In our case
this can be generated before from the --collect-only
argument that can be
passed to nose
. However, in other cases it might be wise to balance them from
previous test runs; particularly if there is a large time variance across all
the tests.
This part had the biggest win on performance, this cut the test time down to
around 8 minutes! However, when lots of people were running the tests at the
same time, on the single instance, this could climb to double that. This
pointed out that we had perhaps put too many executors on the instance we were
using (in AWS this was an m4.2xlarge
@ 12 executors). But looking at the load
of each executor is important, where before each would be running a single
process each were now responsible for 3 containers.
Going multi-node
While it seems like every week AWS releases a new instance type
(m4.10xlarge
FTW! 😎) eventually our number of tests is going to
overtake even this. It would be better if the tests could be run across multiple
systems. Natively the pipeline plugin supports this, however, by adding docker
to the mix we added another dependency. Because the images that we build must
be available from any node that wants to run there needs to be a mechanism to
share these before. Along comes docker registry, but it does need a bit of a
re-jig of the test pipeline and we need to move the pushing of docker images
to into the building part of the job, they are then available for
any node from the registry.
Using the syntax:
node('master') {
...
}
operations can be locked to the master node. We found it improved performance when checking out the repositories if it was always on the same node, similarly for the building of the docker images. Additionally this means that only the master node has rights to checkout the repository and push to the registry which might be useful from a security perspective.
After doing this the tests now can run on any number of hosts. In AWS, we found that running the master on a reserved instance and the group of supporting servers on a spot instance-based auto scaling group as they are stateless and can be destroyed at any time, and are significantly cheaper than their on demand counterparts3.
Concluding Thoughts
Hopefully this post has been useful, and it has highlighted two distinct approaches that can be used in conjunction to give a fast, scalable model for running tests without need to change any of the core code in your application.
The first part is to isolate tests to allow them to work side by side, allowing many instances of the test suite to run concurrently, so many developers can run their tests at the same time.
The second is to parallelise the running of those tests so that many groups of tests can run at the same time, allowing the length of time to wait for tests to become a business decision over a technological one.
Finally we actually meat our goals:
✅ A drop in replacement in our build pipeline
✅ Testing infrastructure should be easy to update and kept in SCM
✅ The tests run in under 10 minutes, from the recently open-sourced stage-view plugin:
Footnotes
-
Ideally one would be able to separate out the tests so that the integration tests and the unit tests could be run independently so that this wouldn’t be such an issue. ↩
-
There is a workaround but changing our model to fit has a few potential gotchas, as the spin-waits have aback off means the job can take even longer when going in parallel, and it makes the job output and step views much more difficult to debug. ↩
-
As a side note we use Chef and the Jenkins cookbook to configure all these instances it’s not done by hand! ↩


Preparation time
1-2 hours
Cooking time
30 mins to 1 hour
Serves
Serves 4
Dietary
A classic of Italian cooking, spinach and ricotta gnocchi bear scant resemblance to the better-known potato gnocchi. Lighter and prettier and easier to make, they have a fabulous flavour and pretensions to healthiness, what with all that spinach.
For the gnocchi, place the thawed frozen spinach or cooked fresh spinach into a sieve to drain. Squeeze out as much water as possible, then weigh the spinach - you should have 250g/9oz of spinach after all the water has been squeezed out. Chop it up finely.
Place the ricotta into a large bowl and beat until smooth. Add the spinach, parmesan, flour, eggs and plenty of nutmeg. Season generously with salt and freshly ground black pepper and mix well with your hands, making sure it is evenly blended. Cover and leave in the fridge for an hour or more before moving on to the next step.
For the sauce, heat the oil in a large pan and fry the onion and carrot slowly until tender. Add the garlic and cook for another minute.
Add the tomatoes, tomato purée, caster sugar and the bouquet garni, then season with salt and freshly ground black pepper and stir. Leave to simmer gently for about 30 minutes, stirring frequently to prevent it from catching on the bottom, even adding a splash of water if necessary. Remove from the heat, remove the bouquet garni and allow to cool slightly.
Place the tomato mixture into a food processor and blend until smooth, then set aside.
Dredge a large plate with plenty of flour. Take dessertspoons of the chilled ricotta mixture, roll into neat balls, then roll in the flour. Place on a floured tray and set aside until needed.
Shortly before you intend to eat the gnocchi, bring a wide, shallow pan of water to the boil, then turn the heat down to a more gentle simmer. Carefully add your gnocchi to the pan, taking care not to overcrowd, and poach for 10-15 minutes, turning occasionally.
Meanwhile, gently reheat the tomato sauce.
When the gnocchi are cooked, remove them from the water with a slotted spoon and place onto warmed plates, or into one large shallow serving dish, and pour over the tomato sauce. Sprinkle with grated parmesan.


--- layout: 2018_default permalink: /faqs title: Frequently Asked Questions published: true ---
Below is a list of Frequently Asked Questions (FAQ).
No. You must register in advance for this event.
No. Although many of our presentations and tutorials are highly technical, our introductory sessions are geared to participants with no prior experience.
200+ Technical and Investment Professionals from around the World!
Our participants include students, industry professionals, engineers, researchers, entrepreneurs, investors, and those just curious to learn what all the fuss is about.
Yes. If you plan on following along with workshop tutorials, it is recommended that you pre-install recommended software ahead of time. Presenters may not take time to walk through the installation process.
Attend our optional software download and install mentoring session Friday evening. We'll have some mentors available throughout the weekend to assist as well.
Nothing compares to attending our sessions in person, whith one on one access to interact with presenters, mentors, and peers. We will provide live streaming of the forum on the Accel.AI Youtube account.
You may become an official sponsor of our event to have your company, product, or event featured on our marketing materials and during the event to our attendees.
Learn more about Sponsorship Opportunities!
We do not make announcements for non-related or unsponsored events or conferences at our gatherings. Distribution of flyers, printed media or other non related materials is not allowed at our events.
We do not offer refunds at this time.
We need volunteers to help make our forum amazing!
We value your time and contributions - volunteering gains you free entry!
Apply to volunteer here.
We highly reccomend using public transportation when attending this event.
If you must drive, there are several pay parking lots and street parking available near the venue. See top cheapest and closets garages here.
Our conference is dedicated to providing a harassment-free conference experience for everyone, regardless of gender, gender identity and expression, age, sexual orientation, disability, physical appearance, body size, race, ethnicity, religion (or lack thereof), or technology choices. We do not tolerate harassment of conference participants in any form. Sexual language and imagery is not appropriate for any conference venue, including talks, workshops, parties, Twitter and other online media. Conference participants violating these rules may be sanctioned or expelled from the conference without a refund at the discretion of the conference organizers.
For full version, please see: confcodeofconduct.com.
For further inquiries, kindly send us an email at aiff@accel.ai


All the global things we use are under governance. Like currencies, media, gasoline. Transnational corporations like Apple, Samsung, Louis Vuitton, etc. are under the management.
Earlier blockchain was a governance-free system, but now it’s time to change the game. It may seem disappointing because of the lack of freedom coming next to governance. But we need to go through this to popularize blockchain, make it a tool that will be implemented in our daily lives. If the government cannot control something, it forbids the thing. So we just need to calm down and understand the necessity of blockchain governance.
Blockchain governance will be nothing like the governance present in transnational corporations. Blockchain under the management will be as transparent and decentralized as it can. It will be a new form of governance we need to welcome the latest technologies in our daily life.
Blockchain has no one-size-fits-all governance strategy because it’s a new technology. But what we know for sure, it is decentralized. So in the blockchains, the participants make their moves in the decision-making process. In some governance strategies, the participants are the only decision-makers. Some blockchains like Ethereum have a less conventional approach to governance.
If the part of the community disagrees with the decision made, forks start to appear. Bitcoin Cash and Ethereum Classic were created because of hard forks.
The hard fork appears when two different opinions are among the majority of users. Or when many users get in trouble as it happened with DAO contracts on Ethereum. Briefly, the hacker found a loophole and have stolen 3.6M ETH. To reverse this losses, Ethereum community made a fork.
So there are some governance strategies. We’ll start the disclosure from more democratic to less democratic.
As you can see, the blockchain governance strategies different. The only same thing about them is an influence on the decision-making process. And control on the blockchain.
Off-Chain governance is more centralized than on-chain management and open governance. It is more likely to traditional governance, like in transnational corporations. Cryptocurrencies with established idea and infrastructure use off-chain governance. They try to balance the impact of users, miners, core developers, and business entities.
Off-Chain governance excludes mainstream users from decision-makers. Thus leaving only the people capable of handling the technical and management inquiries. Usually, the decision-making team contains lead tech developers. Owners and inventors of the blockchain are included too. Regular people only use the blockchain, don’t handle the decisions.
This governance is based on the BIP proposals transaction mechanism. It isn’t as centralized as traditional governing structures. It’s still as transparent and decentralized as the blockchain supposed to be. Influencers on decision-making have enough awareness of the big picture to decide rationally.
On-chain governance, unlike the off-chain one, is 100% democratic. As a new version of management, created especially for the blockchain, it amazes. On-chain governance is possible, thanks to blockchain built-in voting mechanisms. Many on-chain governance versions launched days ago or existed as the prototypes only at the moment when we submitted this article.
So, the first challenge we face is the complexity of governance itself. From the World’s history, we know that governance models take a long time to develop. Every governance model we know was established via the trial and error method. Existing governance models were developing for centuries. While the blockchain itself exists for a decade. Adapting democracy-like governance models for the blockchain is challenging.
Onchain governance transfers the power of decision-making from developers to miners and users. Users only can vote for the decisions via the built-in mechanisms of voting. But we know, again from the history, that democracies tend to fail if the number of people in a group is extensive. It happens because of selfish and emotional nature of most people.
Let’s move on from the theory to practice. We talked a lot about the governance models in the blockchain. Let’s disclose the most significant examples of the solutions to the blockchain governance problem. We stopped on three of them.
Governance is what blockchain needs. The whole blockchain ecosystem can’t exist in anarchy. But the truth is that all the governances for all the systems we have now we're building for centuries.
The challenges crypto-community faces now are about adapting some existing governance to the blockchain. Or inventing a brand new governance model. We can see companies like EOS, Decred, and Tezos. They try to make the blockchain governance democratic. Thus keeping the highest degree of decentralization the system can afford.
From the other side we see Ethereum where all the decisions pass a review from Vitalik Buterin. And yet nobody knows what is better. Is there any governance model that fits the specific of blockchain? It’s still an open question. Maybe, you could invent one?


import FilterBuilderCtrl from 'uoit-campus-map/src/filter/filter-builder_controller.js'
FilterBuilderCtrl
The FilterBuilderCtrl class provides a controller for the
<filter-builder>
directive; it contains logic for extracting
and combining the ng-model
of any number of arbitrary
transcluded inputs inside it.
The values of its transcluded inputs are converted to a unified query filter object (MongoDB/Mongoose-style in this case).
Unlike the <filter-controls>
component, this directive does not
make any server calls or deal otherwise with with the actual map
data – it is purely responsible for providing the filter to make
the server calls with.
Static Member Summary
| Static Public Members | ||
| public static get |
$inject: * |
Constructor Summary
| Public Constructor | ||
| public |
constructor($scope: *, $attrs: *, $parse: *) |
Member Summary
| Public Members | ||
| public |
Holds a map of child input NgModelControllers keyed by the string reference to the scope model of the input. |
Method Summary
| Public Methods | ||
| public |
$onInit() Initializes and attaches the controller's behaviours – this includes:
|
|
| public |
formatModelValue(modelValue: Object) The |
|
| public |
Gets the |
|
| public |
parseViewValue(viewValue: Array): Object The |
|
| public |
removeNulls(array: Array): Array Removes null and undefined values from a given array. |
|
| public |
Sets the |
Static Public Members
public static get $inject: * source
Public Constructors
public constructor($scope: *, $attrs: *, $parse: *) source
Params:
| Name | Type | Attribute | Description |
| $scope | * | ||
| $attrs | * | ||
| $parse | * |
Public Members
public parts: Object source
Holds a map of child input NgModelControllers keyed by the
string reference to the scope model of the input. For example,
if a child input has an ng-model="this.that"
attribute, its
key in this property will be 'this.that'
.
Its value represents the "model" of this directive: the parts of this property are compiled an parsed into the final filter.
Example:
// in HTML...
`<filter-builder ng-model="$ctrl.animalFilter">
<select ng-model="$ctrl.furType">....</select>
<input type="checkbox" ng-model="$ctrl.hasClaws" />
</filter builder>`
// ...will result in `this.parts` being equivalent to:
{ '$ctrl.furType': NgModel, '$ctrl.hasClaws': NgModel }
Public Methods
public $onInit() source
Initializes and attaches the controller's behaviours – this includes:
- setting a
$watchCollection
on the scope that...- watches the returned value of
getViewValue()
- responds to changes in the watch by calling
setViewValue()
- watches the returned value of
- pushing
parseViewValue
onto ng-model's$parsers
- pushing
formatModelValue
onto ng-model's$formatters
public formatModelValue(modelValue: Object) source
The formatModelValue
function is pushed onto the $formatters
of
the NgModelController
. It is responsible for delegating incoming
scope values (set programmatically) to their respective input elements' scopes.
The function needs to:
- determine which scope models are available to set
- disregard incoming values with no matching input element by building an
array of models with a matching value
[{ modelName: '$ctrl.modelName', modelValue: '...' }, {...}]
- for each available model with a matching value:
- use Angular's
$parse
service to generate a getter/setter for the model's scope reference - use the provided setter to set the scope reference, therefore updating
the child input elements by setting off their respective
$formatters
- use Angular's
Params:
| Name | Type | Attribute | Description |
| modelValue | Object | Map of values by name to set on child scopes |
public getViewValue(): Array source
Gets the $viewValue
of each child input from the controller's
parts
collection and returns them in a newly-mapped array
for efficient $watchCollection
ing.
public parseViewValue(viewValue: Array): Object source
The parseViewValue
function is pushed onto the $parsers
of
the NgModelController
. It is responsible for determining how many values
are being set on the view. If the view has...
- no values, return an empty object
- one value, return that value
- more than one value, return them wrapped in
{ $and: [...] }
Params:
| Name | Type | Attribute | Description |
| viewValue | Array | Incoming data from setViewValue |
Example:
// anything considered empty...
[]
[{}]
// turns into this:
{}
// a single predicate...
[{ category: 'abc123' }];
// gets flattened:
{ category: 'abc123' };
// multiple predicates...
[{ category: 'abc123' }, { feature: '123abc' }];
// get wrapped with the `$and` operator:
{ $and: [{ category: 'abc123' }, { feature: '123abc' }] }
public removeNulls(array: Array): Array source
Removes null and undefined values from a given array.
Params:
| Name | Type | Attribute | Description |
| array | Array | The array to remove nulls from |
Example:
// turns these...
[0, '', false, null, null]
[null, null]
// ..into these:
[0, '', false]
[]
public setViewValue() source
Sets the $viewValue
of this directive's ng-model based on
the $watch
results of getViewValue()
. Since the value needs
to be bound by reference, the original parts
collection is used
instead of the $watch
's copy value.
The values mapped into the new view value by this function are
obtained by using the parts[key].getFilter()
method, which is
defined on the filter input directive's NgModelController object.
If the value is an array, the getFilter()
wraps the array in
a MongoDB { $in: {...} }
operator and assigns it to a property
keyed by the input's name
attribute; if it is a primitive it
is assigned without wrapping.
Before setViewValue()
is called to fire off the parser pipeline,
the final value is run through removeNulls()
to cleanse it of
null
and undefined
values.


Assets are resources files that can be accessed via an URL (images, icons, fonts, etc.)
The source files are located under [NWAYO_ROOT]/components/[NAME]/assets/
They are 5 types of assets:
In the bundle file, components listed under assets
property will have all their assets built into the bundle's build directory.
These tasks interact with the assets


Compilation of the code
EasyMesh is written in the C language. It was developed and tested on a PC, using Watcom C/C++ 10.0a compiler. During the development, many non-standard Watcom's graphical functions were included to facilitate the debugging of the code. Later, this functions were not cancelled but enclosed inside the compiler directives, which resulted in the portability of the code. So, the code should be portable.
I compiled and run EasyMesh on the following platforms:
If someone successfully compiles and run the code on a different machine, or operating sistem, or compiler, please let me know, so that I can add it to the list.
EasyMesh was designed in such a
way to be as easy to use and maintain as possible. In that spirit, memory
allocation is made static. As a consequence, the program cannot generate
grids with more than 3000 nodes. However, you can increase the number of
acceptable nodes by changing the constant in the line:
#define MAX_NODES 3000
to a value greater than 3000. For example:
#define MAX_NODES 6000.
If you want to run EasyMesh on a
PC, and want to see the graphics, you must change the line:
#define GRAPHICS OFF
to:
#define GRAPHICS ON,
then you can compile under DOS, but with Watcom compiler only.
For those who are not fammiliar with the C compilers, the command line
to compile EasyMesh on UNIX-based machines,
is the following:
cc -o EasyMesh -O3 easymesh.c -lm
or on machines running Linux:
gcc -o EasyMesh -O3 easymesh.c -lm
On the PC running DOS/W95, which have Watcom C compiler installed, the
command line to compile EasyMesh is:
wcl386 easymesh.c


The Who become the first artist to be honoured on London’s Music Walk Of Fame
by https://www.facebook.com/ClassicRockMagazine/Roger Daltrey and Pete Townshend were on hand to receive the honour from Primal Scream’s Bobby Gillespie in Camden
The Who have become the first artist to be recognised on London’s new Music Walk Of Fame.
Roger Daltrey and Pete Townshend were on hand to receive the accolade from Primal Scream frontman Bobby Gillespie in the city’s Camden area.
The Walk Of Fame has been designed as a new cultural attraction in London and uses Augmented Reality technology which allows visitors to scan the founding stone where they’ll be “taken on a journey through the culture and history of music, using stones and landmarks as trigger points to learn more.”
The Who say: "We are honoured to be the first band with a stone on the Music Walk Of Fame. Camden has always been vital to London’s thriving music scene and is, as we all know, a world-renowned hub for the arts.
“As Londoners, it’s very surreal to be immortalised in stone on Camden High Street, and it’s quite something to know that people can pop by and see us anytime, albeit virtually!”
Music Walk Of Fame founder Lee Bennett adds: “What a great day for music, fans, the world, London, and Camden. To cap it off by having one of the greatest bands of all time, I’m thrilled to bits.”
Visitors can also get an exclusive preview of The Who’s new track I Don’t Wanna Get Wise by scanning the stone using the Music Walk of Fame app.
The single will go on general release this coming Friday (November 22). It’s been taken from the band’s upcoming album Who, which will launch on December 6.
For more on the Music Walk Of Fame, visit the official website.
- Dive into EMP's range of The Who merch
- Black Friday 2019 headphones deals: All the latest deals
- Black Friday 2019 vinyl deals: Where to find the biggest bargains
The Who: Who
The Who return with their new studio album Who – their first record since 2006's Endless Wire. It'll be out in November and feature Hero Ground Zero, Ball And Chain and All This Music Must Fade. View Deal
The Who UK and Ireland 2020 tour
Mar 16: Manchester Arena, UK
Mar 18: Dublin 3Arena, Ireland
Mar 21: Newcastle Utilita Arena, UK
Mar 23: Glasgow SSE Hydro, UK
Mar 25: Leeds First Direct Arena, UK
Mar 30: Cardiff Motorpoint Arena, UK
Apr 01: Birmingham Resorts World Arena, UK
Apr 03: Nottingham Motorpoint Arena, UK
Apr 06: Liverpool M&S Bank Arena, UK
Apr 07: London SSE Wembley Arena, UK


Now that you have installed the Ionic CLI you can generate your project using the blank template:
ionic start ionic-todo blank
It may take a minuter or two to run. You can say no to making the app cordova capable and you don't need to sign in to Ionic Pro. After the app is generated open that folder in your command prompt:
cd ionic-todo
Then open the /ionic-todo folder in your preferred code editor (VSCode or Atom work great for Ionic projects).
Ionic is built on the Angular framework for developing web applications so developing an Ionic 2+ application will be very similar to developing a standard Angular 2+ app.
All of the components for our application will be in the /src folder (including the root component in the /app folder, and all of our page components in the /pages folder). A component will consist of a template (.html file defining structure and elements), class definition (.ts file defining actions and logic) and styles (.scss file defining layout and appearance).
Along with components, you have providers (like the data service we will create later) which don’t have a html template or scss styling, but are similar in structure component's typescript class. These providers and will be placed in a providers folder.
import { Component } from '@angular/core';
import { HomePage } from '../pages/home/home';
@Component({
templateUrl: 'app.html'
})
export class MyApp {
rootPage:any = HomePage;
constructor() {
}
}
The app.component.ts file defines our root component. This component is special when compared to the rest of the components because it is the first component that will be added to the application, and from there we can display more components, which can then add even more components and so on. Basically, our application structure is like a tree with the root component at the root of that tree. So, it’s important that our root component knows where to find our HomePage as it will need to set it as the root page. Notice that we are importing the HomePage at the top of this file, and then setting it as the root page with the following code:
rootPage: any = HomePage;
We are able to declare variables above the constructor to make them member variables or class members,
meaning they will be accessible throughout the entire class by referencing this.myVar
and it will also
be available to your templates. In this case, we are creating a class member called rootPage
that we will
be able to access throughout this class, and in the template. If we take a look at the associated template
that is in src/app/app.html we would see:
<ion-nav [root]="rootPage"></ion-nav>
The template is accessing that class member that is stored in the TypeScript class file to configure the
<ion-nav>
component. Remember every component you create will consist of a .html
template file and a .ts typescript class file.
The root page is the first page that will be displayed in your application, and then you can navigate to other pages from there. To change views in an Ionic application you can either change this root page, or push and pop views on top of that page. Pushing a view will change to that view, and popping it will remove it and go back to the previous view.
Now that we’ve got our basic application set up, we will set up our todo list template in our home page.
<ion-header>
<ion-navbar color="secondary">
<ion-title>
Todos!
</ion-title>
<ion-buttons end>
<button ion-button icon-only (click)="addItem()"><ion-icon name="add-circle"></ion-icon></button>
</ion-buttons>
</ion-navbar>
</ion-header>
<ion-content>
<ion-list>
<ion-item *ngFor="let item of items" (click)="viewItem(item)">{{item.title}}</ion-item>
</ion-list>
</ion-content>
Take notice of the *
syntax used here for the *ngFor
in the list,
this is shorthand for creating an embedded template. So rather than literally rendering out:
<ion-item *ngFor="let item of items" (click)="viewItem(item)">{{item.title}}</ion-item>
to the DOM (Document Object Model), an embedded template will be created for each items specific data.
So, if our items array (which will be defined later in the class definition) had 4 items in it, then
the <ion-item>
would be rendered out 4 times.
Also notice that we are using let item
, which assigns a
single element from the items
array to item
as we loop through the array.
This allows us to reference its properties, and also pass it into the viewItem
function.
We are also setting the title to Todos! and we are supplying a button using <ion-buttons>
.
Since we have supplied the end attribute, the button will be placed in the “end” position.
Different attributes may behave differently depending on what platform they are running on,
but on iOS for example, “end” will place the button to the right of the nav bar. Also note
that on the button itself we give it an attribute of ion-button
which will give the button the Ionic styling,
as well as icon-only
which styles buttons that only contain an icon and no text.
We are using (click)
to attach a click listener to this element, which will call the addItem()
function in home.ts (which doesn’t exist yet).
Now that we have our template sorted, we need to create the functions we are referencing in our HomePage class, and we also need to supply the items data (we will just set up some dummy data initially).
import { Component } from '@angular/core';
import { NavController } from 'ionic-angular';
@Component({
selector: 'page-home',
templateUrl: 'home.html'
})
export class HomePage {
public items;
constructor(public navCtrl: NavController) {
}
ionViewDidLoad(){
this.items = [
{title: 'hi1', description: 'test1'},
{title: 'hi2', description: 'test2'},
{title: 'hi3', description: 'test3'}
];
}
addItem(){
}
viewItem(){
}
}
We are assigning a type of NavController
to the navCtrl
parameter in the constructor.
This is how dependency injection works in Ionic (or any Angular app), and is basically a way of telling the application
“we want navCtrl
to be a reference to NavController
“. By adding the public
keyword in front of it,
it automatically creates a member variable for us.
This means that we can now reference the NavController
anywhere in this class by using this.navCtrl
.
ionic serve -l
Now that we’ve set up some dummy data (we use the ionViewDidLoad
lifecycle hook to do this, which is
triggered as soon as the page is loaded), you should be able to see items rendered in your list when you run the app.
Since we have imported the NavController
service, we will
be able to push and pop views from this component by using:
this.navCtrl.push(SOME_PAGE); // To navigate to a new page in the stack
this.navCtrl.pop(); // To navigate backwards in the stack
We’ve also created function placeholders for adding items and viewing items, but before we can take this any further we are going to have to create a AddItemPage and ItemDetailPage component.
We’re going to create a new component that will allow us to add new todo’s. This will be a simple form where we supply a title and description.
ionic g page AddItem --no-module
Whenever we create a new page, we need to ensure that it is imported into our app.module.ts,
and declared in the declarations
and entryComponents
arrays.
import { BrowserModule } from '@angular/platform-browser';
import { NgModule, ErrorHandler } from '@angular/core';
import { IonicApp, IonicModule, IonicErrorHandler } from 'ionic-angular';
import { MyApp } from './app.component';
import { HomePage } from '../pages/home/home';
import { AddItemPage } from '../pages/add-item/add-item';
@NgModule({
declarations: [
MyApp,
HomePage,
AddItemPage
],
imports: [
BrowserModule,
IonicModule.forRoot(MyApp)
],
bootstrap: [IonicApp],
entryComponents: [
MyApp,
HomePage,
AddItemPage
],
providers: [{provide: ErrorHandler, useClass: IonicErrorHandler}]
})
export class AppModule {}
<ion-header>
<ion-toolbar color="secondary">
<ion-title>
Add Item
</ion-title>
<ion-buttons end>
<button ion-button icon-only (click)="close()"><ion-icon name="close"></ion-icon></button>
</ion-buttons>
</ion-toolbar>
</ion-header>
<ion-content>
<ion-list>
<ion-item>
<ion-label floating>Title</ion-label>
<ion-input type="text" [(ngModel)]="title"></ion-input>
</ion-item>
<ion-item>
<ion-label floating>Description</ion-label>
<ion-input type="text" [(ngModel)]="description"></ion-input>
</ion-item>
</ion-list>
<button full ion-button color="secondary" (click)="saveItem()">Save</button>
</ion-content>
We made a button calling the saveItem()
function that we will define in add-item.ts shortly.
We also have a button that references a close()
function –
since we will eventually launch this page as a Modal
we want the ability to dismiss the page,
so we will also be defining this function in add-item.ts.
Then we have some inputs, and on them, we have [(ngModel)]
, which sets up two-way data binding for us.
Any change we make to the title
field will be immediately reflected on the this.title
member variable in add-item.ts (which we will also add shortly). The same goes in reverse, any change
we make to this.title
in add-item.ts will also be immediately reflected in the template.
Also notice that on our save button we use the full
attribute, this is a handy little attribute that will
make the button full width for us.
import { Component } from '@angular/core';
import { NavController, ViewController } from 'ionic-angular';
@Component({
selector: 'page-add-item',
templateUrl: 'add-item.html'
})
export class AddItemPage {
title: string;
description: string;
constructor(public navCtrl: NavController, public view: ViewController) {
}
saveItem(){
let newItem = {
title: this.title,
description: this.description
};
this.view.dismiss(newItem);
}
close(){
this.view.dismiss();
}
}
We’re importing a new service ViewController
as view
which can be used with Modals to dismiss (close) them.
Apart from that, we are just creating the saveItem()
function which sets up a newItem object,
which will use the current values of title
and description
(i.e. whatever the user puts in the input fields we set up two-way data binding on). We then dismiss
the view,
but we also pass in that new item to the dismiss function.
This will allow us to set up a listener back on our home page to grab that item.
In this way, we can pass data from one page to another.
We are sending some data back to the HomePage component to be saved, so we are going to have to set that up. We are also going to import our new AddItemPage component into the HomePage so that we can create that view when the user clicks Add Item.
import { Component } from '@angular/core';
import { ModalController, NavController } from 'ionic-angular';
import { AddItemPage } from '../add-item/add-item'
@Component({
selector: 'page-home',
templateUrl: 'home.html'
})
export class HomePage {
public items = [];
constructor(public navCtrl: NavController, public modalCtrl: ModalController) {
}
addItem(){
let addModal = this.modalCtrl.create(AddItemPage);
addModal.onDidDismiss((item) => {
if(item){
this.saveItem(item);
}
});
addModal.present();
}
saveItem(item){
this.items.push(item);
}
viewItem(item){
}
}
If you look at the top of this file, you can see that we are now importing the AddItemPage component.
This will allow us to create a Modal using that page, as we are doing in the addItem()
function.
Notice that we also set up the onDidDismiss()
listener here, which will grab that item that is being passed back
and then save it using the saveItem()
function.
For now we just save an item by pushing it into the items
array, but eventually we will save it into storage.
We’ve also removed the dummy data, because now when a user enters in a new item it will be added to this.items
through the saveItem()
function. We also set items
to be an empty array initially.
Save all your files and if ionic serve
is running you should see your home page now allows you to add new
items via a modal and when you return to the home page the items should display in a list.
Now we want to add the ability to click on a specific todo list item, and then view the details of that item (i.e. the description). To do this, we are going to create a new page component.
ionic g page ItemDetail --no-module
and once again, we will need to set it up in our app.module.ts file:
import { BrowserModule } from '@angular/platform-browser';
import { NgModule, ErrorHandler } from '@angular/core';
import { IonicApp, IonicModule, IonicErrorHandler } from 'ionic-angular';
import { MyApp } from './app.component';
import { HomePage } from '../pages/home/home';
import { AddItemPage } from '../pages/add-item/add-item';
import { ItemDetailPage } from '../pages/item-detail/item-detail';
@NgModule({
declarations: [
MyApp,
HomePage,
AddItemPage,
ItemDetailPage
],
imports: [
BrowserModule,
IonicModule.forRoot(MyApp)
],
bootstrap: [IonicApp],
entryComponents: [
MyApp,
HomePage,
AddItemPage,
ItemDetailPage
],
providers: [{provide: ErrorHandler, useClass: IonicErrorHandler}]
})
export class AppModule {}
Now let’s set up our new page component.
<ion-header>
<ion-navbar color="secondary">
<ion-title>
{{title}}
</ion-title>
</ion-navbar>
</ion-header>
<ion-content>
<ion-card>
<ion-card-content>
{{description}}
</ion-card-content>
</ion-card>
</ion-content>
Compared to the rest of the templates, this one is pretty straight forward. We’re just using the <ion-card>
component to display the title
and
description
which will be defined in item-detail.ts.
import { Component } from '@angular/core';
import { NavParams } from 'ionic-angular';
@Component({
selector: 'page-item-detail',
templateUrl: 'item-detail.html'
})
export class ItemDetailPage {
title;
description;
constructor(public navParams: NavParams){
}
ionViewDidLoad() {
this.title = this.navParams.get('item').title;
this.description = this.navParams.get('item').description;
}
}
When we push this page we will pass in the data of the item that was clicked, and then we just set the title and description to that of the item using NavParams.
Now all we have to do is set up the viewItem function in home.ts and import the new detail page.
import { ItemDetailPage } from '../item-detail/item-detail';
viewItem(item){
this.navCtrl.push(ItemDetailPage, {
item: item
});
}
This will push the item detail page, and pass in the item in the list that was clicked. If you try clicking on an item in the list now, you should see something like this:
The todo application will basically work now, but the data isn’t being stored anywhere so as soon as you refresh the application you will lose all of your data (not ideal).
What we’re going to do now is create a service called Data that will handle storing and retrieving data for us. We will use the Storage service Ionic provides to help us do this. Storage is Ionic’s generic storage service, and it handles storing data in the best way possible while providing a consistent API for us to use.
ionic g provider TodoService
import { Storage } from '@ionic/storage';
import { Injectable } from '@angular/core';
@Injectable()
export class TodoServiceProvider {
constructor(public storage: Storage){
}
getData() {
return this.storage.get('todos');
}
save(data){
this.storage.set('todos', data);
}
}
This one is a little bit different to the rest of the classes we have been creating.
Instead of using the @Component
decorator, we are instead declaring this class as an @Injectable
.
In our constructor, we set up a reference to the Storage service as storage
.
Our save()
function simply takes in the array of all of the items and saves it to storage,
whenever the items change we will call this function.
We will also need to set up the Storage service (which requires us to include a IonicStorageModule
import in the @NgModule
),
as well as the Data
provider, in our app.module.ts file.
import { BrowserModule } from '@angular/platform-browser';
import { NgModule, ErrorHandler } from '@angular/core';
import { IonicApp, IonicModule, IonicErrorHandler } from 'ionic-angular';
import { IonicStorageModule } from '@ionic/storage';
import { MyApp } from './app.component';
import { HomePage } from '../pages/home/home';
import { AddItemPage } from '../pages/add-item/add-item';
import { ItemDetailPage } from '../pages/item-detail/item-detail';
import { TodoServiceProvider } from '../providers/todo-service/todo-service';
@NgModule({
declarations: [
MyApp,
HomePage,
AddItemPage,
ItemDetailPage
],
imports: [
BrowserModule,
IonicModule.forRoot(MyApp),
IonicStorageModule.forRoot()
],
bootstrap: [IonicApp],
entryComponents: [
MyApp,
HomePage,
AddItemPage,
ItemDetailPage
],
providers: [TodoServiceProvider, {provide: ErrorHandler, useClass: IonicErrorHandler}]
})
export class AppModule {}
Notice that we have declared the Data
provider in the declarations
or entryComponents
arrays.
IonicStorageModule.forRoot()
is set in the imports
array.
Now we need to update home.ts to make use of this new service.
import { Component } from '@angular/core';
import { ModalController, NavController } from 'ionic-angular';
import { AddItemPage } from '../add-item/add-item'
import { ItemDetailPage } from '../item-detail/item-detail';
import { TodoServiceProvider } from '../../providers/todo-service/todo-service';
@Component({
selector: 'page-home',
templateUrl: 'home.html'
})
export class HomePage {
public items = [];
constructor(
public navCtrl: NavController,
public modalCtrl: ModalController,
public dataService: TodoServiceProvider
) {
this.dataService.getData().then((todos) => {
if(todos){
this.items = todos;
}
});
}
addItem(){
let addModal = this.modalCtrl.create(AddItemPage);
addModal.onDidDismiss((item) => {
if(item){
this.saveItem(item);
}
});
addModal.present();
}
saveItem(item){
this.items.push(item);
this.dataService.save(this.items);
}
viewItem(item){
this.navCtrl.push(ItemDetailPage, {
item: item
});
}
}
Lastly, we’re importing the data service and passing it through to our constructor.
We are still setting the items
to be empty to start off with, and fetching the data using the data service.
If there are any items
returned it will set items to that, but if there is not it will just set it to an empty array again.
It’s important to note here that getData()
returns a promise
not the data itself. Fetching data from storage
is asynchronous
which means our application will continue to run while the data loads. A promise allows us
to perform some action whenever that data has finished loading, without having to pause the whole application.
Finally, we also add a call to the save()
function in the data service when a new item is being added.
So now this function will update our items
array with the new data straight away,
but it will also save a copy to the data service so that it is available next time we come back to the application.
You have learned how to use Ionic Framework to generate a simple todo app!


What does it do?
CSS Smart Grid builds on the popular 960 grid concept, mixing in responsive grids that are “mobile first”. It is built on three concepts:
-
Performance Driven
CSS Smart Grid was engineered to be lightweight. Minified and gzipped, it weighs in at only 1.2K.
It does not require the use of polyfills to work in IE 7-8. Instead, CSS Smart Grid uses a class of "oldie" set via Paul Irish's conditional

syntax (as seen in HTML5 Boilerplate) to give IE 6-8 the default 960 pixel version of the grid.IE 6 is not officially supported.
-
Built to Scale
CSS Smart Grid supports devices as narrow as 320 pixels all the way up to 1920 pixel wide HD displays. The grid is based on 12 columns with 20 pixel gutters. The width of the columns varies along the six breakpoints:
Platform Min Pixels Column Width Mobile 320 full Mobile Portrait or Large Screen 480 full Tablet Portrait 768 44 Desktop 960 60 Desktop Widescreen 1200 80 Desktop HD 1080p 1920 140 This page uses CSS Smart Grid; resize your browser to see it in action.
-
Not Just Mobile Friendly, But Mobile First
On mobile devices every kilobyte of bandwidth and every CPU cycle used to render a page counts. With that in mind, CSS Smart Grid uses mobile as its default layout. Mobile browsers that don't understand
@media
queries aren't left in the dust, they are first-class citizens. And because there's no need for polyfills on older browsers, even feature phone handsets will receive a single column view.
How to Use It
There's only one CSS file to include: smart-grid.min.css
. Place that in
before your own stylesheet.
Wrap your page inside a

. If you want to support larger screens, use

or for HD screens use

. Note that you can use more than one container if your need calls for it:

My Page Title

This is where my content goes.

Column Markup
Grid columns are achieved by adding a column
class to any element. By default, anything with the column
class is one column wide. For wider columns, add a class matching the number of columns you want the element to be: two
, four
, etc. Additionally, there are several shorthand classes for common use cases: one-fourth
, three-fourths
, one-third
, two-thirds
, one-fifth
, two-fifths
, three-fifths
, four-fifths
and one-half
. Group rows of columns together under a parent element with the class row
to make sure all of the floats are cleared.

The beginning of the best article in the history of humanity.

Here is some additional information.

If you only have one row of columns in a container, you can use the same element for both classes:

The beginning of the best article in the history of humanity.

Here is some additional information.

Column Offsets
Sometimes you need a blank column between content. Rather than add superfluous markup, you can add one of the offset-xxxxx
classes to the element you want to push left. There are classes defined to offset anywhere from 1 (offset-one
) to 11 (offset-eleven
) columns. Note that the offsets work by padding the element they're placed on; if you change the padding in your own CSS, the offsets will not work. Just like their column counterparts, offsets only take effect in browsers that are at least 768 pixels wide.

There are two blank columns to the left of this one.

This column leaves one column empty between it and it's predecessor then takes up the rest of the row.

You can mix and match columns and offsets however you want as long as the offset and column numbers add up to 12. To see it all working together, view the demo.
To get around the IE 7 :first-child
bug when adding elements via JavaScript, make sure to add a class of first
to element you introduce that is the first-child in its row.


Two more men arrested in connection with abduction of Kevin Lunney
by Jack QuannGardaí have arrested two more men in connection with the abduction of Quinn Industrial Holdings executive Kevin Lunney.
Two other men, both aged 38, were arrested on Thursday morning in the Dublin area.
They are being held at Ballymun and Finglas Garda stations.
While a 25-year-old man was subsequently arrested in Dublin and is being detained under Section 50 Criminal Justice Act at Irishtown Garda station.
And a fourth man, aged 66, was arrested in Co Cavan and is being held under Section 50 Criminal Justice Act 2007 at Monaghan Garda station.
An Garda Síochána is not providing any further information at this time.
They are continuing to appeal to any person who has any information, no matter how insignificant it appears, to contact An Garda Síochána at Cavan on 049-4368-800, the Garda Confidential Line at 1800-666-111, Crime Stoppers on 1800-25-00-25 or any Garda station.
Mr Lunney was kidnapped and assaulted by a group of masked men in September.
He was taken from near his home in Co Fermanagh, before being dumped at the side of the road in Co Cavan.
Three people were arrested in connection with the investigation last week, and have since been released without charge.


WebsiteForOnlineFoodDelivery.in
Home
Sing In
Sign Up
MERCHANT SINGN UP FORM
Name
Email
`
Mobile No.
+91
Restaurant Name
Restaurant Address


NAME
make_docs.pl
DESCRIPTION
An internal eHive script for regenerating the documentation both in docs/scripts (using pod2html) and docs/doxygen (using doxygen).
The script doesn't have any options at the moment.
LICENSE
Copyright [1999-2015] Wellcome Trust Sanger Institute and the EMBL-European Bioinformatics Institute
Copyright [2016-2021] EMBL-European Bioinformatics Institute
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License
is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and limitations under the License.
Please subscribe to the Hive mailing list: http://listserver.ebi.ac.uk/mailman/listinfo/ehive-users to discuss Hive-related questions or to be notified of our updates


The Discounting Model Selector (Web) is a web-based tool for applying approximate Bayesian model selection for delay discounting applications. This program allows researchers and clinicians with to perform an empirical comparison of Discounting models for individual series of data. This method has been simplified by Discounting Model Selector through the use of an easy-to-use interface resembling common spreadsheet software. At present, the online version of the DMS is performed with only one discounting series at a time.
Published:
Gilroy, S. P. & Hantula, D. A. (2018). Discounting model selection with area-based measures: A case for numerical integration. Journal of the Experimental Analysis of Behavior. https://doi.org/10.1002/jeab.318
Gilroy, S. P., Franck, C. T. & Hantula, D. A. (2017). The discounting model selector: Statistical software for delay discounting applications. Journal of the Experimental Analysis of Behavior, 107(3), 388-401. https://doi.org/10.1002/jeab.257
Franck, C. T., Koffarnus, M. N., House, L. L., & Bickel, W. K. (2015). Accurate characterization of delay discounting: a multiple model approach using approximate Bayesian model selection and a unified discounting measure. Journal of the Experimental Analysis of Behavior, 103(1), 218-233. https://doi.org/10.1002/jeab.128
This tool automates discounting model fitting, Approximate Bayesian Model Selection, model selection, and calculation of the Effective Delay 50 (ED50).
To perform model selection, input at least 3 pairs (x and y) of discounting data. At least three pairs of data are necessary to proceed.
Delay values (x) can be any number, though values must be between 0-1. This should be calculated as a proportion (i.e., the Y value divided by the Maximum Value). Any higher numbers will prevent you from proceeding.
The Discounting Model Selector (Web) uses the following tools to function:
Differential Evolution - Github
Random.js (MIT Licensed) - Github
Math.js (Apache 2.0 Licensed) - Github
Jquery (MIT Licensed) - Github


{% extends "base.html" %} {% block body %} {% include "navbar.html" %}
• Analyze one image/minute
• Analyze images up to 1 MB
• Analyze unlimted images
• No limit for pictures uploads.


Reproducible, programmatic retrieval of survey datasets from the Pew Research Center.
| Version: | 0.2.0 |
| Imports: | rvest, magrittr, purrr, httr |
| Suggests: | knitr, rmarkdown |
| Published: | 2016-09-24 |
| Author: | Frederick Solt [aut, cre], Yue Hu [aut], Eric Persson [ctb] |
| Maintainer: | Frederick Solt <frederick-solt at uiowa.edu> |
| License: | MIT + file LICENSE |
| NeedsCompilation: | no |
| Materials: | README NEWS |
| CRAN checks: | pewdata results |
| Reference manual: | pewdata.pdf |
| Vignettes: |
pewdata: Reproducible Retrieval of Pew Research Center Datasets |
| Package source: | pewdata_0.2.0.tar.gz |
| Windows binaries: | r-devel: pewdata_0.2.0.zip, r-release: pewdata_0.2.0.zip, r-oldrel: pewdata_0.2.0.zip |
| OS X binaries: | r-release: pewdata_0.2.0.tgz, r-oldrel: pewdata_0.2.0.tgz |
| Old sources: | pewdata archive |
Please use the canonical form https://CRAN.R-project.org/package=pewdata to link to this page.


{% extends "_post.html" %} {%hyde title: "wedding photos" created: 2004-08-27 02:11:12 %} {% block article %} {%article%}
So, we finally got some wedding photos back. I think this one is nice :)


I am sorry but your browser does not seem to support HTML5 Canvas. This is most likely you are using a very old version, probably IE. Supported browsers include Firefox, Chrome, IE 9 and above, Webkit based browsers on IPad or Android devices.
Upgrade your browser or just enjoy the video bellow


--- layout: default title: My Minecraft Skins description: A page with skins that I use on Minecraft, and my first Vue project. (also interactive!) render_with_liquid: false pwa: true ---
Here are skins that I use on Minecraft. Thank you for all of the original creators of these skins.
Two simple reasons.


Odd and Even Numbers |
Numbers may be odd or even.
The numbers l, 3, 5, 7, and 9 are odd numbers.
Numbers that end in l, 3, 5, 7, and 9 are also odd numbers. Look at the other examples of odd numbers below.
The numbers 0, 2, 4, 6, and 8 are even numbers.
Numbers that end in 0, 2, 4, 6, and 8 are also even numbers. Look at the other examples of even numbers.


|
ESP32 HTTPS Server
|
Base class for a URL/route-handler in the server. More...
#include <HTTPNode.hpp>
Public Member Functions | |
| HTTPNode (const std::string &path, const HTTPNodeType nodeType, const std::string &tag="") | |
| bool | hasUrlParameter () |
| uint8_t | getUrlParamCount () |
| size_t | getParamIdx (uint8_t) |
| std::vector< HTTPValidator * > * | getValidators () |
| virtual std::string | getMethod ()=0 |
| void | addURLParamValidator (uint8_t paramIdx, const HTTPValidationFunction *validator) |
Public Attributes | |
| const std::string | _path |
| const std::string | _tag |
| const HTTPNodeType | _nodeType |
Base class for a URL/route-handler in the server.
Use ResourceNode for requests that access dynamic or static resources or HttpNode for routes that create Websockets.
| void httpsserver::HTTPNode::addURLParamValidator | ( | uint8_t | paramIdx, |
| const HTTPValidationFunction * | validator | ||
| ) |
Adds a validation function that checks if the actual value of a parameter matches the expectation
| paramIdx | defines the ID of the parameter that should be checked (starts by 0) |
| validator | the function (string -> bool) that checks if the parameter matches the expecatation |
| const HTTPNodeType httpsserver::HTTPNode::_nodeType |
Stores the type of the node (as we have not runtime type information by default)
| const std::string httpsserver::HTTPNode::_path |
The path under which this node will be available. Should start with a slash. Example: "/myResource"
| const std::string httpsserver::HTTPNode::_tag |
Stores a tag that can be used in middleware and handler functions to identify this specific node, tag the node with a required permission, ...


@layout("/common/_container.html",{bg:"bg-white",js:["/assets/modular/customer/customer_site/customer_site_project_add.js"]}){


Lorem ipsum dolor sit amet consectetur adipisicing elit. Aut laboriosam iusto fugit! Nam, animi illum?
by Tiffany - 5 mins ago
Coding Javascript With Nordic
Training yourself day by day
Small steps make big changes...
Coding something could help :D
Believe it, you can do it.


Embedded Artistry Framework
Embedded Systems C++ Framework
src
platforms
platforms Directory Reference
Directory dependency graph for platforms:
Directories
directory
blinky
directory
fwdemo
directory
unit_test
Generated by
1.8.15


As I discussed in a post last month, I recently took a Coursera class on network theory and analysis. I did this in part because I wanted to evaluate the MOOC format from a student’s perspective. But I also did it because network theory is very hot right now and appeals to my old life as a mathematician.
During the first couple of weeks of the class I decided that I needed a real-life network to play around with. Inspired by this post, I decided to look at the history of philosophy as described by the “influence” relationship in Wikipedia. I plan to write a paper — maybe for a digital humanities project — on my findings, complete with some background on network theory for non-philosophers. Here I’m going to skip the technical details and show you some pretty pictures and some basic results about identifying the “most influential” philosophers.
My dataset is large by the standards of the traditional humanities, though not so large by the standards of many digital humanities projects and tiny compared to, say, a genome sequence. The base graph contains 1,997 distinct philosophers (assuming no repeats — one step in acquiring the dataset consolidates repeats, but I have to identify these manually) with 4,022 connections between them. Connections represent one philosopher influencing another. Because of this size, pretty much any effort to represent the entire graph is an incomprehensible mess. So here’s a picture of the 177 philosophers in the dataset who are connected to at least 10 other philosophers.
The size of the circle indicates something called the eigenvector centrality of the node in the network — one of the measures of influence that I investigated and will discuss below. The color picks out distinct communities of highly-inter-connected philosophers, though I think the algorithm used to determine this doesn’t work so well for this particular network.
The post that I linked to in the second paragraph did this much. But I wanted to use some of the tools for quantitative analysis that I was learning in my course. Since the contemporary culture of philosophy seems to care a lot about ranking — programs, schools, journals, individual philosophers — I decided to focus on that.
From a network perspective, one obvious ranking question to ask is “how well-connected is each node to the rest of the network?” These are measures of the centrality of nodes. And there are several different ways to do it. One way is simply to measure the number of immediate connections, or neighbors, that a node has. More sophisticated ways look at the node within the overall structure of the network. I used three measures of centrality: out-degree, the number of philosophers directly influenced by the given philosopher; betweenness, which looks at the position of the given philosopher along distant connections in the network; and eigenvector, which looks at how well-connected the given philosopher is to other well-connected philosophers. Here are the rankings:
| Out-degree | Betweenness | Eigenvector | Condorcet | Leiter “Most Important” | |
|---|---|---|---|---|---|
| 1. Kant | 1 | 2 | 1 | 44 | 3 |
| 1. Hegel | 3 | 1 | 2 | 42 | 11 |
| 3. Marx | 4 | 5 | 4 | 35 | 17 |
| 4. Aristotle | 2 | 3 | 27 | 2 | |
| 4. Descartes | 11 | 4 | 7 | 26 | 5 |
| 6. Plato | 5 | 16 | 5 | 22 | 1 |
| 6. Nietzsche | 6 | 6 | 20 | 18 | |
| 6. Heidegger | 8 | 10 | 10 | 20 | |
| 6. Leibniz | 3 | 9 | 20 | 12 | |
| 6. Spinoza | 14 | 6 | 8 | 20 | 13 |
| 11. Hume | 13 | 7 | 15 | 13 | 4 |
| 11. Rousseau | 8 | 12 | 12 | 20 | |
| 11. Husserl | 10 | 15 | 11 | 12 | |
| 14. Wittgenstein | 7 | 9 | 7 | ||
| 14. Aquinas | 9 | 7 | 10 | ||
| 14.  Blanks indicate that the given philosopher wasn’t ranked in the top-20 by that centrality measure. I’m going to come back to the final column.) The first thing that I notice is that there is both significant agreement and significant disagreement among these rankings. All three agree that Kant and Hegel are at the top, followed a little ways by Marx, and Heidegger near the bottom of the top-10. But there’s also significant disagreement about who comes in the middle.
To some extent, this is probably due to the way the different measures work. For example, Ancient philosophers have a disadvantage on the betweenness measure: most of the philosophers in the network came centuries later, and so the Ancient philosophers don’t mediate many connections. I want to discuss this further in the paper.
To aggregate these three lists, I used a variation on Condorcet polling. In a Condorcet poll, each voter ranks all of the candidates in order of preference; we then aggregate these votes by seeing how among how many voters each candidate beats the others. Here I used the three lists as my three voters, and replaced the one-to-one comparisons of a Condorcet poll with a simpler counting scheme. For example, Hegel outranks the other 15 a total of 42 times among the three lists; Marx outranks the other 15 a total of only 35 times, and so comes below Hegel. We can then assign rankings, ignoring differences of 2 “points” or less.
Finally, it’s interesting to contrast these rankings with the results of a poll on the “most important philosophers of all time,” conducted by Brian Leiter on his blog in 2009. That’s the final column of the table above. Compared to my analysis, Leiter’s poll ranks Plato significantly higher, and ranks Hegel, Marx, and Nietzsche significantly lower. Heidegger and Husserl don’t even show up in Leiter’s top-20; conversely, my top-20 doesn’t include Socrates, Locke, and Frege.
What could explain this difference? My dataset ultimately comes from Wikipedia; Leiter’s comes from the readers of his blog. Insofar as “anyone can edit a Wikipedia page” and Leiter’s audience is primarily professional philosophers, it seems reasonable to think that this probably explains a lot of the difference: professional philosophers generally think less of Heidegger and Husserl, and more of Plato and Frege, than the “anyone” who is editing the Wikipedia pages on these philosophers.
Does this mean that Leiter’s rankings are, in some sense, better than the results of my analysis? I’m skeptical, for at least two reasons. First, the voters in Leiter’s poll knew that they were voting in a poll, and so simply a priori there’s the possibility of people voting multiple times or engaging in strategic voting to manipulate the results. The Wikipedia editors had no idea that I was going to carry out this analysis, and so it’s much less plausible to think that they might have tried to manipulate the dataset.
But that’s a minor concern. My second and deeper reason is it’s not clear what counts as a “better” ranking. We might think a better ranking is “more accurate”; but more accurate to what? Leiter asks which philosophers are “most important,” and it’s not clear to me that there’s an objective fact of the matter about whether Plato is more or less important than Marx. If the poll had been taken in the eighteenth century, Aristotle and Aquinas probably wouldn’t have even been candidates; late in the nineteenth century, Hegel would have been much closer to the top and Hume much further down. Furthermore, even if there is an objective fact of the matter, the poll’s methodology seems to be better designed to measure who is liked more by readers of Leiter’s blog than who is objectively more important.
My analysis is based on data about philosophical influence. It seems to me more plausible to think that these data are more objective than importance. But influence is quite vague. Is it reasonable to say that Descartes was influenced by Aristotle or al-Ghazali? What about someone like John Rawls, who was arguably influenced by a hundred different thinkers in the history of ethics, but in the dataset is only influenced by Locke? Furthermore, we have to draw disciplinary boundaries somehow. Should these be based on the boundaries of the contemporary university? Should we include Newton, or Thomas Kuhn?
At this point, it seems that we must take the purposes of the rankings into account. What question are we trying to answer, and why are we trying to answer it?


Toggle navigation
Menu
Cookie
food
About
Contact
Cookie Monster
Cookie - Cookie - Cookie
food
About
Made using the help of Bootstrap, tried to make it look as vanilla as possible.
Send me Cookies
Name
Email Address
Phone Number
Message
Send


Pic It is my first mobile application developed for Android devices. It may not be the best app I have ever done, but it is something I am really proud to show! Pic It was the result of gathering with a friend and analysing current social networks. We saw that there are bunch of different social networks, and all of them had different approaches to eveything: likes, pictures, comments, opinions and so on... However, we wanted to create something that involved pictures and ratings! Something different. Pic It allows you to upload pictures (taken by your camara or stored in your phone), and rate them from 1 to 5 (stars). As a user, you could create your account, upload pictures, and rate random selected pictures. For our backend we decided to use PHP, and our android app was developed using Java in Eclipse Studio (back in the day when Android Studio wasn't there). Unfortunately, we didn't keep developing this product, but as this was my first project, I've always seen it like something that I would always talk about! You can ask me anything also. Below you may find information about its tech stack and APIs used to make this possible. Built With and Technologies Used:


A Gas Explosion in an Apartment Building Killed Seven People in Slovakia
At least seven people were killed and more than 40 were injured in yesterday's gas explosion in a 12-floor apartment building in the Slovak town of Prešov, police and fire officials said.
One person is still missing. Earlier, five people were reported dead.
The explosion occurred at noon on one of the upper floor of the block and caused a fire that affected four to five of the high floors. Soldiers and helicopters took part in the extinguishing of the fire.
A fire department spokesman told reporters that the blast could be the result of a wrong installation of a new gas system two years ago.


Most of my projects here are either for my work at UConn's Center for Career Development, where I intern as a designer, or projects I have done for fun on the side.
I am fairly handy with after effects and would like to use my skills in the future to design intricate interactions for digital media.
For my on campus internship I spend some of my time animating videos to help students with Career Development. I try to make the videos as fun as possible while still giving the most amount of information possible.
The first video was on interviewing. The second was a promo (draft) for a website I made to host all the videos our team created. I've made several videos like this but I like these the best.
This is a TV show idea about Fidel Castro and the Russian and American involvement in Cuba.
While this isn't the most beautifully designed animation, it does incorporate my joy of storytelling. For this project I was limited to using "Vine" and stop motion.
This is one the first animations I ever made. Trichotillomania, also known as hair pulling disorder, is an impulse control disorder characterized by a long term urge that results in the pulling out of one's hair.