Documenting your API with IODocs on Heroku
Neil Mansilla over at Mashery has created an awesome new system called IODocs, which can be used to create a system for browsing through OAuth-secured APIs. Being a Developer Advocate at LinkedIn, I decided to try and get this up and running with LinkedIn’s API. Since it was LinkedIn’s internal hackday on Friday, I decided to go the extra mile and try to build the configuration dynamically from our nascent discovery API system, and run it on one of Heroku’s node.js hosted systems.
Thanks in part to a heavy piece of furniture (which fell on me on Friday, relegating me to bed rest for the weekend) I got it working. You can visit the LinkedIn API Documentation site and use your LinkedIn API key and secret to browse through the many API resources LinkedIn has to offer.
Getting the IODocs system running on Heroku required several steps, but once you have them it’s pretty straightforward. So I share them with you here so you can get IODocs running on your own Heroku instance, in the hopes that all of the OAuth APIs out there can leverage this functionality and improve developers’ lives.
Consider this an inclusive set of instructions to the ones they have on the site.
- Get “Local Workstation Setup” done from http://devcenter.heroku.com/articles/node-js
-
Do the initial IODocs setup
% git clone http://github.com/mashery/iodocs.git % cd iodocs/ % npm install % echo “web: node app.js” > Procfile % cp config.json.sample config.json % vi config.json (remove address line)

- Add the following block under “var db;” to app.js:
if (process.env.REDISTOGO_URL) { var rtg = require(“url”).parse(process.env.REDISTOGO_URL); db = require(“redis”).createClient(rtg.port, rtg.hostname); db.auth(rtg.auth.split(“:”)[1]); } else { db = redis.createClient(config.redis.port, config.redis.host); db.auth(config.redis.password); }
And then this in the Load API Configs section, after reading the config file:
var app = module.exports = express.createServer();
var hostname, port, password
if (process.env.REDISTOGO_URL) { var rtg = require(“url”).parse(process.env.REDISTOGO_URL); hostname = rtg.hostname; port = rtg.port; password = rtg.auth.split(“:”)[1]; } else { hostname = config.redis.host; port = config.redis.port; password = config.redis.password; }

-
Add a LinkedIn block to public/data/apiconfig.json:
“linkedin”: { “name”: “LinkedIn”, “protocol”: “http”, “baseURL”: “api.linkedin.com”, “publicPath”: “”, “privatePath”: “/v1”, “auth”: “oauth”, “oauth”: { “type”: “three-legged”, “requestURL”: “https://api.linkedin.com/uas/oauth/requestToken”, “signinURL”: “https://api.linkedin.com/uas/oauth/authorize?oauth_token=”, “accessURL”: “https://api.linkedin.com/uas/oauth/accessToken”, “version”: “1.0”, “crypt”: “HMAC-SHA1” }, “keyParam”:”” },

- Copy linkedin.json into your public/data folder
-
Set up your git repository for heroku
% git init % git add . % git add -f config.json Procfile public/data/* % git commit -m “init”

- Set up heroku
% heroku create –stack cedar; % heroku addons:add redistogo [note: this may require that you add a credit card to your heroku account. there is no charge, though] % heroku addons:add logging % git push heroku master % heroku ps:scale web=1

Once you’ve gotten all this set up, you’re ready to rock. Heroku will give you the right system name and port, and you can use ‘heroku logs’ to check the logs for the node.js server.
You can set up your own APIs using the config file – the IODocs documentation is fantastic, with OCD-level detail on how to set up configurations for new APIs, and I’m certain you can make it work with whatever you’re trying to use.
LINKEDIN · WEB APIS
heroku iodocs linkedin node.js oauth


2-D Motion Challenge #1 The gap starts at m high and m away horizontally. The ball has a horizontal velocity of m/s. I think the correct initial vertical velocity is m/s fire clear Reload to try a new random problem.


{% extends "workflow/project_base.html" %} {% block title %}Create a new template{% endblock title %} {% block nav_item_templates %}active{% endblock nav_item_templates %} {% load crispy_forms_tags %} {% block content %}
Something short and leading about the collection below—its contents, the creator, etc. Make it short and sweet, but not too short so folks don’t simply skip over it entirely.


Custom algorithms
py3 only
This section describes the process, steps and resources required to run custom algorithms in Skyline. Adding a custom algorithm or algorithms is easier and better than modifying the core Skyline algorithm files yourself.
If you are wanting to implement a custom algorithm, ensure you read this documentation thoroughly and understand the layout in the example algorithms. This will save you time if you do it properly from the beginning.
Custom algorithms are currently only implemented in analyzer (also covers analyzer_batch), crucible and mirage.
Available custom algorithms
There is a collection of custom algorithms already available in Skyline and each has a page here. However currently most are only documented in the code and their pages refer to the source code.
The performance and accuracy of the available algorithms vary, their inclusion is not a validation of the method, simply that they can function as outlier detectors. Each generates different results and few seldom agree. The Vortex webapp UI can be used to run them adhoc on any time series should you wish to assess there performance.
Implementing a custom algorithm
To implement a custom algorithm, you need to define it in
settings.CUSTOM_ALGORITHMS
and add the Python source custom algorithm
file.
Warning
A note on speed, bear in mind that any custom algorithms added have to run FAST, otherwise analysis stops being real time and the Skyline apps will terminate their own spawned processes if they run too long. Consider that Skyline’s three-sigma triggered algorithms take on average 0.0023 seconds to run and all 9 are run on a metric in about 0.0207 seconds. Adding any algorithms that run substantially slower is not recommended, even if it is on a small set of metrics. Any algorithms added to should be as computationally efficient as possible and suitable for processing real time streaming data, e.g. O(n). This is especially true for any custom algorithms added to Analyzer. This is not a hard requirement, just a recommendation. It is possible to add non O(n) algorithms to Mirage, but they should be designed and implemented to be as computationally efficient as possible.
Custom algorithms can be run before or after the core three-sigma
algorithms. The custom algorithm can be configured to run before the three-sigma
algorithms which allows the user to disable the running of three-sigma
algorithms on namespaces if they so desire, more on this below. By default
custom algorithms are run before three-sigma algorithms.
Running the custom algorithm after three-sigma allows the user to only run
a custom algorithm if three-sigma achieves settings.CONSENSUS
or run the
custom algorithm regardless of the CONSENSUS that was achieved.
The custom algorithms settings are therefore highly configurable, specifically take note of the consensus, run_3sigma_algorithms, run_before_3sigma and run_only_if_consensus parameters, especially if you are attempting to run multiple custom algorithms at different stages, before or after three-sigma and what consensus should be applied. It is probably possible to configure poorly given the methods and modes that can be configured.
The use of numba optimisations
Any performance optimisations that can be achieve in custom algortihm with numba jit functions is encouraged, with the following caveats.
If the algorithm or any part thereof uses numba optimisations in anyway ensure
that the jit
or njit
decorator has cache=True
applied to ensure that
the jit compilation overhead is only incurred once and is not incurred on every
execution. In terms of multiprocessing and threading if there is no jit cache
file of a function the jit compilation happens every execution which is slow.
Also note that in the normal Skyline build on CentOS 8 the default
NUMBA_CACHE_DIR
is /opt/skyline/.cache/numba
this is not specifically
defined, it is what gets defaulted to by numba. IMPORTANT as per relevant
upgrade instructions in release notes, this directory needs to be flushed
whenever an upgrade is made to Python and/or any dependencies, so that the numba
jit cache files can be recompiled with the new versions.
In terms of making changes to any existing numba optimised custom algorithms that are loaded by Skyline, numba will automatically replace it jit cache files when a change is made to the algorithm source file in Skyline when the relevant Skyline service is restarted and the custom algorithm function is called for the first time.
That said this has a direct impact on the custom algorithm max_execution_time
parameter. This is because the first execution of the jit function when the
cache files are not present could take say 40 seconds to compile the function.
Now if you can expect the algorithm to run in say less than 1 second WHEN the
jit cache file is present, you may want to set the max_execution_time: 1.2,
however the custom algorithm will be terminated by the timeout decorator on
every run and it will never compile and therefore never save the jit cache
files.
Therefore an additional key value pair can be passed in the
settings.CUSTOM_ALGORITHMS
definition for any custom algorithm that uses
numba jit functions, e.g. 'numba_cache_dirs': ['stumpy_'],
. This is a list
of cache dirs that are expected to exist and if do not exist then increase the
max_execution_time
to 180 seconds to allow for first time numba jit
compilations to occur so that the timeout decorator does not terminate the
algorithm due to a low max_execution_time.
The numba_cache_dirs
is a list of substrings of the directories created in
the default /opt/skyline/.cache/numba
which are expected.
For example the stumpy stump algorithm with njit caching enabled saves
/opt/skyline/.cache/numba/stumpy_7b65d2f0242c0368bd086e515d849481810e817d
with nbc and nbi files:
(skyline-py3816) [root@skyline-test-1 skyline-py3816] ls -al /opt/skyline/.cache/numba/ | grep stump
drwxr-xr-x 2 skyline skyline 4096 Jan 12 16:37 stumpy_7b65d2f0242c0368bd086e515d849481810e817d
(skyline-py3816) [root@skyline-test-1 skyline-py3816] ls -al /opt/skyline/.cache/numba/stump*
total 460
drwxr-xr-x 2 skyline skyline 4096 Jan 12 16:37 .
drwxr-xr-x 8 skyline skyline 4096 Jan 12 16:09 ..
-rw-rw-rw- 1 skyline skyline 455583 Jan 12 16:37 stump._stump-216.py38.1.nbc
-rw-rw-rw- 1 skyline skyline 1487 Jan 12 16:37 stump._stump-216.py38.nbi
(skyline-py3816) [root@skyline-test-1 skyline-py3816]
This would be declared as 'numba_cache_dirs': ['stumpy_']
, and the
custom_algorithms.run_custom_algorithm_on_timeseries
checks for the
existence of a dir matching these substrings/patterns in
/opt/skyline/.cache/numba
, if not found sets the max_execution_time
to
180 seconds for that run to allow for the jit compile and save overhead without
terminating the run before it has time to compile and save.
You therefore need to be fully aware of what jit cache files your algorithm will create and declare them appropriately.
settings.CUSTOM_ALGORITHMS
Custom algorithms are only available in analyzer, crucible and mirage, any declared for use with analyzer will automatically also be applied for analyzer_batch. For a custom_algorithm to be available for use in crucible it must be declared in CUSTOM_ALGORITHMS.
Custom algorithms are defined in the settings.CUSTOM_ALGORITHMS
dictionary. The format and key values of the dictionary are shown in the
following example:
CUSTOM_ALGORITHMS = {
'abs_stddev_from_median': {
'namespaces': ['telegraf.cpu-total.cpu.usage_system'],
'algorithm_source': '/opt/skyline/github/skyline/skyline/custom_algorithms/abs_stddev_from_median.py',
'algorithm_parameters': {},
'max_execution_time': 0.09,
'consensus': 6,
'algorithms_allowed_in_consensus': [],
'run_3sigma_algorithms': True,
'run_before_3sigma': True,
'run_only_if_consensus': False,
'trigger_history_override': 0,
'use_with': ['analyzer', 'analyzer_batch', 'mirage'],
'debug_logging': False,
},
'last_same_hours': {
'namespaces': ['telegraf.cpu-total.cpu.usage_user'],
'algorithm_source': '/opt/skyline/github/skyline/skyline/custom_algorithms/last_same_hours.py',
# Pass the argument 1209600 for the sample_period parameter and
# enable debug_logging in the algorithm itself
'algorithm_parameters': {
'sample_period': 604800,
'debug_logging': True
},
'max_execution_time': 0.3,
'consensus': 6,
'algorithms_allowed_in_consensus': [],
'run_3sigma_algorithms': True,
'run_before_3sigma': True,
'run_only_if_consensus': False,
'trigger_history_override': 0,
# This does not run on analyzer as it is weekly data
'use_with': ['mirage', 'crucible'],
'debug_logging': False,
},
'detect_significant_change': {
'namespaces': ['swell.buoy.*.Hm0'],
# Algorithm source not in the Skyline code directory
'algorithm_source': '/opt/skyline_custom_algorithms/detect_significant_change/detect_significant_change.py',
'algorithm_parameters': {},
'max_execution_time': 0.002,
'consensus': 1,
'algorithms_allowed_in_consensus': ['detect_significant_change'],
'run_3sigma_algorithms': False,
'run_before_3sigma': True,
'run_only_if_consensus': False,
'trigger_history_override': 0,
'use_with': ['mirage'],
'debug_logging': True,
},
'skyline_matrixprofile': {
'namespaces': ['*'],
'algorithm_source': '/opt/skyline/github/skyline/skyline/custom_algorithms/skyline_matrixprofile.py',
'numba_cache_dirs': ['stumpy_'],
'algorithm_parameters': {'windows': 5, 'k_discords': 20},
'max_execution_time': 5.0,
'consensus': 1,
'algorithms_allowed_in_consensus': ['skyline_matrixprofile'],
'run_3sigma_algorithms': True,
'run_before_3sigma': False,
'run_only_if_consensus': True,
'trigger_history_override': 4,
'use_with': ['mirage'],
'debug_logging': False,
'numba_cache_dirs': ['stumpy_',]
},
}
Within the dictionary each custom algorithm is declared and its variables are defined. Each custom algorithm defined is required to adhere to the following requirements.
algorithm_name: firstly and importantly, name of algorithm must be simple, unbroken, alphanumeric string. It must also be the name of the main algorithm function, this is because it is loaded by
importlib
and the name in the dictionary is used to load the custom algorithm at runtime.namespaces
: this is a list of the namespaces you want to run the custom algorithm against. These can be absolute metric names, substrings or dotted elements of a namespace or a regex of a namespace.algorithm_source
: the full path to the custom algorithm Python file, the file can be deployed to any directory it does not need to be in the same path as the Skyline code, just ensure the user running the Skyline process has read permissions on the path and file itself.algorithm_parameters
- this is a dictionary of any parameters/arguments that you want to pass to your algorithm. Your custom algorithm will need to interpolate your parameters/arguments (key/value) from this dictionary. If none are required simply use an empty dict {}.max_execution_time
- a float (and read the warning about speed above).consensus
- this allows you to add your algorithm to theCONSENSUS
or overrideCONSENSUS
by setting this to 1. If you are runningCONSENSUS = 6
and wanted to just add your custom algorithm as an addition to the normal three-sigma algorithms, you would just pass'consensus': 6
or'consensus': 7
depending on what you want. The only other option currently is to override theCONSENSUS
, if you want an anomaly triggered every time your custom algorithm triggers, regardless of three-sigmaCONSENSUS
then set'consensus': 1
algorithms_allowed_in_consensus
: must be passed but is not implemented yet but this is a list of algorithms that must have triggered for consensus to be achieved. If an empty list is passed [] this will be ignored and normalCONSENSUS
will be used.run_3sigma_algorithms
: a boolean stating whether to run the normal three-sigma algorithms, this is optional and defaults toTrue
if it is not passed in the dictionary. NOTE - If any custom algorithm is run that has this set toFalse
no three-sigma algorithms will be run regardless of what any other custom algorithms are set to. If multiple custom algorithms are being run and only 1 has this set toFalse
it will be applied to all.run_before_3sigma
: a boolean stating whether to run the custom algorithm before the normal three-sigma algorithms, this defaults toTrue
. If you want your custom algorithm to run after the three-sigma algorithms set this toFalse
.run_only_if_consensus
: a boolean stating whether to run the custom algorithm only if CONSENSUS or MIRAGE_CONSENSUS is achieved, it defaults toFalse
. This only applies to custom algorithms that are run after three-sigma algorithms, e.g. with the parameterrun_before_3sigma: False
Currently this parameter only uses the CONSENSUS or MIRAGE_CONSENSUS setting and does not apply the consensus parameter above.trigger_history_override
: an int defining whether override the outcome of the custom algorithm if the three-sigma algorithms have triggered this many times in a row. Setting this to 0 disables the override and the number of times the three-sigma algorithms have triggered is not checked. If this value is set to 4 then even if the custom algorithm evaluates the metric as not anomalous, if the metric has been determined to be anomalous by the three-sigma analysis 4 times in a row, the custom algorithm result will be overridden and the metric will be classified as anomalous.use_with
- a list of the Skyline apps that should apply the custom algorithm. All the apps can be declared but they will only apply the custom algorithm if they actually handle the metric. Simply declaring them in the list does not mean that the app will just automatically run them all the time. If the app does not handle the metric, it being declared makes no difference, therefore if you are unsure, it is safe to list them all. Although do note that if your custom algorithm needs more data thansettings.FULL_DURATION
then do not specify'analyzer'
as apps to run the custom algorithm with.debug_logging
: a boolean to enable debug_logging, which wraps the custom algorithm run in a bit of additional logging, regarding timings, etc this is useful for development and testing. In general use and production this should always be set toFalse
.
It is also possible to set settings.DEBUG_CUSTOM_ALGORITHMS
to True
and this enables debug logging on all custom algorithms, regardless of what
their debug_logging
is set to. However if this is set to False
debug
logging can still be implemented on each custom_algorithm individually using
'debug_logging': True,
in the algorithm item in
settings.CUSTOM_ALGORITHMS
.
The custom algorithm file
Although any Python code can be added to a custom algorithm file, the algorithm file must meet some basic requirements that are required to properly integrate and be run by Skyline.
Below the requirements are outlined, please read them and you can refer to a couple of example custom algorithm files in the skyline/custom_algorithms directory of the repo. https://github.com/earthgecko/skyline/tree/master/skyline/custom_algorithms
Warning
Do remember if the algorithm has requirements that are not declared in Skyline’s requirements.txt file, ensure that you install the algorithm’s requirements in the Skyline virtualenv.
int and floats ONLY and no nans
If your custom algorithm has the ability to also return_results
or
return_anomalies
be advised that you need to ensure that the results are
coerced to int and float types only. This is due to the fact the results can be
moved through the pipeline and saved as json. Therefore results from any numpy
arrays could have type int64
or other which are not JSON serializable.
The same is true for nan
values, although floats in Python they are not
valid in JSON, ensure nan
values are coerced to None
which json will
dump to null
or False
which json will dump to false
.
anomalyScore
Unlike the core Skyline algorithms, custom algorithms introduces the requirement
for the algorithm to also return a anomalyScore
. The concept of the
anomalyScore
is used in many anomaly detection algorithms and methods and it
is useful in many cases for algorithm testing.
Custom algorithm requirements
Must be written in Python
Must import all modules and classes it requires.
The algorithm must have the following four parameters, e.g.
def last_same_hours_weekly(current_skyline_app, parent_pid, timeseries, algorithm_parameters):
The four parameters are:
current_skyline_app
- this will be passed to the custom algorithm by Skyline to identify which Skyline app is executing the algorithm, this is required for error handling and logging. You do not have to worry about handling thecurrent_skyline_app
argument in your algorithm, your algorithm must just accept it as the first argument.parent_pid
- this will be passed to the custom algorithm by Skyline to identify which pid has executed the algorithm, this is required for error handling and logging. You do not have to worry about handling theparent_pid
argument in your algorithm, your algorithm must just accept it as the second argument.timeseries
- the algorithm must accept a time series as a list e.g.[[1578916800.0, 29.0], [1578920400.0, 55.0], ... [1580353200.0, 55.0]]
algorithm_parameters
- this is a dictionary of any of parameters that the algorithm requires.
Your algorithm should be a simple single function, see the example algorithms for guidance. It is possible that a multi classed algorithm could work, but your mileage may vary. This method is only tested with the algorithm being a simple function.
The custom algorithm must return a boolean to state whether the data point is anomalous and a
anomalyScore
, e.g.
# return (anomalous, anomalyScore)
return (True, 1.0)
return (False, 0.2)
The returned boolean must be one of the following three choices:
True
- the data point is anomalousFalse
- the data point is not anomalousNone
- returned when the algorithm could not determineTrue
orFalse
, an error occurred or there was no data, etc.
The returned
anomalyScore
must be a float between 0.0 and 1.0, 0.0 being not anomalous and 1.0 being a certain anomaly. You can pass (False, 0.7), you just have to normalise youranomalyScore
between 0.0 and 1.0. TheanomalyScore
is currently only for testing it is not used in any way but it must be returned. The anomalous classification is currently only determined from the boolean and theanomalyScore
is currently not used in any way other than for testing. If your algorithm does not calculate an anomaly score, when your algorithm returnsFalse
just return it with a 0.0 and when your algorithm returnsTrue
just return it with 1.0
Error handling
In the example algorithms there are examples of how to wrap your algorithm in normal Skyline algorithm exception handling method. Although you can implement your own logging in a custom algorithm, before you do, consider using the method described in the example algorithms, because the algorithms iterate over 1000s of time series every minute, logging all errors that are encountered in the developing or running of an algorithm is not practical (due to simply I/O) or desired. To accommodate error logging from algorithms, Skyline’s error handling method writes out any errors to a single file per algorithm during the analysis phase, overwriting the file with each error. The errors files are handled in the /tmp directory which is normal memory based tmpfs resources so no disk I/O is encountered. Once analysis is complete, the parent process checks for any algorithm error files and logs any errors found to the main application log once. As shown in the example below.
2020-06-07 05:47:40 :: 12856 :: error :: spin_process with pid 12870 has reported an error with the abs_stddev_from_median algorithm
2020-06-07 05:47:40 :: 12856 :: Traceback (most recent call last):
File "/opt/skyline/github/skyline/skyline/custom_algorithms/abs_stddev_from_median.py", line 46, in abs_stddev_from_median
make_an_error = median * UNDEFINED_VARIABLE
NameError: name 'UNDEFINED_VARIABLE' is not defined
This allows for errors to be encountered while not spewing 1000s and 1000s of lines of errors to disk based the application logs and incurring masses of I/O.
Example custom algorithms
There are two example custom algorithms in the repo for you to model the structure of your custom algorithm on.
This is the simplest custom algorithm structure, it does not have any
algorithm_parameters
and has no debug logging.
This is an example of a more complex custom algorithm structure, that uses
algorithm_parameters
and can even debug log to the Skyline app log if
debug_logging
is passed and enabled via the algorithm_parameters
.
https://github.com/earthgecko/skyline/tree/master/skyline/custom_algorithms/last_same_hours.py
Running a Mirage only custom algorithm on a metric all the time
Normally for Analyzer to push a metric to Mirage, Analyzer would have to trigger
on it as anomalous. However if you wish to run a custom algorithm on a metric
that requires SECOND_ORDER_RESOLUTION_HOURS
of data to run against as the
settings.FULL_DURATION
data is not sufficient for the custom algorithm,
perhaps due to seasonality, then you need to declare the metric in
settings.MIRAGE_ALWAYS_METRICS
. This will cause Analyzer to add the
metric to Mirage on every run. Note that the metric needs to be defined as a
mirage enabled metric in the normal way, ensuring it matches a smtp alert
defined in settings.ALERTS
with a SECOND_ORDER_RESOLUTION_HOURS
declared.
Some things to consider
Think about what Skyline apps you want your algorithm to run in. If you are wanting to use data >
settings.FULL_DURATION
then ensure you only specify'use_with': ['mirage', 'crucible'],
.Thoroughly test your algorithm with
debug_logging
Purposefully break your algorithm during testing to test and see how the error handling is working.
Any custom algorithms applied to analyzer must be FAST. Custom algorithms that are only applied to mirage and analyzer_batch can take a bit longer to run, but they will delay analysis the longer their execution time.


This article is part of the God object resolution series. To illustrate it, we use a running example through the whole series. So far, we dispatched the logics and the state of the God object into new features. This article is about the dispatch of the tests of the God object to the relevant features.
Each feature is now complete, but is not properly tested. The tests of the God object cover them but, since these features may be directly used elsewhere, it is important to ensure that they are correct, without the God object layer.
As we did for the code, we can move the test methods iteratively, one after the other. Following what we did for the code, we start with testing the hiring method. Two tests are on this method: retrieving a hired employee, and ensuring hiring generates different IDs. Let's take the latter:
@Test
public void testEmployeesHaveDifferentIDs() {
EmployeeManager manager = new EmployeeManager();
int employeeID1 = manager.hireEmployee(new TestEmployee());
int employeeID2 = manager.hireEmployee(new TestEmployee());
int employeeID3 = manager.hireEmployee(new TestEmployee());
assertNotEquals(employeeID1, employeeID2);
assertNotEquals(employeeID1, employeeID3);
assertNotEquals(employeeID2, employeeID3);
}
This logics is now in the EmployerImpl
, so we can replace the God object by this feature:
@Test
public void testEmployeesHaveDifferentIDs() {
Employer employer = new EmployerImpl(new HashMap<>());
int employeeID1 = employer.hireEmployee(new TestEmployee());
int employeeID2 = employer.hireEmployee(new TestEmployee());
int employeeID3 = employer.hireEmployee(new TestEmployee());
assertNotEquals(employeeID1, employeeID2);
assertNotEquals(employeeID1, employeeID3);
assertNotEquals(employeeID2, employeeID3);
}
This test can now be moved to a dedicated EmployerImplTest
class, unless you prefer to do move all its tests at once.
Notice the additional map we must create to instantiate the employer
.
Beside this, the test remains unchanged, showing a trivial case.
But it is not always the case, as we will see with the other hiring test:
@Test
public void testEmployeeCanBeRetrievedAfterHiring() {
Employee employee = new TestEmployee();
EmployeeManager manager = new EmployeeManager();
int employeeID = manager.hireEmployee(employee);
assertEquals(employee, manager.getEmployee(employeeID));
}
By replacing the God object by the feature, here is what we obtain:
@Test
public void testEmployeeCanBeRetrievedAfterHiring() {
Employee employee = new TestEmployee();
Map<Integer, Employee> employees = new HashMap<>();
Employer employer = new EmployerImpl(employees);
int employeeID = employer.hireEmployee(employee);
assertEquals(employee, employees.get(employeeID));
}
Beside the expected replacement, we must interact with the employees
map to retrieve the hired employee.
Indeed, the employer
provides no method to retrieve it.
This is not an issue, though, because it provides a test focusing on the hiring method alone.
We can now pass to the next test, which is firing the employee:
@Test
public void testEmployeeCannotBeRetrievedAfterFiring() {
Employee employee = new TestEmployee();
EmployeeManager manager = new EmployeeManager();
int employeeID = manager.hireEmployee(employee);
manager.fireEmployee(employeeID);
assertNull(manager.getEmployee(employeeID));
}
After the minimal replacement, here is what we obtain:
@Test
public void testEmployeeCannotBeRetrievedAfterFiring() {
Employee employee = new TestEmployee();
Map<Integer, Employee> employees = new HashMap<>();
Employer employer = new EmployerImpl(employees);
int employeeID = employer.hireEmployee(employee);
employer.fireEmployee(employeeID);
assertNull(employees.get(employeeID));
}
Similarly to the previous test, we had to interact directly with the map to retrieve the employee.
However, now that the employees
map is used as an external dependency, it is not enough to ensure that hiring and firing work together.
Indeed, other features will interact with our dependency, so we need to ensure that we properly use it.
In other words, we also need to ensure that when another feature adds an employee, we can properly fire it:
@Test
public void testEmployeeCannotBeRetrievedAfterFiring() {
Employee employee = new TestEmployee();
Map<Integer, Employee> employees = new HashMap<>();
Employer employer = new EmployerImpl(employees);
int employeeID = 123;
employees.put(employeeID, employee);
employer.fireEmployee(employeeID);
assertNull(employees.get(employeeID));
}
Rather than needing both tests (hire and fill map), we only need to keep the second (fill map). Indeed, a previous test already validates that hiring updates the map, so we can consider that they are equivalent. Said another way, the complete refactoring of the initial test correspond to the last version.
Another aspect highlighted by this test is the evolution of the coverage.
If you execute all the tests we have so far, you can see that EmployeeManager.fireEmployee(employeeID)
is not covered anymore.
In fact, the coverage is decreasing since we started the dispatch of the tests.
The reason why we didn't see it is that we removed calls to the hiring method of the God object, which is still in use in many other tests.
Thus, we reduced the amount of calls, but as long as we call it at least once it will remain covered.
The firing method, however, was called only in its own test, and now that the test have been dispatched, it is not called anymore.
The coverage decrease should occur iteratively, after each dispatched test, until the God object reaches a 0% coverage. Indeed, our current goal is to dispatch all the tests to their relevant features. If you plan to get rid of the God object, then it should be fine, since you will remove the code and the tests altogether. If instead you plan to transform it into a façade, then the next phases will provide you the right tests for that.
Coming back to our test dispatch, we have now refactored all the tests of EmployerImpl
.
If you didn't do it yet, you can move them to a dedicated EmployerImplTest
class.
The next test is for the EmployeeManager.setEmployee(employeeID, newDetails)
:
@Test
public void testEmployeeDetailsCanBeChanged() {
EmployeeManager manager = new EmployeeManager();
Employee employee = new TestEmployee();
int employeeID = manager.hireEmployee(employee);
Employee newDetails = new TestEmployee();
manager.setEmployee(employeeID, newDetails);
assertNotEquals(employee, manager.getEmployee(employeeID));
assertEquals(newDetails, manager.getEmployee(employeeID));
}
This method has been moved, but several elements have also been renamed, which leads us to a significant refactoring:
@Test
public void testEmployeeDetailsCanBeChanged() {
// Setup
Map<Integer, Employee> contracts = new HashMap<>();
int employeeID = 123;
Employee oldContract = new TestEmployee();
Employee newContract = new TestEmployee();
contracts.put(employeeID, oldContract);
// Execute
new EmployeeDetailsImpl(contracts).setContract(employeeID, newContract);
// Test
assertNotEquals(oldContract, contracts.get(employeeID));
assertEquals(newContract, contracts.get(employeeID));
}
As a summary, we:
contracts
;setEmployee(...)
by the renamed setContract(...)
;employee
variables by contract
variables ;contracts
map directly.
Since we didn't create a Contract
class, we still use the Employee
class for our contracts.
It may seem odd, but this is the result of the iterative process: you may do it before to reach this step, or you may leave it for later.
Although we didn't give it a proper highlight so far, you should not only run your tests after dispatching your code or test, but also check your test coverage.
As we mentionned, the progressive dispatch of the tests decreases the coverage of the God object, something we also observe here.
However, with the deeper refactoring of the test, we also decreased the coverage of EmployeeDetailsImpl
.
Indeed, the method getContract(employeeID)
is not covered anymore.
This should be fixed before to go further: since it is not covered, we know that no other test calls it, so we need to add one:
@Test
public void testEmployeeDetailsCanBeRetrieved() {
// Setup
Map<Integer, Employee> contracts = new HashMap<>();
int employeeID = 123;
Employee expectedContract = new TestEmployee();
contracts.put(employeeID, expectedContract);
// Execute
Employee actualContract = new EmployeeDetailsImpl(contracts).getContract(employeeID);
// Test
assertEquals(expectedContract, actualContract);
}
With this new test, we resolved our test coverage. We could have done it another way, by using the method in the previous test, like the original version. However, we wouldn't have properly tested the interaction with the map dependency. Rather than consisten behaviours between methods, we seek for consistency through this dependency.
Let's go now to the next test:
@Test
public void testEmployeeAddressCanBeChanged() {
EmployeeManager manager = new EmployeeManager();
Employee employee = new TestEmployee();
int employeeID = manager.hireEmployee(employee);
Address address1 = new TestAddress();
manager.setAddress(employeeID, address1);
assertEquals(address1, manager.getAddress(employeeID));
Address address2 = new TestAddress();
manager.setAddress(employeeID, address2);
assertNotEquals(address1, manager.getAddress(employeeID));
assertEquals(address2, manager.getAddress(employeeID));
}
Which we refactor as such:
@Test
public void testEmployeeAddressCanBeChanged() {
EmployeeDetails details = new EmployeeDetailsImpl(new HashMap<>());
int employeeID = 123;
Address address1 = new TestAddress();
details.setAddress(employeeID, address1);
assertEquals(address1, details.getAddress(employeeID));
Address address2 = new TestAddress();
details.setAddress(employeeID, address2);
assertNotEquals(address1, details.getAddress(employeeID));
assertEquals(address2, details.getAddress(employeeID));
}
Beside replacing the God object by its dedicated feature, we should notice another important point: the absence of contract.
Indeed, the God object allows to generate an employeeID
only through its hiring method.
We may dig in the code and see that it is not required, but these are implementation details, not something we can guess from the methods of the object.
With the dedicated feature, however, the employeeID
can be generated by hand, so we don't need to hire (or set a contract).
This is possible because this part of the state is externalized: we provide the contracts map to the constructor.
This is also for this reason that we could make the assertions directly on that map for the previous tests.
At the opposite, the addresses map is managed inside the details
instance, forcing us to use its getAddress(employeeID)
to do the assertions.
The test about the phone numbers is highly similar:
@Test
public void testEmployeePhoneNumberCanBeChanged() {
EmployeeManager manager = new EmployeeManager();
Employee employee = new TestEmployee();
int employeeID = manager.hireEmployee(employee);
String phone1 = "123456789";
manager.setPhoneNumber(employeeID, phone1);
assertEquals(phone1, manager.getPhoneNumber(employeeID));
String phone2 = "987654321";
manager.setPhoneNumber(employeeID, phone2);
assertNotEquals(phone1, manager.getPhoneNumber(employeeID));
assertEquals(phone2, manager.getPhoneNumber(employeeID));
}
Consequently, it goes through the same refactoring:
@Test
public void testEmployeePhoneNumberCanBeChanged() {
EmployeeDetails details = new EmployeeDetailsImpl(new HashMap<>());
int employeeID = 123;
String phone1 = "123456789";
details.setPhoneNumber(employeeID, phone1);
assertEquals(phone1, details.getPhoneNumber(employeeID));
String phone2 = "987654321";
details.setPhoneNumber(employeeID, phone2);
assertNotEquals(phone1, details.getPhoneNumber(employeeID));
assertEquals(phone2, details.getPhoneNumber(employeeID));
}
With that, we have refactored all the tests of the EmployeeDetailsImpl
.
If you didn't do it after each test, you can move them to a dedicated EmployeeDetailsImplTest
class.
The last tests are the following:
@Test
public void testEmployeeSalaryCanBeChanged() {
EmployeeManager manager = new EmployeeManager();
Employee employee = new TestEmployee();
int employeeID = manager.hireEmployee(employee);
double salary1 = 123;
manager.setSalary(employeeID, salary1);
assertEquals(salary1, manager.getSalary(employeeID), 0);
double salary2 = 456;
manager.setSalary(employeeID, salary2);
assertNotEquals(salary1, manager.getSalary(employeeID));
assertEquals(salary2, manager.getSalary(employeeID), 0);
}
@Test
public void testEmployeeSalaryCanBeRaised() {
EmployeeManager manager = new EmployeeManager();
Employee employee = new TestEmployee();
int employeeID = manager.hireEmployee(employee);
manager.setSalary(employeeID, 123);
manager.raiseSalary(employeeID, 321);
assertEquals(444, manager.getSalary(employeeID), 0);
}
We refactor them for SalarySettingsImpl
:
@Test
public void testEmployeeSalaryCanBeChanged() {
SalarySettings settings = new SalarySettingsImpl();
int employeeID = 42;
double salary1 = 123;
settings.setSalary(employeeID, salary1);
assertEquals(salary1, settings.getSalary(employeeID), 0);
double salary2 = 456;
settings.setSalary(employeeID, salary2);
assertNotEquals(salary1, settings.getSalary(employeeID));
assertEquals(salary2, settings.getSalary(employeeID), 0);
}
@Test
public void testEmployeeSalaryCanBeRaised() {
SalarySettings settings = new SalarySettingsImpl();
int employeeID = 42;
settings.setSalary(employeeID, 123);
settings.raiseSalary(employeeID, 321);
assertEquals(444, settings.getSalary(employeeID), 0);
}
And that's it! All the tests are now refactored and should be moved to the test classes of their corresponding features if you (still) didn't do it yet. The God object has no remaining test, and has reached a test coverage of 0%. At the opposite, the features it builds on are fully tested, with a 100% coverage.
 If you want to get rid of it, then you can directly refactor its uses to replace it with the features. If you want instead to keep it as a façade, then we must now transform it into one. If you are not sure what to do, check the final refactoring phase to see if the façade may be useful.


Tailor is a Python (Django) application designed to take your fabric commands, and make them executable from an API. Tailor is built with modularity in mind by binding explicitly to the Fabric file you supply. Fabric commands can be made accessible to the web API by adding the @tailored decorator.


¡Hola Buenos Aires!
Welcome to the Buenos Aires 2018 YOG Cultural Check lisk
Are you ready to play?
Yes!


London Transport Live Status
Last Updated:
Reload
Powered by TfL Open Data - Contains OS data © Crown copyright and database rights 2020
Website code and design © Nick Smith 2020<EMAIL_ADDRESS>Changelog:
09/01/2017 - Tube strike threw new status titles at me. Adjusted code to suit.
16/02/2020 - Didn't have a "Reduced service" option. Fixed!
22/02/2020 - Added icons, improved readability, altered colours to TFL standard and reduced code duplication


For full functionality of this website it is necessary to enable JavaScript.Here are the instructions how to enable JavaScript in your web browser.


Education Background
- Oct 2013 to 2017: B.A. In Sociology, Moi University (Nairobi Campus)
- July 2009 – June 2010:
Diploma in Project Management {upper credit}, Kenya Institute of Management
- April 2009 – June 2009:
Advanced certificate in Human Resource Management
{Upper credit}, Kenya Institute of management
- Jan 2009 – March 2009:
Certificate in Business Management {upper credit}, Kenya Institute of Management
-
Jan 2004 – Nov 2007:
Kenya Certificate of Secondary Education, {B- (Minus)},
Moi Equator Girls Secondary School
- Jan 1996 – Nov 2003: Kenya certificate of primary education, {B (Plain)},
Gitinga Primary School.
Proffesional Experience
- Monitoring & Evaluation Manager
MPEG Initiative, Kiambu County, March 2018 to Date
- Associate Program Officer; LINKAGES Project
NOPE, Kiambu County, Oct 2015 – February 2018
- Field Program Assistant/ M&E Assistant; NPI-SHAP Project
NOPE, Thika District, March 2011 - October 2011
Interest/Hobbies
- Riding Bike
- Community Service
- Travelling
- Watching Movies


Keep track of your ticket requests in one easy location.
You are about to delete your ticket request. This procedure is irreversible.
Do you want to proceed?


Google Earth Enterprise Documentation Home | Developers
Google Maps API v3 for GEE 5.x
- Overview
- How
geeCreateFusionMap
works geeCreateFusionMap
Factorygoogle.maps.Map
Method extensions- Examples
- KML Support
Overview
The Google Maps Javascript API V3 is bundled with Google Earth Enterprise (GEE) Server and, for offline use, with Portable Server. As of November 2015, Google Maps JavaScript API v3.20 is bundled with GEE v5.1.2, but the API is updated periodically to align with the Release version.
The bundled offline Google Maps JavaScript API is the same core Javascript V3 API supporting:
- Events: Listening to click, mouseover
- Controls: Built-in zoom, pan, scale + custom controls
- Overlays: Symbols, markers, polylines
However there are some differences:
- Method of invoking the API from a GEE or Portable Server to load in a web page.
geeCreateFusionMap
is a factory used to create instances of thegoogle.maps.Map
class.- No support for objects that require access to online Google services:
- Geocoding (
google.maps.Geocoder
) - Directions (
google.maps.Directions
) - StreetView (
google.maps.StreetViewPanorama
) - Traffic (
google.maps.TrafficLayer
) - Places API, Distance Matrix, Wikipedia, Panaramio, Weather layer, etc.
- Geocoding (
Using the Fusion Maps API
The Fusion Maps API is used to create and interact with map layers created in Google Earth Enterprise. The API is based on the Google Maps API but includes geeCreateFusionMap
, which makes it easier to interact with map layers generated by Google Earth Enterprise. Essentially, geeCreateFusionMap
is a factory used to create instances of the google.maps.Map
class in which the GEE-specific configuration options can be added as Method extensions.
The following code snippet is a Hello World example of using geeCreateFusionMap
to load a map:

<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />

<title>Hello World - GEE 2D Map Example</title>

Factory geeCreateFusionMap
Use of the factory geeCreateFusionMap
is distinct from the standard Google Maps JavaScript API usage in the following ways:
- Instantiate
geeCreateFusionMap
in order to create a Fusion map. This is a factory for an extended version of the Maps API v3google.maps.Map
class, and the other methods are the extensions to that class. - Use
geeCreateFusionMap
class instead ofgoogle.maps.Map
to create applications that use layers from GME or GEE. geeCreateFusionMap(container, opts?)
creates a new map inside the given HTML container, typically aDIV
element. Options are the same as those ofgoogle.maps.Map
- If a map type is passed into the options, GEE Server will override these if an imagery layer is included in the Fusion Maps Database.
- The path and location of the new map is
serverURL/default_map
, for example, http://my_host_name/default_map.
Factory geeCreateFusionMap Description
The Factory
and Method extensions
are described in the following tables.
Factory
| Factoryclass | Description |
|---|---|
geeCreateFusionMap(container, opts?) |
Creates a new Fusion map inside of the given HTML container, which is typically a DIV element. The options are the same as the options for google.maps.Map . However, if a map type is passed in to the options, the Fusion maps server will override these if an imagery layer is included in the Fusion Maps Database. After this constructor is invoked, the setCenter() method should be called before any methods that display Fusion layers on top of the map. |
Method extensions
geeCreateFusionMap
Method extensions are extensions of the Google Maps API v3 google.maps.Map
class.
| Method extensions | Return Value | Description |
|---|---|---|
showInitialFusionLayers() |
None | Show all layers that are enabled by default. This method should only be invoked after the setCenter() |
getFusionLayerCount() |
Number | Returns the number of Fusion map layers. This does not include the base imagery layer, which is built as a custom map type and serves as the background of the map. |
isFusionLayerVisible(index) |
Boolean | Returns true if the layer is currently shown on the map and false if it is hidden. |
showFusionLayer(index) |
None | Shows a previously hidden Fusion map layer. This method should only be invoked after the setCenter() method has been called to initially draw the map. |
hideFusionLayer(index) |
None | Hides the specified Fusion map layer. |
getFusionLayerName(index) |
String | Returns the name of the specified layer. |
getFusionLayerIcon(index) |
String | Returns the URL of the icon associated with the specified layer. |
Examples
Several examples that illustrate how to use the Fusion Maps API are installed by default. You can find these examples in:
/opt/google/gehttpd/htdocs/maps
The following files are used by default for a published database. For example, when serving http://your-host.com/YourPublishedDatabase
, this code is used to render the page.
maps_local.html
maps_google.html
The following files provide basic examples of initializing a Fusion Map. You can use them as templates but you'll need to edit them with the target path of a published 2D database to correctly initialize a map in the browser.
example_google.html
example_local.html
KML Support
The KMLLayer
object in the Google Maps Javascript API is unavailable in GEE since KML rendering is performed server-side and requires a connection to google.com. As a workaround, you can overlay KML data on your 2D Map using the GeoXml parser extension for Google Maps.
The following steps are needed to utilize the GeoXml library with 2D maps hosted on a Google Earth Enterprise Server:
- Download the GeoXml library to your GEE Server.
geoxmlfull_v3.js
is the main file to download. - Store the GeoXml library in the GEE Server Apache Document root. Default location is
/opt/google/gehttpd/htdocs/js
- Load the GeoXml library in your GEE 2D Map HTML file:

- Store the target KML file in the GEE Server Apache Document root.
- Create a GeoXml object in the GEE 2D Map HTML file to load your KML file. Refer to GeoXml-specific methods and options.
See GeoXml samples.
Note:
- Performance may degrade with large KML files.
- GeoXml is an open-source package, not supported by Google.


| I l@ve RuBoard |
4.7 The cPickle Module(Optional) The cPickle module shown in Example 4-13 contains a faster reimplementation of the pickle module. Example 4-13. Using the cPickle ModuleFile: cpickle-example-1.py try: import cPickle pickle = cPickle except ImportError: import pickle |
| I l@ve RuBoard |


(defmethod free-list-empty-p (size-class (heap free-list-heap)) ;; A free list is empty when the start points to itself. (let ((start (free-list-start heap size-class))) (= start (free-list-pointer size-class))))


2
Create Transaction
Insert Transaction Details and Sign
offline
There was an error creating the transaction
Step 1 Information
Information
Value
Mi
Max
To Address
Seed
---
Calculating Address Key Index
Cancel
Continue
Create Transaction
Save Signed Transaction
Raw Transaction
Signed Transaction


{include file="../application/common/view/web/agent/head.html" title=" - 系统管理"}
{include file="../application/common/view/web/agent/header.html"}
{include file="../application/common/view/web/agent/left.html"}
系统管理
-
系统管理
-
修改密码
修改密码
旧密码
新密码
再确认
确认并保存
{include file="../application/common/view/web/agent/footer.html"}
{include file="../application/common/view/web/agent/foot.html"}


Core_Utils
Core_CSS contains various classes, objects, utilities and widgets to facilitate the development of your application. Such as:
- Easing functions
- Gravatar helper
- Hash functions
- Locales (coreLocales)
- Pickers (corePickers)
- Storage engine
- Service classes
- Template engine
- Touch and swipe plugin
- Utilities functions (coreUtils)


in stock
1.50
in stock
20.00
only left one in stock
2.50
in stock
200.00
in stock
1,000.00
Subtotal
Shipping
Tax
36.00
2.00
200.00


FM House / alarciaferrer arquitectos
- Curated by Clara Ott
- about 11 hours
- version="1.0" encoding="UTF-8"? Architects: alarciaferrer arquitectos
- AreaArea of this architecture projectArea: 320.0 m2
- version="1.0" encoding="UTF-8"?YearCompletion year of this architecture project Year: 2016
- version="1.0" encoding="UTF-8"?PhotographsPhotographs: Federico Cairoli
- Lead Architect Joaquin Alarcia, Federico Ferrer Deheza
- Structural engineering Germán Serboraria
- Building Julio Quiroz
More Specs Less Specs
Text description provided by the architects. A holiday home of great size, but at the same time seeks to adapt its scale to those who use it. The proposal is based on dividing the program into two, as if it were two autonomous houses. This allows not only to condition the use according to your requirement, but also to feel an intense use of each environment.
The "lower" house has a more intimate relationship with the terrain and the nearby views, while the "superior", in contrast, seeks a more intense relationship with the distant views of the lake, the mountains and the steep slope. The layout of the whole house is linear, leaving all its rooms towards an optimal orientation, being only the main gallery, meeting point of the house, the environment that seeks to focus its disposition with the colored hill.
The inculpation of the vacuum through patios not only allows a better illumination and ventilation of the environments but also emphasizes its linear character, generating a more precise scale with its imposing context. The materials used are low maintenance and respond to structural and project logics that balance their presence with their environment.


Solo-Play mode
Private lessons would be a 3 hour window in which students would come to MIC with a project which they would like to work on. Students would work directly with a developer to build the project. The developer would break down the project into 3 hour sessions, and create a timeline of when the project can be expected to finish. The lessons will be very student driven in which the students would be introduced as a part of either a Creative Track or Gaming Track. Basically the track just adds a theme to get the student started on a project.
Game Developer | Game Track
Currently gaming is the most popular form of entertainment. This course will cover many of the basic lessons of how many of these games are made and more importantly how to make our own game. Many of the “simple” mobile games that we see today are replicable. We are always seeing “clones” of the same set of games, but for some reason only one or two become very popular. We will dive into what exactly is it that makes that game popular and how to build our own game.
Game Music Composer | Creative Track
Press start! [bing!] You are to collaborate with the Game Developer to create a mini sound library and a theme song for a game. Learn to organize, work as a team and communicate your artistic vision and bring out the best in the interactivity. The learning process will hone in your creative intuition to drive the making of your own song that fits the game criteria with Sonic-PI. We will be playing a lot of music. Listening is critical especially when it comes down to rhythm, tempo and tones. You will bring a collection of 20 game music midis. We will take a look at your selections of songs and identify structures for melodic and rhythmic motives that drives a story. There will be short exercises of music theory and song arrangements in the GarageBand to help create the composition of an original song for the project. At the end, you will present your final piece in the game. [continue?]
Authors and Contributors
You can @mention a GitHub username to generate a link to their profile. The resulting <a>
element will link to the contributor’s GitHub Profile. Hit up the instructors with Qs Charles Nguyen (@charles6), Aisis Chen (@aisis)
Support or Contact
Having trouble with Pages? Check out our documentation or contact support and we’ll help you sort it out.


Edifice:CSS & JS the Rails way
Edifice makes your Rails life easier. It's designed to simplify CSS & JS integration in your Rails app by following the principle of DRY, less obtrusive markup. Stop writing unnecessary javascript boilerplate, stop wasting time namespacing view CSS and start enjoying rails again.
But really now, what is Edifice?
 Add it to your Gemfile
:
gem 'edifice'
Namespacing CSS
Automatically generate a namespace for each of your views. Use it to fine tune styling on a page-by-page basis without worrying about altering your global names. After all thinking of names is hard, why not just use the view's name? Let edifice handle that for you:
Rather than:<body id="user_profile">
<body class="<%= edifice_body_classes %>">
<body class="c_users v_show l_application">
Page-level Javascript
Condensing your sites javascript assets into one master file is a performance requirement these days. It gets pretty confusing when you only want to run certain bits of code on different pages. Edifice solves this problem by enabling view specific JS.
Just add:userShow = {
onReady: function() {
alert('The users#show page is ready!');
}
}
The rest will be taken care of.
Site-wide Javascript
Reluctant to separate your JS by views? Edifice-widgets & traits unobtrusively hook up standard behaviors for you
Just add:<select name="country" data-widget="styled_select">
<input type="text" name="zipcode" data-trait="only_allow_numbers">
styled_select
is and what only_allow_numbers
means).
Avoid form boilerplate
Tired of writing standard code to deal with form errors? Wondering why rails' unobtrusive remote form's don't handle it for you? Let edifice-forms help you out:
Just add:<form data-remote="true" data-form="show_errors">
Easy non-persistent forms
Need a form that's not based on a DB-backed model? Still want to validate fields and write simple controllers? Yep, edifice-forms can help with that too:
Just add:class Feedback < Edifice::Forms::FormModel
attr_accessor :message
attr_accessor :email
validates :email, :presence => true, :format => {:with =><EMAIL_ADDRESS>validates :message, :presence => true
def save
SelfMailer.feedback(self).deliver
end
end
class FeedbacksController < ApplicationController
def create
respond_with @feedback = Feedback.create params[:feedback]
end
end
@feedback
is just like a normal model:
<%= form_for @feedback do |f| %>
Edifice is crafted by Percolate Studio and released under the MIT license


--- title: 'A Spoonful of Hugo: Page Bundles' authors: - alison date: '2019-02-21' summary: Why (and how) you should use Hugo's new page bundles feature image: caption: '[Photo by Joanna Kosinska on Unsplash](https://unsplash.com/photos/Prfs32wh-o4)' focal_point: 'center' categories: [hugo, blogdown] tags: [blogdown] ---
“Just a spoonful of Hugo helps the blog go down.” - me, only somewhat kidding
In this series, I’m sharing small spoonfuls of Hugo that I have learned that hopefully can help you get your site UP (and even better- more efficient, more streamlined, more automated). You can read the previous posts about my “Spoonful of Hugo” series about Hugo archetypes and Hugo versions.
This is my third post in this series and it is breaking news.
Well, not really breaking news, but you still may not know about it! Hugo v0.32 introduced a new feature called Page Bundles, as a way to organize the content files. Blogdown users rejoice that Davis Vaughn posted an issue on the rstudio/blogdown repo to enable this option, which Yihui added shortly before rstudio::conf 2019 🎉. Here is the snippet from the NEWS.md
:
“One benefit of using a page bundle instead of a normal page is that you can put resource files associated with the post (such as images) under the same directory of the post itself. This means you no longer have to put them under the
static/
directory, which has been quite confusing to Hugo beginners.”
What does a blogdown/Hugo site begin to look like without page bundles? I think here is a representative example from tidyverse.org (sorry tidyverse team- it’s not you, it’s the old Hugo).
For this team, they need an image for every post, which gets out of control pretty fast. Also, some ended up in static/
too, organized by post (which I have done on my own blog, though not well or consistently).
What would it look like to use page bundles?
content/
├── about
│ ├── index.md
├── posts
│ ├── 2015-07-23-hi-world
│ │ ├── bakers.csv
│ │ ├── image1.jpg
│ │ ├── image2.png
│ │ └── index.Rmd
│ └── 2015-07-24-bye-world
│ └── index.Rmd
One could call this bundled file structure “tidier” 🍱.
In the above, after serving site, index.html
files also get added to the bundle. In Hugo’s terms, these are leaf bundles. The resource files allowed in a bundle include page and non-page items like images, pdf, .csv files, etc.
This is instead of:
content/
├── about
│ ├── index.md
├── posts
│ ├── 2015-07-23-hi-world.Rmd
│ ├── bakers.csv
│ ├── image1.jpg
│ ├── image2.png
│ └── 2015-07-24-bye-world.Rmd
When you create a new bundled post, the actual content of the post goes in the index file of a page bundle. So:
# not bundled post
post/2015-07-23-hi-world.Rmd
# bundled post
post/2015-07-24-bye-world/index.Rmd
First, read the previous post on setting up a netlify.toml file. Since using Hugo page bundles depends on Hugo v0.32 or higher, you should go ahead and update hugo then update your netlify.toml with your updated version:
blogdown::update_hugo()
blogdown::hugo_version()
Now, let’s use the usethis package.
First, I’m going to demo here how to create a project-specific .Rprofile file- but know that you can do a user-level .Rprofile file too.
# install.packages("usethis") # uncomment this to install
usethis::edit_r_profile(scope = "project")
These helpful messages should print to your console: please note the “restart” reminder…
> usethis::edit_r_profile(scope = "project")
● Restart R for changes to take effect
✔ Setting active project to '/Users/alison/rprojs/alison.rbind.io'
● Modify '.Rprofile'
Now you could add this to your file:
# in .Rprofile of the website project
if (file.exists("~/.Rprofile")) {
base::sys.source("~/.Rprofile", envir = environment())
}
options(blogdown.new_bundle = TRUE)
The first code chunk above is from the blogdown book, where we describe a workaround for loading both user and project .Rprofile files (since R technically only reads one startup profile file).
If you don’t want this, you could add the blogdown options to your user .Rprofile instead using:
usethis::edit_r_profile(scope = "user")
Heck, while you are at it, you could set a bunch of options to make your blogdown life easier:
# in .Rprofile of the website project
if (file.exists("~/.Rprofile")) {
base::sys.source("~/.Rprofile", envir = environment())
}
options(
blogdown.author = "Alison Hill",
blogdown.ext = ".Rmd",
blogdown.subdir = "post",
blogdown.yaml.empty = TRUE,
blogdown.new_bundle = TRUE,
blogdown.title_case = TRUE
)
For the blogdown-specific options, any of these prepopulate content in your “New Post” Addin (I told you to use this here). There is a handy table from the blogdown book, summarized here:
blogdown.author
= author of new postsblogdown.ext
= default extension of new posts (can also be “.md” or “.Rmarkdown”)blogdown.subdir
= theme-specific, you need to know your theme and content folder hereblogdown.yaml.empty
= I told you to do that hereblogdown.new_bundle
= what this whole post is about!blogdown.title_case
= “nEed More coFFee” –> “Need More Coffee” (it tidies all your post titles to title case)Here is a massive .Rprofile gotcha: this file must end with a blank line. So make sure you add an empty line at the end of the file, then save it, and restart your R session.
Want to make your general R life easier in the future? Follow Yihui’s advice and do this in RStudio to ensure that all source files end with a newline:
After restarting R, try using the “New Post” Addin, this time with feeling. There is still one more gotcha though. Use the Addin to create your new bundled post. The only catch is that once you are looking at your exciting new post, you should delete the slug in the YAML (I posted an issue about this here).
The reason is that you want the link to your post to be:
http://alison.rbind.io/post/2019-02-21-hugo-page-bundles/
If you include the slug, the link to your post will be:
http://alison.rbind.io/post/2019-02-21-hugo-page-bundles/hugo-page-bundles
Another option is to update your config.toml
file with permalinks like Yihui suggests (but beware: this will change all your past links as well, requiring some Netlify redirects):
[permalinks]
post = "/:year/:month/:day/:slug/"
The default here from Hugo was /post/:year-:month-:day-:slug/:slug/
.
A small note: if you want to add relative links from a blog post to another post in your same blog. So [this](/post/2019-02-19-hugo-archetypes/)
becomes this.
Now, add images and data files to your ❤’s content! But you may want to do one more thing…
If you are anything like me, you may draft a blog post then come back to it later. For example, I started this post 2 days ago, but want to publish it today, 2019-10-03. The cool thing that was already built-in to blogdown is the “Update Metadata” Addin. With your blog post open (it should be called index.Rmd
)1, click on Addins and select “Update Metadata”. You should see a window like this:
Check the box to rename the file if the date has changed. RStudio will tell you your file has been deleted- which is technically true since the folder was renamed, but don’t panic!
Click YES. The index.Rmd
file that is now open should have an updated date field in the YAML. In your RStudio file viewer, you may want to click on “content” at this point then navigate back to view your post- then you will then see that the folder name now has an updated date too.
If no post is open, you will get an error: Warning message: The current document does not seem to contain YAML metadata
↩


--- layout: post status: publish published: true title: '3rd Annual Ivy Envy Bus Trip to Wrigley ' author: display_name: Corey Fineran login: Corey email<EMAIL_ADDRESS>url: '' author_login: Corey author_email<EMAIL_ADDRESS>wordpress_id: 6581 wordpress_url: http://ivyenvy.com/?p=6581 date: '2012-01-13 12:56:29 +0000' date_gmt: '2012-01-13 18:56:29 +0000' categories: - Ivy Envy - Events tags: - Rockies - Bus Trip - 2012 Bus Trip comments: [] ---
Tickets are now on sale for our bus trip to see the Cubs play the Rockies on August 25th. All of the info is on this flyer and email me -<EMAIL_ADDRESS>for any additional information.


pydrake.systems.meshcat_visualizer¶
Provides utilities for communicating with the browser-based visualization package, Meshcat:
-
pydrake.systems.meshcat_visualizer.
AddTriad
(vis, name, prefix, length=1.0, radius=0.04, opacity=1.0)¶ Initializes coordinate axes of a frame T. The x-axis is drawn red, y-axis green and z-axis blue. The axes point in +x, +y and +z directions, respectively. TODO(pangtao22): replace cylinder primitives with ArrowHelper or AxesHelper one they are bound in meshcat-python. :param vis: a meshcat.Visualizer object. :param name: (string) the name of the triad in meshcat. :param prefix: (string) name of the node in the meshcat tree to which this
triad is added.Parameters: - length – the length of each axis in meters.
- radius – the radius of each axis in meters.
- opacity – the opacity of the coordinate axes, between 0 and 1.
-
pydrake.systems.meshcat_visualizer.
ConnectMeshcatVisualizer
(builder, scene_graph, output_port=None, **kwargs)¶ Creates an instance of MeshcatVisualizer, adds it to the diagram, and wires the scene_graph pose bundle output port to the input port of the visualizer. Provides an interface comparable to ConnectDrakeVisualizer.
Parameters: - builder – The diagram builder used to construct the Diagram.
- scene_graph – The SceneGraph in builder containing the geometry to be visualized.
- output_port – (optional) If not None, then output_port will be connected to the visualizer input port instead of the scene_graph. get_pose_bundle_output_port(). This is required, for instance, when the SceneGraph is inside a Diagram, and we must connect the exposed port to the visualizer instead of the original SceneGraph port.
- kwargs are passed through to the MeshcatVisualizer (Additional) –
- constructor. –
Returns: The newly created MeshcatVisualizer object.
-
class
pydrake.systems.meshcat_visualizer.
MeshcatContactVisualizer
(meshcat_viz, force_threshold=0.01, contact_force_scale=10, plant=None)¶ Bases:
pydrake.systems.framework.LeafSystem_[float]
MeshcatContactVisualizer is a System block that visualizes contact forces. It is connected to (1) the pose bundle output port of a SceneGraph, and (2) the contact results output port of the SceneGraph’s associated MultibodyPlant.
-
__init__
(meshcat_viz, force_threshold=0.01, contact_force_scale=10, plant=None)¶ Parameters: - meshcat_viz – A pydrake MeshcatVisualizer instance.
- force_threshold – contact forces whose norms are smaller than force_threshold are not displayed.
- contact_force_scale – a contact force with norm F (in Newtons) is displayed as a cylinder with length F/contact_force_scale (in meters).
- plant – the MultibodyPlant associated with meshcat_viz.scene_graph.
-
DoPublish
(context, event)¶
-
-
class
pydrake.systems.meshcat_visualizer.
MeshcatPointCloudVisualizer
(meshcat_viz, draw_period=0.03333333333333333, name='point_cloud', X_WP=<pydrake.common.eigen_geometry.Isometry3_[float] object>, default_rgb=[255.0, 255.0, 255.0])¶ Bases:
pydrake.systems.framework.LeafSystem_[float]
MeshcatPointCloudVisualizer is a System block that visualizes a PointCloud in meshcat. The PointCloud:
- Must have XYZ values. Assumed to be in point cloud frame,
P
. - RGB values are optional; if provided, they must be on the range [0..255].
An example using a pydrake MeshcatVisualizer:
viz = builder.AddSystem(MeshcatVisualizer(scene_graph)) pc_viz = builder.AddSystem( MeshcatPointCloudVisualizer(viz, viz.draw_period))
Using a native meshcat.Visualizer:
viz = meshcat.Visualizer() pc_viz = builder.AddSystem(MeshcatPointCloudVisualizer(viz))
- System YAML
- name: MeshcatPointCloudVisualizer input_ports: - point_cloud_P
-
__init__
(meshcat_viz, draw_period=0.03333333333333333, name='point_cloud', X_WP=<pydrake.common.eigen_geometry.Isometry3_[float] object>, default_rgb=[255.0, 255.0, 255.0])¶ Parameters: - meshcat_viz – Either a native meshcat.Visualizer or a pydrake MeshcatVisualizer object.
- draw_period – The rate at which this class publishes to the visualizer.
- name – The string name of the meshcat object.
- X_WP – Pose of point cloud frame
P
in meshcat world frameW
. Default is identity. - default_rgb – RGB value for published points if the PointCloud does not provide RGB values.
-
DoPublish
(context, event)¶
- Must have XYZ values. Assumed to be in point cloud frame,
-
class
pydrake.systems.meshcat_visualizer.
MeshcatVisualizer
(scene_graph, draw_period=0.03333333333333333, prefix='drake', zmq_url='default', open_browser=None, frames_to_draw={}, frames_opacity=1.0, axis_length=0.15, axis_radius=0.006, **kwargs)¶ Bases:
pydrake.systems.framework.LeafSystem_[float]
MeshcatVisualizer is a System block that connects to the pose bundle output port of a SceneGraph and visualizes the scene in Meshcat.
The most common workflow would be to run:
bazel run @meshcat_python//:meshcat-server
in another terminal, open the url printed in that terminal in your browser, then to run drake apps (potentially many times) that publish to that default url.
-
__init__
(scene_graph, draw_period=0.03333333333333333, prefix='drake', zmq_url='default', open_browser=None, frames_to_draw={}, frames_opacity=1.0, axis_length=0.15, axis_radius=0.006, **kwargs)¶ Parameters: - scene_graph – A SceneGraph object.
- draw_period – The rate at which this class publishes to the visualizer.
- prefix – Appears as the root of the tree structure in the meshcat data structure
- zmq_url – Optionally set a url to connect to the visualizer.
Use
zmp_url="default"
to the value obtained by running a singlemeshcat-server
in another terminal. Usezmp_url=None
orzmq_url="new"
to start a new server (as a child of this process); a new web browser will be opened (the url will also be printed to the console). Use e.g.zmq_url="tcp://<IP_ADDRESS>:6000"
to specify a specific address. - open_browser – Set to True to open the meshcat browser url in your default web browser. The default value of None will open the browser iff a new meshcat server is created as a subprocess. Set to False to disable this.
- frames_to_draw –
a dictionary describing which body frames to draw. It is keyed on the names of model instances, and the values are sets of the names of the bodies whose body frames are shown. For example, if we want to draw the frames of body “A” and “B” in model instance “1”, then frames_to_draw is
{“1”: {“A”, “B”}}. - axis_length and axis_radius are the opacity, length (frames_opacity,) – and radius of the coordinate axes to be drawn.
Additional kwargs will be passed to the MeshcatVisualizer constructor. .. note:
This call will not return until it connects to the ``meshcat-server``.
-
static
add_argparse_argument
(parser)¶ Provides a common command-line interface for including meshcat support in a python executable. Example:
parser = argparse.ArgumentParser(description=__doc__) ... MeshcatVisualizer.add_argparse_argument(parser) ... args = parser.parse_args() ... if args.meshcat: meshcat = builder.AddSystem(MeshcatVisualizer( scene_graph, zmq_url=args.meshcat, open_browser=args.open_browser))
-
DoPublish
(context, event)¶
-
load
()¶ Loads
meshcat
visualization elements.- Precondition:
- The
scene_graph
used to construct this object must be part of a fully constructed diagram (e.g. viaDiagramBuilder.Build()
).
-
publish_recording
(play=True, repetitions=1)¶ Publish any recorded animation to Meshcat. Use the controls dialog in the browser to review it.
Parameters: - play – boolean that determines whether the animation will play automatically.
- repetitions – number of times that the animation should play.
-
reset_recording
()¶ Resets all recorded data.
-
set_planar_viewpoint
(camera_position=[0, -1, 0], camera_focus=[0, 0, 0], xmin=-1, xmax=1, ymin=-1, ymax=1)¶ Sets meshcat to use an orthographic projection with locked out orbit controls, and turns off the background, axes, and grid. This allows meshcat to play a role similar to PlanarSceneGraphVisualizer.
Parameters: - camera_position – a 3 element vector specifying the initial xyz location of the camera.
- camera_focus – a 3 element vector specifying the focal point of the camera.
- xmax, ymin, ymax (xmin,) – Scalars specifying the initial view coordinates of the orthographic camera. (Note that xmax is actually ignored because the view is scaled to fit the size of the browser window).
Note: The orientation of the camera will be locked, but users can still pan and zoom interactively in the browser.
-
start_recording
()¶ Sets a flag to record future publish events as animation frames.
-
stop_recording
()¶ Disables the recording of future publish events.
-


SQAB is committed to simplifying the transition to quantitative behavior analysis for students as well as advanced researchers. These videos of presentations from leaders in the field are at various levels and are appropriate for individual, classroom, and seminar use. Individual video presentations can be accessed by clicking on the appropriate links below. All of the videos can be accessed on our YouTube channel.


~ Parts ~
Submission Deadline: Sunday, Jun 14, 2020 at 11:59 PM (Hawaii Time)
| Project | Part | Downloads |
|---|---|---|
| The End Begins To Rock | Trumpet 3 | sheet music click track reference track |
| Project | Part | Downloads |
|---|---|---|
| The End Begins To Rock | Trumpet 3 | sheet music click track reference track |


任職於趨勢科技: 多平台密碼管理解決方案
1.以無停機的解決方案將服務及基礎建設從自架資料中心移轉到AWS上
2.開發訂閱制
3.完成基礎架設一鍵部署
4.服務容器化，升級php
5.服務監控
1.任職於岱鐠科技
2.是一款高度客製化的人資系統,適用大部分的中小型企業
3.主要負責功能:考勤,差假,排班,簽核(呈),績效考核,薪資核算 4.結合Line@ 提供額外附加功能,如:Line打上下班卡,資訊通知
1.任職於緯創資通
2.GINA Talk能協助使用者在不同的即時訊息平台上傳送訊息以及安排工作給朋友、夥伴和工作群組。實現跨平台的單人以及群組對話
3.透過不同平台上的聊天機器人(chatbot),收發訊息. 主要是以MS botframework開發
4.支援的平台有 Facebook,Line,Skype,微信,Amazon Alexa.
5.實現即時翻譯
6.Alexa backend: written in python ; powered by amazon lambda
1.協助實驗室同儕獲取實驗數據,以進行意見領袖探勘
2.透過python scrapy, 多線程的抓取資料 3.搭配 selenium , 解決必須手動登入,獲取cookie的頁面
1.單位:陸軍司令部人事軍務處
2.功能:人事資料查詢,客製化兵力報表,專長分類,KPI
3.維護並延續開發功能, 此網站於2018二月過年時,因raid損壞,遺失所有資料,團隊透過程式碼重建資料結構與預設資料
Eric who is our backend engineer from Identity Group. With his enthusiasm,
he is always looking for a better solution and willing to take the challenge to adopt new technology into our team.
He started to involve Password Manager backend implementation since Q1 this year. Due to Password Manager is an old project which started from 6 years ago,
he realized that there is some legacy issue such as no local development environment, out-of-date operation system, and unreliable deployment process.
Then he raised his hand to the team and requesting some help from others.
However, as a junior engineer, he has been told by other peers that it is not easy to migrate and resolve for some reasons. From his standpoint, the most simple way for him is keeping the same way it was and let the issues and concerns remain.
In consist, Erik Wu decided to take a further step, besides working on new features, he spent his off-duty time and working on PoC to establish new containerized solution on his local environment to prove it works first
then he continued to communicate with the team, at the end, now the new workflow has become to our team standard practice.
Therefore, I would like to admire his right attitude when facing issues. Not compliant but do conquer. Not concerns but do control.
For the new build process and new framework, due to there are some configuration and code structure changed would be made,
Erik Wu’s second challenge is how to convince our QA team and managers to push the new environment to our production line.
And our resource is already allocated and planned at that moment, there is no further resource to help on the testing for these changes.
Erik Wu choose a move that I would like to highlight to the team. He requested QA share their testing scripts and testing mind-map to him,
then he installed different client build such as mobile, PC to run the test cases one by one by himself.
He started to play as a QA role to test his new environment manually and automatically. He also integrated with code coverage tools to represent how is the confidence level between his testing and build quality.
Regarding this, I would also want to appreciate his breaking-silo mindset, as an engineer, we should always think about " how to " solve the problem instead of thinking " who should ".
服役不見得是一般人所認為的浪費一年，軍旅生涯讓我能夠有時間靜下心思考從前忙碌生活中找不到答案的問題，
小弟我運氣還不錯,專長選兵的時候有選到能寫code的單位,雜事雖然不少,辦公室忙碌但是長官們的工作氣氛都很好,
我還能天天寫code,也有十足的時間可以自學Django,ReactJs,Data science,受益良多,工作上業務主要有:
1.撰寫SQL server stored procedures
2.開發軍職人事系統(C#.Net),供長官查詢資料,如:兵力統計,編制/職缺/現員查詢
3.兵力報表
4.開發新兵小幫手(win form),軍事訓練小幫手,配籤輔助軟體,提供新訓單位便捷的服務
緯創與amazon攜手佈局語音助理裝置，我們團隊負責以開發amazon echo的應用軟體為主
1.團隊以scrum執行，快速建立Prototype
2.專案部分主要以MS Botframework開發跨平台通訊聊天機器人(Gina Talk),結合的平台有Line,Facebook,Wechat,Skype, Amazon Alexa
3.整合Alexa 即時翻譯與傳訊功能
C#.Net MS Bot Framework SQL Server Python nodeJs Amazon: AWS.Lambda.Alexa Skills
與12人的團隊一起開發Nueip人力資源管理系統，主要負責的功能有：打卡，考勤核算，薪資結算，以及簽核等功能。Nueip是個可以高度客製化，適合中小型企業的人資系統，它提供彈性的參數設定，能產生適合各家公司的規則。
我們依照功能來切割負責範圍，依據UI師及PM的需求實作前端佈局，以及後端功能實現，此外，我們對系統安全性以及可拓展性也有做十足的建設。相關的工作項目如下：
1.導入 Redis ,負載平衡架構,虛擬化.
2.Database, Queries 效能調校.
3.撰寫客戶端windows服務,windows form 程式.
4.撰寫cronJob,bash script, 管理 centos7 伺服器.
參與開發大戶託運訂單系統EasyShip,主要負責表單輸入輸出,後臺資料交換web services,此外,還有儘可能滿足客戶要客製化的需求
1.EasyShip自動化表單輸入
2.開發後台的SOAP資料交換
3.VBA: 將excel交易紀錄個別匯出成PDF格式收據.
4.替客服部門開發CRM績效考核工具
大學三年級時旅美當交換生的OPT program(Optional Practical Training),主要撰寫Hybrid apps,公司是接案公司,以州政府的專案為主,所屬團隊開發一個
以電動汽車充電車位為主的即時資訊系統
1.後端:處理停車場sensor回傳的資料,顯示於前端
2.前端:以Appcelerator(類似react native) 撰寫ios/Android apps


Titans' Nightwing Finally Appears In An Epic Season 2 Finale Trailer
by Charles Pulliam-MooreTitans has been taking its sweet arse time to show us the goods—the goods being Dick Grayson embracing his Nightwing identity that the series has been teasing for weeks. We’ve watched as the Titans went their separate ways because of Dick’s betrayal, leaving the former Boy Wonder broken, alone, and feeling as if there’s nothing left in the world for him. But that’s all about to change.
Ahead of Titans’ season two finale, DC Universe has just dropped a trailer teasing the team’s reunion to take Deathstroke out once and for all—and while they appear to be stronger than ever, they’re all still understandably terrified of the lethal assassin. But just as it seems Deathstroke might actually be able to defeat the show’s heroes, someone “new” shows up with a fancy pair of electrified batons.
Titans’ season two finale hits DC Universe on November 29.


|
Perl Weekly
Issue #228 - 2015-12-07 - Advent Season
latest | archive | by Yanick Champoux
|
|
With December comes back a beloved Perl tradition: the Advent calendars. In other seasonal news, Christmas is getting ever closer for Perl 6. And on a slightly more "bah humbug"ish note, the various Perl-related Kickstarters aren't doing so well right now. But hey, this season is known for its miracles, so... we never know. In the meantime, enjoy! ~ `/anick
|
|
|
|
Sponsors
|
Senior Applications Engineer
Uniregistry is looking for a talented and passionate engineer to build and maintain a world-class registry and registrar. This position requires the ability to analyze and implement elegant solutions to complex problems while contributing to the development of reusable components
|
|
Supporting the Perl Weekly?
by Gabor Szabo (SZABGAB)
Would you like to support the Perl Weekly? A Perl Job ad in the Perl Weekly, like the one above, will reach almost 6000 Perl developers. People like you, who are enthusiastic about Perl and not just use it as an add-on tool.
|
|
|
Announcements
|
|
|
|
|
Articles
|
|
|
Making the Larry Wall shirt
by David Farrell (DFARRELL)
David made a cool "Larry Wall, hero of the revolution" t-shirt (if you want one, the Kickstarter is still ongoing, hurry!).  Matt reviews some of the proeminent Perl REPL out there for us.
|
|
Free go faster stripes for your Perl programs
by Sinan Unur (NANIS)
There is an an optimization coming for Perl 5.24 that might boost some benchmarks by 25% to 40%. Sinan gives the nitty gritty details of this upcoming nitro injection to the Perl engine.
|
|
|
|
|
Grants
|
November 2015 Grant Votes
by Makoto Nozaki
A grant to merge stabilize and merge Test::Stream and Test::Simple into perl-blead has been approved.
|
|
Perl 6
|
|
|
|
|
Advent Calendars
|
|
|
|
|
Weekly collections
|
|
|
Perl Maven Articles
|
|
|
Monitoring the most recent uploads to CPAN
Are you looking for a place to contribute. Here is the 100 most recently uploaded modules that are either missing the link to their repository, have no Travis-CI enabled, or have no license in the META files.
|
|
You know, you could get the Perl Weekly right in your mailbox. Every Week. Free of charge!
|


Genesis 38:12
And in process of time the daughter of Shuah Judah's wife died; and Judah was comforted, and went up unto his sheepshearers to Timnath, he and his friend Hirah the Adullamite.


SYNOPSIS: In late 2012, the Camden campus of Rutgers University where I studied graphic design came under fire. Seemingly out of the blue, Chris Christie, the Governor of New Jersey, endorsed a plan to overhaul the higher-education system in New Jersey. Part of the disclosure called for my school to be divorced from the Rutgers family and merge it to Rowan University. Worse yet, the Governor's plan was utterly lacking in detail. Students, their parents, and alumni did not have much awareness of this plan, so I decided to start a campaign against it.
CORRUPTION AND CAMDEN seem to accompany each other frequently when the city is mentioned in the media. At the break of the merger plan, it wasn't any different. The campus was just part of an elaborate plan involving both private investors such as George Norcross of Cooper Health Systems and New Jersey representatives including Senator Sweeney (D), Donald Norcross (D; Brother of George Norcross) to create an artificial state education funding pipeline by absorbing local property. Upon discovering the plan, I decided to create a website that allowed people to sign a petition against the plan.
The idea of the website was to bring everyone up to speed on the plan and allow them to take action. Along with the primary purpose of signing an online petition against the proposed plan and possible legislation, the R2RMerge website provided tools like targeted template emails, VOIP phone calls, representative meeting broadcasts, and general information regarding the proposal. Later the website turned into an organization with a vast network of alumni and professors, which enabled physical outreach and activism.
"WE DID IT." was the last message I sent out to the 14,000+ people who have participated in the movement. After months of hard work from the Rutgers Board of Governors and Trustees, politicians, students, parents, alumni, faculty and many others, the Senate, No. 2063 State of New Jersey 215th Legislature was signed and the campus of Rutgers Camden was prevented from merging with Rowan University. *Current news of UMDNJ merger with Rutgers University is a different news and has been in the planning for awhile.


Find all the people who share your articles on Google+
18/Nov 2013
Have you ever wonder how it was possible to build your** Google+ fan base** ? It is easy, of course, to find who have you in circle, but not to know** who has ever shared one of your article**. Say you are writing on several blogs and want to collect the list of people who shared it on Google+ , now an easy solution exists on WordiZ.it .
Nurturing your Google+ fan base
I am really excited to describe this new feature because I am using it quite extensively since it is available. I really think it helps your content marketing or social media strategy. Basically, it does only one thing : showing the people who put a link to your article on Google+. That’s it, nothing more, but there is a very deep scope behind that simple feature.
When you are writing an article on the web, you want to maximize mainly one thing : interactions. Interactions on your post could be seen as views,* number of comments, *incoming links or social media mentions. You cannot really do anything with the number of views, but you can engage people who create links, comment or share your post. That simple action will allow you to get more engaged readers and to turn them to ambassadors or fans.
So, you probably understand now how the new feature works. Publish on the web and WordiZ.it will collect automatically your articles and list all your Google+ sharers. Under your profile tab, you will find the link to this list. Open it, and you will be able to add any single fan to a dedicated circle, something like “my G+ readers” for instance.
Then, what to do next is up to you. You can either ping them when you publish something new, or just say “thanks” for their involvement … You can also comment below and tell us how you would use this feature.
Connect with the people who shared your top articles
In addition to an author-wise fan base, we also wanted to give you the opportunity to connect with people who shared a specific article. So, for all your top articles, you will find a quick link to “G+ fanbase” to see who exactly shared this article.
This way, you will easily be able to see individually who helped you to get your articles to the top. That’s a really great tool to create connections.


|
DistributedRobotWorld
|
#include <ObjectId.hpp>
Public Types | |
| typedef unsigned char | value_type |
| typedef unsigned char * | pointer |
| typedef const unsigned char * | const_pointer |
| typedef unsigned char & | reference |
| typedef const unsigned char & | const_reference |
| typedef std::vector< unsigned char > | base |
Public Member Functions | |
| template<typename InputIterator > | |
| ObjectId (InputIterator first, InputIterator last) | |
| ObjectId (const std::string &anObjectIdString) | |
| ObjectId & | operator= (const ObjectId &anObjectId) |
| bool | operator== (const ObjectId &anObjectId) const |
| bool | operator< (const ObjectId &anObjectId) const |
| std::string | toString () const |
| void | fromString (const std::string &anObjectIdString) |
| bool | isNull () const |
| bool | isValid () const |
Debug functions | |
| std::string | asString () const |
| std::string | asDebugString () const |
Static Public Member Functions | |
| static ObjectId | newObjectId () |
Static Public Attributes | |
| static std::string | objectIdNamespace = "" |
CORBA required interface for PortableServer::ObjectId and sequence< T > | |
| static pointer | allocbuf (unsigned long nelems) |
| static void | freebuf (pointer aT) |
| ObjectId () | |
| ObjectId (unsigned long max) | |
| ObjectId (unsigned long, unsigned long len, unsigned char *aDataPointer, bool) | |
| ObjectId (const ObjectId &anObjectId) | |
| virtual | ~ObjectId () |
| unsigned long | maximum () const |
| void | length (unsigned long len) |
| unsigned long | length () const |
| reference | operator[] (unsigned long index) |
| const_reference | operator[] (unsigned long index) const |
| bool | release () const |
| void | replace (unsigned long, unsigned long len, pointer newData, bool) |
| pointer | get_buffer (bool orphan=false) |
| const_pointer | get_buffer () const |
The ObjectId class is also used in Dagda. Therefore it has the required PortableServer::ObjectId / unbounded sequence interface.
The OID class is 16 bytes, this class is 24 bytes. If one is memory constraint the OID class may be of some help. Be warned: the OID class is not actively maintained anymore (but than, who reeds this besides me, the maintainer).
| typedef std::vector< unsigned char > Base::ObjectId::base |
| typedef const unsigned char* Base::ObjectId::const_pointer |
| typedef const unsigned char& Base::ObjectId::const_reference |
| typedef unsigned char* Base::ObjectId::pointer |
| typedef unsigned char& Base::ObjectId::reference |
| typedef unsigned char Base::ObjectId::value_type |
|
inline |
Default ctor.
Also specified by
|
inline |
Maximum ctor.
| max | Initial elements reservation |
|
inline |
Data ctor.
| max | Initial elements reservation. Is actually ignored |
| length | Length of the data |
| data | Start of the data |
| release | If true the sequences owns and manages any containing pointers Is actually ignored and always true. |
|
inline |
Makes a deep copy.
|
virtual |
Also specified by PortableServer::ObjectId and sequence< T >
|
inline |
|
inline |
|
inlinestatic |
Do not use. It always throws an Danu::InvalidRequest exception.
| nelems |
| std::string Base::ObjectId::asDebugString | ( | ) | const |
Returns a description of the object with all data of the object usable for debugging
| std::string Base::ObjectId::asString | ( | ) | const |
Returns a 1-line description of the object
|
inlinestatic |
Do not use. It always throws an Danu::InvalidRequest exception.
| aT | The buffer to free |
|
inline |
Calling obj1.fromString( obj2.toString()) has the same effect as assignment, obj1 = obj2.
| anObjectIdString | A string representation of an ObjectId. |
|
inline |
| orphan |
|
inline |
| bool Base::ObjectId::isNull | ( | ) | const |
| bool Base::ObjectId::isValid | ( | ) | const |
|
inline |
If the current length of the sequence is less than the new length we append new elements which are created by calling the default constructor. If the current length is more than the new length we just cut of the tail of the sequence.
| length | The new length of the sequence |
|
inline |
|
inline |
|
static |
This function returns an ObjectId that is guaranteed to be unique in the application it is generated in. If multiple application use the same library it is the responsibility of the applications to ensure uniqueness between applications.
| bool Base::ObjectId::operator< | ( | const ObjectId & | anObjectId | ) | const |
| anObjectId |
| bool Base::ObjectId::operator== | ( | const ObjectId & | anObjectId | ) | const |
| anObjectId |
|
inline |
| index |
|
inline |
| index |
|
inline |
This returns always true for a value container
|
inline |
| max | Is ignored |
| rel | Is ignored and is treated as true |
|
inline |
Calling obj1.fromString( obj2.toString()) has the same effect as assignment, obj1 = obj2.
|
static |
If an ObjectId should be really universal unique every application should have its own namespace


Fabrice Bellard
https://bellard.org/
make
./prog > lena.ppm
eog lena.ppm # On Linux
preview lena.ppm # On MacOS
wget http://upload.wikimedia.org/wikipedia/en/2/24/Lenna.png
pngtopnm < Lenna.png | pnmscale 0.25 | cjpeg -arithmetic -dct float -quality 14 > small.jpg
The file small.jpg
will be approximately of the same size as the raw image data
in the program. Compare the level of the detail and the artifacts of
small.jpg
and lena.ppm
.
Compressing images is just a matter of simple arithmetic and some magic, isn’t it?
We could understand some of the arithmetic but none of the magic.
Deciphering the mechanism used for data encoding to make use of the whitespaces, braces and semicolons should be a slightly easier task.
This program outputs a 128x128 RGB image file to the standard output using the portable pixmap file format (PPM). It contains the famous “Lena” image which is used in many image compression tests.
The uncompressed image is 12 times larger than the source code of the program which includes the image data and the complete decoder. The actual image data is 1220 byte long, which gives a compression ratio of 40. Using a JPEG-like algorithm would not be enough to reach this level of compression (the Lena image would be barely recognizable). So the algorithm is based on the latest advances in image compression. It includes the following features:
The image data is encoded to a C string with some tricks to make the best use of the IOCCC size constraints. The identifiers were shortened to a single letter to save space. No specific obfuscation was needed as the algorithms already have a significant complexity.
Although the program was optimized to decompress its built-in image, it accepts to decompress image files from its standard input. Examples:
./prog d < lena512.bin > lena512.ppm
./prog d < fruits.bin > fruits.ppm
./prog d < vintage_cars.bin > vintage_cars.ppm
The original images for fruits and vintage cars come from Wikipedia and were resized to a width of 1024 pixels. Warning: the program is not protected against invalid input.
The program should be portable on any Unix system. On Windows the line “setmode(0, 32768); setmode(1, 32768);” must be added at the start of the main() function to avoid unwanted carriage return characters in the output.
© Copyright 1984-2018,
Leo Broukhis, Simon Cooper, Landon Curt Noll
- All rights reserved |