text:
from pylab import *
from keyboard_reader import *
import sensel
import math
import copy
import pickle

with open("dict.txt") as word_file:
    english_words = set(word.strip().lower() for word in word_file)

keys_pressed = {
    'a': 0,
    'b': 0,
    'c': 0,
    'd': 0,
    'e': 0,
    'f': 0,
    'g': 0,
    'h': 0,
    'i': 0,
    'j': 0,
    'k': 0,
    'l': 0,
    'm': 0,
    'n': 0,
    'o': 0,
    'p': 0,
    'q': 0,
    'r': 0,
    's': 0,
    't': 0,
    'u': 0,
    'v': 0,
    'w': 0,
    'x': 0,
    'y': 0,
    'z': 0,
    ' ': 0,
    'shift': 0,
    'backspace': 0,
    ',': 0,
    '.': 0,
}

load_grid = False
save_grid = False
plot_x = []
plot_y = []
grid = [[copy.deepcopy(keys_pressed) for y in range(120)] for x in range(230)]
starting_x = 0
starting_y = 0
offset_x = 0
offset_y = 0
num_dogs = 2
prompt_str = ''
for i in range(num_dogs):
    prompt_str += 'the quick brown fox jumps over the lazy dog '

prompt_str1 = ('the quick brown fox jumps over the lazy dog '
              'pack my box with five dozen liquor jugs '
              'jackdaws love my big sphinx of quartz '
              'a quick movement of the enemy will jeopardize six gunboats '
              'wafting zephyrs quickly vexed jumbo ')

prompt_str2 = ('nerd nerd nerd nerd nerd nerd nerd nerd nerd nerd')

def openSensorReadContacts():
    sensel_device = sensel.SenselDevice()

    if not sensel_device.openConnection():
        print "Unable to open Sensel sensor!"
        exit()

    #Enable contact sending
    sensel_device.setFrameContentControl(sensel.SENSEL_FRAME_CONTACTS_FLAG)

    #Enable scanning
    sensel_device.startScanning()
    global starting_x
    global starting_y
    global grid
    print 'Please put 8 fingers in a \'starting position\'.'
    position_set = False
    while not position_set:
        contacts = sensel_device.readContacts()
        if len(contacts) == 8:
            for c in contacts:
                starting_x += int(c.x_pos_mm)
                starting_y += int(c.y_pos_mm)
            starting_x /= 8
            starting_y /= 8
            position_set = True
            #print 'starting_x: ', starting_x
            #print 'starting_y: ', starting_y
    if load_grid:
        grid = pickle.load(open('saved', 'rb'))
    else:
        print 'Please type:', prompt_str
        typed_chars = 0;
        done_calibrating = False

        while not done_calibrating:
            contacts = sensel_device.readContacts()

            if len(contacts) == 0:
                continue

            for c in contacts:
                if c.type == sensel.SENSEL_EVENT_CONTACT_INVALID:
                    pass
                elif c.type == sensel.SENSEL_EVENT_CONTACT_START:
                    sensel_device.setLEDBrightness(c.id, 100) #Turn on LED
                    print prompt_str[typed_chars]
                    radius = int((c.major_axis_mm + c.minor_axis_mm) / 4)
                    calibrate_key(prompt_str[typed_chars], int(c.x_pos_mm),
                                  int(c.y_pos_mm), radius)
                    typed_chars += 1
                elif c.type == sensel.SENSEL_EVENT_CONTACT_MOVE:
                    pass
                elif c.type == sensel.SENSEL_EVENT_CONTACT_END:
                    sensel_device.setLEDBrightness(c.id, 0) #Turn off LED
                else:
                    pass
            done_calibrating = typed_chars == len(prompt_str)

    if save_grid:
        pickle.dump(grid, open('saved', 'wb'))
    #show_plot()
    receive_input(sensel_device)

def calibrate_key(key, x_pos, y_pos, radius):
    n = 3
    keys_pressed[key] += 1
    for x in range(x_pos - radius * n, x_pos + radius * n + 1):
        for y in range(y_pos - radius * n, y_pos + radius * n + 1):
            if math.sqrt((x_pos - x)**2 + (y_pos - y)**2) <= radius * n:
                if (x >= 0 and x < 230 and y >= 0 and y < 120):
                    grid[x][y][key] += 1
                    plot_x.append(x)
                    plot_y.append(y)
                    #fix later

def receive_input(sensel_device):

    global offset_x
    global offset_y

    for key in keys_pressed:
        for x in range(len(grid)):
            for y in range(len(grid[x])):
                if keys_pressed[key] > 0:
                    grid[x][y][key] /= (keys_pressed[key] + 0.0)

    print 'Start typing! :)'
    typed_chars = 0
    #still_typing = True
    output_str = ''
    possible_letters = []
    possible_words = []
    delete_cooldown = 0
    cooldown_mult = 1

    while True:
        if delete_cooldown != 0:
            delete_cooldown += cooldown_mult
        if delete_cooldown > 100:
            delete_cooldown = 0

        contacts = sensel_device.readContacts()
        if len(contacts) == 0:
            continue

        if len(contacts) == 8 and len([c for c in contacts if c.type == sensel.SENSEL_EVENT_CONTACT_START]):
            new_starting_x = 0
            new_starting_y = 0
            for c in contacts:
                new_starting_x += int(c.x_pos_mm)
                new_starting_y += int(c.y_pos_mm)
            new_starting_x /= 8
            new_starting_y /= 8
            offset_x = starting_x - new_starting_x
            offset_y = starting_y - new_starting_y
            #print 'offset_x: ', offset_x
            #print 'offset_y: ', offset_y
            output_str = ''

        if (len(contacts) == 3 and
            len([c for c in contacts if c.total_force > 7000]) == 3 and
            delete_cooldown == 0 and len(output_str)):
            average_forces = 0
            for c in contacts:
                average_forces += c.total_force
            average_forces /= 3
            cooldown_mult = ((average_forces - 6000) / 1000) ** 2
            delete_cooldown += cooldown_mult
            #length_last_word = len(output_str.rsplit(None, 1)[-1])
            #output_str = output_str[:len(output_str) - length_last_word - 1]
            output_str = output_str[:len(output_str) - 1]
            print output_str

        for c in contacts:
            if c.type == sensel.SENSEL_EVENT_CONTACT_START:
                typed_chars += 1
                x = int(c.x_pos_mm) + offset_x
                y = int(c.y_pos_mm) + offset_y
                if x >= 229:
                    x = 229
                if x < 0:
                    x = 0
                if y >= 119:
                    y = 119
                if y < 0:
                    y = 0
                total = 0
                for letter in grid[x][y]:
                    total += grid[x][y][letter]
                key = max(grid[x][y], key=grid[x][y].get)
                smaller_dict = copy.deepcopy(grid[x][y])
                del smaller_dict[key]
                key2 = max(smaller_dict, key=smaller_dict.get)
                if total > 0:
                    #print 'most likely: ', key, ' prob: ', grid[x][y][key], ' %: ', grid[x][y][key] / total
                    #print '2nd likely: ', key2, ' prob: ', grid[x][y][key2], ' %: ', grid[x][y][key2] / total
                    #print '\n'
                    output_str += key
                possible_letters.append((key, key2))
                if key == ' ':
                    possible_letters.pop()
                    possible_words = find_possible_words([], possible_letters)
                    real_words = []
                    for word in possible_words:
                        if word in english_words:
                            output_str = output_str[:len(output_str) - len(word) - 1] + word + ' '
                            break
                    possible_letters = []
                print output_str

        #still_typing = typed_chars < 320

    sensel_device.stopScanning();
    sensel_device.closeConnection();

def find_possible_words(list_of_words, list_of_tuples):
    if len(list_of_tuples) > 12:
        return []
    if not len(list_of_tuples):
        return list_of_words
    if not len(list_of_words):
        for letter in list_of_tuples[0]:
            list_of_words.append(letter)
        return find_possible_words(list_of_words, list_of_tuples[1:])
    new_words = []
    for word in list_of_words:
        for letter in list_of_tuples[0]:
            new_words.append(word + letter)
    return find_possible_words(new_words, list_of_tuples[1:])

def show_plot():
    hist2d(plot_x,plot_y, range=[[0, 230], [0, 120]], bins=[230,120])
    plt.gca().invert_yaxis()
    show()

if __name__ == "__main__":
    openSensorReadContacts()


text:
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:orientation="vertical">

        <com.loopj.android.image.SmartImageView
            android:id="@+id/image"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:adjustViewBounds="true" />

        <LinearLayout
            android:id="@+id/ad"
            android:orientation="horizontal"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:layout_gravity="center_vertical|center_horizontal">

            </LinearLayout>

    </LinearLayout>

</ScrollView>

redpajama_set_name: RedPajamaGithub


text:
layout: post
title: "Jenius Engineer reading list #344"
author: "dedenf"
tags:
    - news
    - jenius

categories:
    - readinglist
    - engineer
published: true
canonical: https://jakartadev.org/daily-digest-514/
---

-[How To Build JWT's in Go (Golang)](https://qvault.io/2020/02/20/how-to-build-jwts-in-go-golang/)
- [How Docker Authentication Works: By Documentation, MITM, and Implementation](https://levelup.gitconnected.com/how-docker-authentication-works-by-documentation-mitm-and-implementation-e62cd7a31178)
- [Taking Back Software Engineering](https://www.infoq.com/presentations/redefining-software-engineering/)
- [How to migrate a database schema at scale](https://blog.logrocket.com/how-to-migrate-a-database-schema-at-scale/)
- [Intelligent DNS based load balancing at Dropbox](https://blogs.dropbox.com/tech/2020/01/intelligent-dns-based-load-balancing-at-dropbox/)


text:
layout: post
title: "Big Bang"
modified:
categories: blog
excerpt:
tags: [party, social]
image:
feature:
author: perrin
---

Event Name: The UFV Big Bang

Date and Time: March 31, 7 p.m until midnight

Building: Student Union (S) Building Great Hall

Description: Biggest party of the Winter semester, hosted by the PSA, BCSA and many others! Check out the DJ, play games, win prizes, or listen to UFV's very own String Theory!


text:
title: "MCollective » Configure » Servers"
layout: default
---

[middleware]: /mcollective/deploy/middleware/
[filters]: /mcollective/reference/ui/filters.html
[plugin_directory]: http://projects.puppetlabs.com/projects/mcollective-plugins/wiki
[facter_plugin]: http://projects.puppetlabs.com/projects/mcollective-plugins/wiki/FactsFacter
[ohai_plugin]: http://projects.puppetlabs.com/projects/mcollective-plugins/wiki/FactsOhai
[chef_classfile]: /mcollective/reference/integration/chef.html#class-filters
[subcollectives]: /mcollective/reference/basic/subcollectives.html
[registration]: /mcollective/reference/plugins/registration.html
[puppetdb]: /puppetdb/
[security_plugin]: #security-plugin-settings
[auditing]: /mcollective/simplerpc/auditing.html
[authorization]: /mcollective/simplerpc/authorization.html
[actionpolicy]: http://projects.puppetlabs.com/projects/mcollective-plugins/wiki/AuthorizationActionPolicy
[security_aes]: /mcollective/reference/plugins/security_aes.html
[security_overview]: /mcollective/security.html
[ssl_plugin]: /mcollective/reference/plugins/security_ssl.html
[activemq_tls_verified]: /mcollective/reference/integration/activemq_ssl.html#ca-verified-tls
[activemq_connector]: /mcollective/reference/plugins/connector_activemq.html
[rabbitmq_connector]: /mcollective/reference/plugins/connector_rabbitmq.html
[stdlib]: http://forge.puppetlabs.com/puppetlabs/stdlib
[client_config_ssl_plugin]: ./client.html#ssl-plugin-settings

{% capture badbool %}**Note:** Use these exact values only; do not use "true" or "false."{% endcapture %}

{% capture pluginname %}**Note:** Capitalization of plugin names doesn't matter; MCollective normalizes it before loading the plugin.{% endcapture %}

{% capture path_separator %}system path separator (colon \[`:`\] on \*nix, semicolon \[`;`\] on Windows){% endcapture %}

This document describes MCollective server configuration in MCollective 2.0.0 and higher. Older versions may lack certain fetaures.

Example / Index
-----

The following is an example MCollective server config file showing all of the major groups of settings. All of the setting names styled as links can be clicked, and will take you down the page to a full description of that setting.

[See below the example for a full description of the config file location and format.](#the-server-config-files)

# /etc/mcollective/server.cfg

# Connector settings (required):
# -----------------------------

connector = activemq
direct_addressing = 1

# ActiveMQ connector settings:
plugin.activemq.pool.size = 1
plugin.activemq.pool.1.host = middleware.example.net
plugin.activemq.pool.1.port = 61614
plugin.activemq.pool.1.user = mcollective
plugin.activemq.pool.1.password = secret
plugin.activemq.pool.1.ssl = 1
plugin.activemq.pool.1.ssl.ca = /var/lib/puppet/ssl/certs/ca.pem
plugin.activemq.pool.1.ssl.cert = /var/lib/puppet/ssl/certs/web01.example.com.pem
plugin.activemq.pool.1.ssl.key = /var/lib/puppet/ssl/private_keys/web01.example.com.pem
plugin.activemq.pool.1.ssl.fallback = 0

# RabbitMQ connector settings:
plugin.rabbitmq.vhost = /mcollective
plugin.rabbitmq.pool.size = 1
plugin.rabbitmq.pool.1.host = middleware.example.net
# ... etc., similar to activemq settings

# Security plugin settings (required):
# -----------------------------------

securityprovider = ssl

# SSL plugin settings:
plugin.ssl_client_cert_dir = /etc/mcollective.d/clients
plugin.ssl_server_private = /etc/mcollective.d/server_private.pem
plugin.ssl_server_public = /etc/mcollective.d/server_public.pem

# PSK plugin settings:
plugin.psk = j9q8kx7fnuied9e

# Facts, identity, and classes (recommended):
# ------------------------------------------

factsource = yaml
plugin.yaml = /etc/mcollective/facts.yaml
fact_cache_time = 300

identity = web01.example.com

classesfile = /var/lib/puppet/state/classes.txt

# Registration (recommended):
# -----------------------

registerinterval = 600
registration = agentlist
registration_collective = mcollective

# Subcollectives (optional):
# -------------------------

collectives = mcollective,uk_collective
main_collective = mcollective

# Auditing (optional):
# -------------------

rpcaudit = 1
rpcauditprovider = logfile
plugin.rpcaudit.logfile = /var/log/mcollective-audit.log

# Authorization (optional):
# ------------------------

rpcauthorization = 1
rpcauthprovider = action_policy

# Logging:
# -------

logger_type = file
loglevel = info
logfile = /var/log/mcollective.log
keeplogs = 5
max_log_size = 2097152
logfacility = user

# Platform defaults:
# -----------------

daemonize = 1
libdir = /usr/libexec/mcollective
ssl_cipher = aes-256-cbc

([↑ Back to top](#content))

The Server Config File(s)
-----

### Main Config File

MCollective servers are configured with the `/etc/mcollective/server.cfg` file. It contains MCollective's core settings, as well as settings for the various plugins.

> **Warning:** This file contains sensitive credentials, and should only be readable by the root user, or whatever user the MCollective daemon runs as.

### File Format

Each line consists of a setting, an equals sign, and a value:

    # setting = value
    connector = activemq

The spaces on either side of the equals sign are optional. Lines starting with a `#` are comments.

> **Note on Boolean Values:** MCollective's config code does not have consistent handling of boolean values. Many of the core settings will accept values of `1/0` and `y/n`, but will fail to handle `true/false`; additionally, each plugin can handle boolean values differently, and some of them do not properly handle the `y/n` values accepted by the core settings.
>
> Nearly all known plugins and core settings accept `1` and `0`. Until further notice, you should always use these for all boolean settings, as no other values are universally safe.

### Plugin Config Directory (Optional)

Many of MCollective's settings are named with the format `plugin.<NAME>.<SETTING_NAME>`. These settings can optionally be put in separate files, in the `/etc/mcollective/plugin.d/` directory.

To move a `plugin.<NAME>.<SETTING_NAME>` setting to an external file, put it in `/etc/mcollective/plugin.d/<NAME>.cfg`, and use only the `<SETTING_NAME>` segment of the setting. So this:

    # /etc/mcollective/server.cfg
    plugin.puppet.splay = true

...is equivalent to:

    # /etc/mcollective/plugin.d/puppet.cfg
    splay = true

Note that this doesn't work for settings like `plugin.psk`, since they have no `<SETTING_NAME>` segment; a setting must have at least three segments to go in a plugin.cfg file.

### Best Practices

You should manage your MCollective servers' config files with config management software (such as Puppet). While most settings in a deployment are the same, several should be different for each server, and managing these differences manually is impractical.

If your deployment is fairly simple and there is little division of responsibility (e.g. having one group in charge of MCollective core and another group in charge of several agent plugins), then you can manage the config file with a simple template.

If your deployment is large or complex, or you expect it to become so, you should manage MCollective settings as individual resources, as this is the only practical way to divide responsibilities within a single file.

Below is an example of how to do this using the `file_line` type from the [puppetlabs/stdlib module][stdlib]:

{% highlight ruby %}
    # /etc/puppet/modules/mcollective/manifests/setting.pp
    define mcollective::setting ($setting = $title, $target = '/etc/mcollective/server.cfg', $value) {
      validate_re($target, '\/(plugin\.d\/[a-z]+|server)\.cfg\Z')
      $regex_escaped_setting = regsubst($setting, '\.', '\\.', 'G') # assume dots are the only regex-unsafe chars in a setting name.

      file_line {"mco_setting_${title}":
        path  => $target,
        line  => "${setting} = ${value}",
        match => "^ *${regex_escaped_setting} *=.*$",
      }
    }

    # /etc/puppet/modules/mcollective_core/manifests/server/connector.pp
    # ...
    # Connector settings:
    mcollective::setting {
      'connector':
        value => 'activemq';
      'direct_addressing':
        value => '1';
      'plugin.activemq.pool.size':
        value => '1';
      'plugin.activemq.pool.1.host':
        value => $activemq_server;
      'plugin.activemq.pool.1.port':
        value => '61614';
      'plugin.activemq.pool.1.user':
        value => $activemq_user;
      'plugin.activemq.pool.1.password':
        value => $activemq_password;
      'plugin.activemq.pool.1.ssl':
        value => '1';
      'plugin.activemq.pool.1.ssl.fallback':
        value => '1';
    }
    # ...
{% endhighlight %}

([↑ Back to top](#content))

Required Settings
-----

### Connector Settings

connector = activemq
direct_addressing = 1

# ActiveMQ connector settings:
plugin.activemq.pool.size = 1
plugin.activemq.pool.1.host = middleware.example.net
plugin.activemq.pool.1.port = 61614
plugin.activemq.pool.1.user = mcollective
plugin.activemq.pool.1.password = secret
plugin.activemq.pool.1.ssl = 1
# When ssl == 1:
plugin.activemq.pool.1.ssl.ca = /var/lib/puppet/ssl/certs/ca.pem
plugin.activemq.pool.1.ssl.cert = /var/lib/puppet/ssl/certs/web01.example.com.pem
plugin.activemq.pool.1.ssl.key = /var/lib/puppet/ssl/private_keys/web01.example.com.pem
plugin.activemq.pool.1.ssl.fallback = 0

# RabbitMQ connector settings:
plugin.rabbitmq.vhost = /mcollective
plugin.rabbitmq.pool.size = 1
plugin.rabbitmq.pool.1.host = middleware.example.net
plugin.rabbitmq.pool.1.port = 61613
# ... etc., similar to activemq settings

MCollective always requires a connector plugin. The connector plugin is determined by the [middleware][] you chose for your deployment. Each connector plugin will have additional settings it requires.

> #### Shared Configuration
>
> * All servers and clients must use the same connector plugin, and its settings must be configured compatibly.
> * You must use the right connector plugin for your [choice of middleware][middleware].
> * The hostname and port must match what the middleware is using. The username and password must be valid login accounts on the middleware. If you are using [CA-verified TLS][activemq_tls_verified], the certificate must be signed by the same CA the middleware is using.

#### `connector`

Which connector plugin to use. This is determined by your [choice of middleware][middleware].

- _Default:_ `activemq`
- _Allowed values:_ `activemq`, `rabbitmq`, or the name of a third-party connector plugin. {{ pluginname }}

#### `direct_addressing`

Whether your middleware supports direct point-to-point messages. **This should usually be turned on,** although it is off by default. The built-in `activemq` and `rabbitmq` connectors both support direct addressing, as does the external `redis` connector. (The older `stomp` connector, however, does not.)

- _Default:_ `0`
- _Allowed values:_ `1`, `0`, `y`, `n` --- {{ badbool }}

#### ActiveMQ Connector Settings

ActiveMQ is the main middleware we recommend for MCollective. The ActiveMQ connector can use multiple servers as a failover pool; if you have only one server, just use a pool size of `1`.

> **Note:** This is only a summary of the most commonly used ActiveMQ settings; there are about ten more settings that can be used to tune the connector's performance. [See the ActiveMQ connector documentation][activemq_connector] for more complete details.

- **`plugin.activemq.pool.size`** --- How many ActiveMQ servers to attempt to use. _Default:_ (nothing)
- **`plugin.activemq.pool.1.host`** --- The hostname of the first ActiveMQ server. (Note that additional servers use the same settings as the first, incrementing the number.) _Default:_ (nothing)
- **`plugin.activemq.pool.1.port`** --- The Stomp port of the first ActiveMQ server. _Default:_ `61613` or `6163`, depending on the MCollective version.
- **`plugin.activemq.pool.1.user`** --- The ActiveMQ user account to connect as. If the `STOMP_USER` environment variable is set, MCollective will use its value instead of this setting.
- **`plugin.activemq.pool.1.password`** --- The password for the user account being used. If the `STOMP_PASSWORD` environment variable is set, MCollective will use its value instead of this setting.
- **`plugin.activemq.pool.1.ssl`** --- Whether to use TLS when connecting to ActiveMQ. _Default:_ `0`; _allowed:_ `1/0`, `true/false`, `yes/no`
- **`plugin.activemq.pool.1.ssl.fallback`** --- _(When `ssl == 1`)_ Whether to allow unverified TLS if the ca/cert/key settings aren't set. _Default:_ `0`; _allowed:_ `1/0`, `true/false`, `yes/no`
- **`plugin.activemq.pool.1.ssl.ca`** --- _(When `ssl == 1`)_ The CA certificate to use when verifying ActiveMQ's certificate. Must be the path to a `.pem` file. _Default:_ (nothing)
- **`plugin.activemq.pool.1.ssl.cert`** --- _(When `ssl == 1`)_ The certificate to present when connecting to ActiveMQ. Must be the path to a `.pem` file. _Default:_ (nothing)
- **`plugin.activemq.pool.1.ssl.key`** --- _(When `ssl == 1`)_ The private key corresponding to this node's certificate. Must be the path to a `.pem` file. _Default:_ (nothing)

#### RabbitMQ Connector Settings

The RabbitMQ connector uses very similar settings to the ActiveMQ connector, with the same `.pool.1.host` style of setting names.

[See the RabbitMQ connector documentation][rabbitmq_connector] for more complete details.

([↑ Back to top](#content))

### Security Plugin Settings

securityprovider = ssl

# SSL plugin settings:
plugin.ssl_client_cert_dir = /etc/mcollective/clients
plugin.ssl_server_private = /etc/mcollective/server_private.pem
plugin.ssl_server_public = /etc/mcollective/server_public.pem

# PSK plugin settings:
plugin.psk = j9q8kx7fnuied9e

MCollective always requires a security plugin. (Although they're called security plugins, they actually handle more, including message serialization.) Each security plugin will have additional settings it requires.

> #### Shared Configuration
>
> All servers and clients must use the same security plugin, and its settings must be configured compatibly.

It's possible to write new security plugins, but most people use one of the three included in MCollective:

- **SSL:** The best choice for most users. Provides very good security when combined with TLS on the connector plugin (see above).
- **PSK:** Poor security, but easy to configure; fine for proof-of-concept deployments.
- **AES:** Complex to configure, and carries a noticable performance cost in large networks. Only suitable for certain use cases, like where TLS on the middleware is impossible.

For a full-system look at how security works in MCollective, see [Security Overview][security_overview].

#### `securityprovider`

Which security plugin to use.

- _Default:_ `psk`
- _Allowed values:_ `ssl`, `psk`, `aes_security`, or the name of a third-party security plugin. {{ pluginname }}

#### SSL Plugin Settings

> **Note:** This security plugin requires you to manage and distribute SSL credentials. [See the SSL security plugin page][ssl_plugin] for full details. In summary:
>
> * All servers share **one** "server" keypair. They must all have a copy of the public key and private key.
> * Every admin user must have a copy of the server public key.
> * Every admin user has their own "client" keypair.
> * Every server must have a copy of **every** authorized client public key.

All of these settings have **no default,** and must be set for the SSL plugin to work.

- **`plugin.ssl_server_private`** --- The path to the server private key file, which must be in `.pem` format.
- **`plugin.ssl_server_public`** --- The path to the server public key file, which must be in `.pem` format.
- **`plugin.ssl_client_cert_dir`** --- A directory containing every authorized client public key.

The client uses different settings, which are covered in the [client config reference][client_config_ssl_plugin]:

- `plugin.ssl_server_public`
- `plugin.ssl_client_private`
- `plugin.ssl_client_public`

#### PSK Plugin Settings

> **Note:** The only credential used by this plugin is a single shared password, which all servers and admin users have a copy of.

- **`plugin.psk`** --- The shared passphrase. If the `MCOLLECTIVE_PSK` environment variable is set, MCollective will use its value instead of this setting.

([↑ Back to top](#content))

Recommended Features
-----

### Facts, Identity, and Classes

factsource = yaml
plugin.yaml = /etc/mcollective/facts.yaml
fact_cache_time = 300

identity = web01.example.com

classesfile = /var/lib/puppet/state/classes.txt

MCollective clients use filters to discover nodes and limit commands. (See [Discovery Filters][filters] for more details.) These filters can use a variety of per-server metadata, including **facts, identity,** and **classes.**

* **Facts:** A collection of key/value data about a server's hardware and software. (E.g. `memorytotal = 8.00 GB`, `kernel = Darwin`, etc.)
* **Identity:** The name of the node.
* **Classes:** The Puppet classes (or Chef cookbooks, etc.) applied to this node. Classes are useful as metadata because they describe what _roles_ a server fills at your site.

None of these settings are mandatory, but MCollective is less useful without them.

#### `identity`

The node's name or identity. This **should** be unique for each node, but does not **need** to be.

- _Default:_ The value of Ruby's `Socket.gethostname` method, which is usually the server's FQDN.
- _Sample value:_ `web01.example.com`
- _Allowed values:_ Any string containing only alphanumeric characters, hyphens, and dots --- i.e. matching the regular expression `/\A[\w\.\-]+\Z/`

#### `classesfile`

A file with a list of classes applied by your configuration management system. This should be a plain text file containing one class name per line.

Puppet automatically writes a class file, which can be found by running `sudo puppet apply --configprint classfile`. [Chef can be made to write a class file][chef_classfile].

- _Default:_ `/var/lib/puppet/state/classes.txt`

#### `factsource`

Which fact plugin to use.

MCollective includes a fact plugin called `yaml`. Most users should use this default, set [the `plugin.yaml` setting (see below)](#pluginyaml), and arrange to fill the file it relies on.

Other fact plugins (including [Facter][facter_plugin] and [Ohai][ohai_plugin] ones) are available in the [plugin directory][plugin_directory]. These may require settings of their own.

- _Default:_ `yaml`
- _Allowed values:_ The name of any installed fact plugin, with the `_facts` suffix trimmed off. {{ pluginname }}

#### `plugin.yaml`

_When `factsource == yaml`_

The fact file(s) to load for [the default `yaml` fact plugin](#factsource).

- _Default:_ (nothing)
- _Sample value:_ `/etc/mcollective/facts.yaml`
- _Valid values:_ A single path, or a list of paths separated by the {{ path_separator }}.

**Notes:**

The default `yaml` fact plugin reads cached facts from a file, which should be a simple YAML hash. If multiple files are specified, they will be merged. (Later files override prior ones if there are conflicting values.)

**The user is responsible for populating the fact file;** by default it is empty, and MCollective has no facts.

If you are using Puppet and Facter, you can populate it by putting something like the following in your puppet master's `/etc/puppet/manifests/site.pp`, outside any node definition:

{% highlight ruby %}
    # /etc/puppet/manifests/site.pp
    file{"/etc/mcollective/facts.yaml":
      owner    => root,
      group    => root,
      mode     => 400,
      loglevel => debug, # reduce noise in Puppet reports
      content  => inline_template("<%= scope.to_hash.reject { |k,v| k.to_s =~ /(uptime_seconds|timestamp|free)/ }.to_yaml %>"), # exclude rapidly changing facts
    }
{% endhighlight %}

#### `fact_cache_time`

How long (in seconds) to cache fact results before refreshing from source. This can be ignored unless you're using a non-default `factsource`.

- _Default:_ `300`

([↑ Back to top](#content))

### Node Registration

registerinterval = 600
registration = agentlist
registration_collective = mcollective

> **Note:** We recommend that everyone using the ActiveMQ or RabbitMQ connector set a `registerinterval` of about 600 seconds (10m). You do not need to set a non-default registration plugin or configure a receiver for the registration messages. (If you do, you might want to extend the interval a bit to reduce load.)
>
> We do this to work around a set of annoyances in the underlying network protocols:
>
> * Stomp connections are completely idle when no messages are being sent.
> * Many firewalls will kill idle TCP connections after a while, which can cause nodes to drop out of the deployment at seemingly random times.
> * MCollective sets the keep-alive flag on its TCP connections, but most default OS configurations only send the first keep-alive packet after about two hours, so this doesn't really fix the problem. Nodes may still disappear for an hour or so, then come back.
> * Stomp 1.1 fixes this with protocol-level heartbeats, but the implementations haven't quite caught up and have had some bugs, so we can't rely on it yet.
>
> Thus, we work around all this by sending an irrelevant registration message every ten minutes, which keeps the connection alive (and will recover if it _does_ die) with a very lightweight amount of traffic.

By default, registration is disabled, due to [`registerinterval`](#registerinterval) being set to 0.

Optionally, MCollective servers can [send periodic heartbeat messages][registration] containing some inventory information. This can provide a central inventory at sites that don't already use something like [PuppetDB][], and can also be used as a simple passive monitoring system.

The default registration plugin, `agentlist`, sends a standard SimpleRPC command over the MCollective middleware, to be processed by some server with an agent called `registration` installed. You would need to ensure that the `registration` agent is extremely performant (due to the volume of message it will receive) and installed on a limited number of servers. If your [middleware][] supports detailed permissions, you must also ensure that it allows servers to send commands to the registration agent ([ActiveMQ instructions](/mcollective/deploy/middleware/activemq.html#detailed-restrictions)).

Some registration plugins (e.g. `redis`) can insert data directly into the inventory instead of sending an RPC message. This is a flexible system, and the user is in charge of deciding what to build with it, if anything. If all you need is a searchable inventory, [PuppetDB][] is probably closer to your needs.

#### `registerinterval`

How long (in seconds) to wait between registration messages. Setting this to 0 disables registration.

- _Default:_ `0`

#### `registration`

The [registration plugin][registration] to use.

This plugin must be installed on the server sending the message, and will dictate what the message contains. The default `agentlist` plugin will only send a list of the installed agents. See [Registration Plugins][registration] for more details.

- _Default:_ `agentlist`
- _Allowed values:_ The name of any installed registration plugin. {{ pluginname }}

#### `registration_collective`

Which subcollective to send registration messages to, when using a SimpleRPC-based registration plugin.

- _Default:_ (the value of [`main_collective`](#maincollective), usually `mcollective`)

([↑ Back to top](#content))

Optional Features
-----

### Subcollectives

collectives = mcollective,uk_collective
main_collective = mcollective

Subcollectives provide an alternate way of dividing up the servers in a deployment. They are mostly useful because the middleware can be made aware of them, which enables traffic flow and access restrictions. In multi-datacenter deployments, this can save bandwidth costs and give some extra security.

* [See the Subcollectives and Partitioning page][subcollectives] for more details and an example of site partitioning.

Subcollective membership is managed **on the server side,** by each server's config file. A given server can join any number of collectives, and will respond to commands from any of them.

> #### Shared Configuration
>
> If you are using any additional collectives (besides the default `mcollective` collective), your middleware must be configured to permit traffic on those collectives. See the middleware deployment guide for your specific middleware to see how to do this:
>
> * ActiveMQ: [Subcollective topic/queue names](/mcollective/deploy/middleware/activemq.html#topic-and-queue-names) --- [Multi-subcollective authorization example](/mcollective/deploy/middleware/activemq.html#detailed-restrictions-with-multiple-subcollectives)

#### `collectives`

A comma-separated list (spaces OK) of [subcollectives][] this server should join.

- _Default:_ `mcollective`
- _Sample value:_ `mcollective,uk_collective`

#### `main_collective`

The main collective for this server. Currently, this is only used as the default value for the [`registration_collective`](#registrationcollective) setting.

- _Default:_ (the first value of [the `collectives` setting](#collectives), usually `mcollective`)

([↑ Back to top](#content))

### Auditing

rpcaudit = 1
rpcauditprovider = logfile
plugin.rpcaudit.logfile = /var/log/mcollective-audit.log

Optionally, MCollective can log the SimpleRPC agent commands it receives from admin users, recording both the command itself and some identifying information about the user who issued it. The caller ID of a command is determined by the [security plugin][security_plugin] being used.

MCollective ships with a local logging audit plugin, called `Logfile`, which saves audit info to a local file (different from the daemon log file). Log lines look like this:

    2010-12-28T17:09:03.889113+0000: reqid=319719cc475f57fda3f734136a31e19b: reqtime=1293556143 caller=cert=nagios@monitor1 agent=nrpe action=runcommand data={:process_results=>true, :command=>"check_mailq"}

Tthere are central loggers available from [the plugin directory][plugin_directory], and you can also write your own audit plugins; see [Writing Auditing Plugins][auditing] for more information.

#### `rpcaudit`

Whether to enable [SimpleRPC auditing][Auditing] for all SimpleRPC agent commands.

- _Default:_ `0`
- _Allowed values:_ `1`, `0`, `y`, `n` --- {{ badbool }}

#### `rpcauditprovider`

The name of the audit plugin to use whenever SimpleRPC commands are received.

- _Default:_ (nothing)
- _Sample value:_ `logfile`
- _Allowed values:_ The name of any installed audit plugin. {{ pluginname }}

#### `plugin.rpcaudit.logfile`

_When `rpcauditprovider == logfile`_

The file to write to when using the `logfile` audit plugin. **Note:** this file is not automatically rotated.

- _Default:_ `/var/log/mcollective-audit.log`

([↑ Back to top](#content))

### Authorization

rpcauthorization = 1
rpcauthprovider = action_policy

Optionally, MCollective can refuse to execute agent commands unless they meet some requirement. The exact requirement is defined by an [authorization plugin][authorization].

See [SimpleRPC Authorization][authorization] for more details, including how to enable authorization for only certain agents.

The [actionpolicy][] plugin, which is provided in the [plugin directory][plugin_directory], is fairly popular and seems to meet many users' needs, when combined with a [security plugin][security_plugin] that provides a verified caller ID (such as the SSL plugin). [See its documentation][actionpolicy] for details.

#### `rpcauthorization`

Whether to enable [SimpleRPC authorization][Authorization] globally.

- _Default:_ `0`
- _Allowed values:_ `1`, `0`, `y`, `n` --- {{ badbool }}

#### `rpcauthprovider`

The plugin to use when globally managing authorization. See [SimpleRPC Authorization][authorization] for more details.

- _Default:_ (nothing)
- _Sample value:_ `action_policy`
- _Allowed values:_ The name of any installed authorization plugin. This uses different capitalization/formatting rules from the other plugin settings: if the name of the plugin (in the code) has any interior capital letters (e.g. `ActionPolicy`), you should use a lowercase value for the setting but insert an underscore before the place where the interior capital letter(s) would have gone (e.g. `action_policy`). If the name contains no interior capital letters, simply use a lowercase value with no other changes.

([↑ Back to top](#content))

Advanced Settings
-----

### Logging

logger_type = file
loglevel = info
logfile = /var/log/mcollective.log
keeplogs = 5
max_log_size = 2097152
logfacility = user

The MCollective server daemon can log to its own log file (which it will automatically rotate), or to the syslog. It can also log directly to the console, if you are running it in the foreground instead of daemonized.

Some of the settings below only apply if you are using log files, and some only apply if you are using syslog.

#### `logger_type`

How the MCollective server daemon should log. You generally want to use a file or syslog.

- _Default:_ `file`
- _Allowed values:_ `file`, `syslog`, `console`

#### `loglevel`

How verbosely to log.

- _Default:_ `info`
- _Allowed values:_ In increasing order of verbosity: `fatal`, `error` , `warn`, `info`, `debug`

#### `logfile`

_When `logger_type == file`_

Where the log file should be stored.

- _Default:_ (nothing; the package's default config file usually sets a platform-appropriate value)
- _Sample value:_ `/var/log/mcollective.log`

#### `keeplogs`

_When `logger_type == file`_

The number of log files to keep when rotating.

- _Default:_ `5`

#### `max_log_size`

_When `logger_type == file`_

Max size in bytes for log files before rotation happens.

- _Default:_ `2097152`

#### `logfacility`

_When `logger_type == syslog`_

The syslog facility to use.

- _Default:_ `user`

([↑ Back to top](#content))

### Platform Defaults

daemonize = 1
libdir = /usr/libexec/mcollective
ssl_cipher = aes-256-cbc

These settings generally shouldn't be changed by the user, but their values may vary by platform. The package you used to install MCollective should have created a config file with platform-appropriate values for these settings.

#### `daemonize`

Whether to fork and run the MCollective server daemon in the background.

This depends on your platform's init system. For example, newer Ubuntu releases require this to be false, while RHEL-derived systems require it to be true.

- _Default:_ `0`
- _Allowed values:_ `1`, `0`, `y`, `n` --- {{ badbool }}

#### `libdir`

Where to look for plugins. Should be a single path or a list of paths separated by the {{ path_separator }}.

By default, this setting is blank, but the package you installed MCollective with should supply a default server.cfg file with a platform-appropriate value for this setting. **If server.cfg has no value for this setting, MCollective will not work.**

- _Default:_ (nothing; the package's default config file usually sets a platform-appropriate value)
- _Sample value:_ `/usr/libexec/mcollective:/opt/mcollective`

#### `ssl_cipher`

The cipher to use for encryption. This is currently only relevant if you are using the [AES security plugin][security_aes].

This setting should be a standard OpenSSL cipher string. See `man enc` for a list.

- _Default:_ `aes-256-cbc`


text:
/*************************************************************************

         name: update.pl
  description: GoDiS-AOD update module.
               uses ADL = algorithm definition language
      authors: Original code (June 2002) by Staffan Larsson (SL)
               Modifications by SL and David Hjelm (DH)

*************************************************************************/

/*========================================================================
     Module Declaration
========================================================================*/

:- module(update,[update/0]).
%trindikit 3 or trindikit4

%TRINDIKIT4 test
:- ( current_module(tkit_properties)->
       use_module(trindikit(tkit_tis_access)),
       use_module(trindikit(tkit_operators));
       use_module(library(tis_access)),
       use_module(library(tis_operators))).

/*========================================================================
     Load rules
========================================================================*/

:- ensure_loaded(library(update_rules)).

/*========================================================================
     Load the ADL interpreter
========================================================================*/

%TRINDIKIT4 test
:- ( current_module(tkit_properties)->
       ensure_loaded(trindikit(tkit_dme_adl));
       ensure_loaded(library(dme_adl))).

/*========================================================================
   The update algorithm
========================================================================*/

update_algorithm( [
		   if not ($latest_moves == failed)
		   then [
			getLatestMoves,
			try backupSharedUsr,
			try irrelevantFollowup,
			try noFollowup,
			repeat(
			       [ repeat
			           ( [ integrate,
				     try downdate_issues,
				     try removeFindout,
				     try load_plan ]
              		            orelse apply shift( /private/nim ) )
			         until fully_shifted( $/private/nim ),
				 apply shift( /private/nim ),
				 try select_action,
				 accommodate, try retract
			       ] ),
			apply cancel_shift( /private/nim ),
			repeat exec_plan,
			try downdate_qud,
			repeat downdate_issues,
			repeat exec_plan,
			repeat removeYesNo %SL021125
		       ]
		  else
		  [ ( failedFollowup orelse try unclearFollowup ),
		    try noContact, %DH 031201
		    apply clear( /shared/lu/moves ) ] % this really needed???
		  ] ).

/*========================================================================
   Main predicate
========================================================================*/

update :-
	update_algorithm( Algorithm ),
	adl_exec( Algorithm ).


text:
module Resque
  class Job
    #
    #  Overwriting original create method to mark an item as queued
    #  after Resque::Job.create has called Resque.push
    #
    def self.create_with_loner(queue, klass, *args)
      return create_without_loner(queue, klass, *args) if Resque.inline?
      item = { class: klass.to_s, args: args }
      return 'EXISTED' if Resque::Plugins::Loner::Helpers.loner_queued?(queue, item)
      # multi block returns array of keys
      create_return_value = false
      Resque.redis.multi do
        create_return_value = create_without_loner(queue, klass, *args)
        Resque::Plugins::Loner::Helpers.mark_loner_as_queued(queue, item)
      end
      create_return_value
    end

    #
    #  Overwriting original reserve method to mark an item as unqueued
    #
    def self.reserve_with_loner(queue)
      item = reserve_without_loner(queue)
      Resque::Plugins::Loner::Helpers.mark_loner_as_unqueued(queue, item) if item && !Resque.inline?
      item
    end

    #
    #  Overwriting original destroy method to mark all destroyed jobs as unqueued.
    #  Because the original method only returns the amount of jobs destroyed, but not
    #  the jobs themselves. Hence Resque::Plugins::Loner::Helpers.job_destroy looks almost
    #  as the original method Resque::Job.destroy. Couldn't make it any dry'er.
    #
    def self.destroy_with_loner(queue, klass, *args)
      Resque::Plugins::Loner::Helpers.job_destroy(queue, klass, *args) unless Resque.inline?
      destroy_without_loner(queue, klass, *args)
    end

    #
    # Chain..
    #
    class << self
      alias_method :create_without_loner, :create
      alias_method :create, :create_with_loner
      alias_method :reserve_without_loner, :reserve
      alias_method :reserve, :reserve_with_loner
      alias_method :destroy_without_loner, :destroy
      alias_method :destroy, :destroy_with_loner
    end
  end
end


text:
using System;
using NUnit.Framework;

namespace NServiceKit.Text.Tests.JsonTests
{
    /// A type with public fields.
	[Serializable]
	public class TypeWithPublicFields
	{
        /// The text.
		public readonly string Text;

        ///
        /// Initializes a new instance of the NServiceKit.Text.Tests.JsonTests.TypeWithPublicFields
        /// class.
        ///
        /// <param name="text">The text.</param>
		public TypeWithPublicFields(string text)
		{
			Text = text;
		}
	}

    /// A public field test.
	[TestFixture]
	public class PublicFieldTest : TestBase
	{
        /// Public readonly fields can be deserialized.
		[Test]
		public void Public_readonly_fields_can_be_deserialized()
		{
			using (JsConfig.BeginScope())
			{
				JsConfig.IncludePublicFields = true;
				var instance = new TypeWithPublicFields("Hello");
				var deserilized = instance.ToJson();

				var copy = deserilized.FromJson<TypeWithPublicFields>();

				Assert.That(copy.Text, Is.EqualTo(instance.Text));
			}
		}
	}
}


text:
var Department = function(){}

Department.prototype.getTime = function() {
	return "Time at " + this.location + " is " + new Date().toUTCString();
}


text:
-- phpMyAdmin SQL Dump
-- version 4.3.11
-- http://www.phpmyadmin.net
--
-- Servidor: 127.0.0.1
-- Tiempo de generación: 04-11-2015 a las 12:27:20
-- Versión del servidor: 5.6.24
-- Versión de PHP: 5.6.8

SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
SET time_zone = "+00:00";

/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8 */;

--
-- Base de datos: `yii-curso-gustavo`
--

-- --------------------------------------------------------

--
-- Estructura de tabla para la tabla `auth_asignacion`
--

CREATE TABLE IF NOT EXISTS `auth_asignacion` (
  `itemname` varchar(64) NOT NULL,
  `userid` varchar(64) NOT NULL,
  `bizrule` text,
  `data` text
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

--
-- Volcado de datos para la tabla `auth_asignacion`
--

INSERT INTO `auth_asignacion` (`itemname`, `userid`, `bizrule`, `data`) VALUES
('rol_edicion', '1', NULL, 'N;');

-- --------------------------------------------------------

--
-- Estructura de tabla para la tabla `auth_items`
--

CREATE TABLE IF NOT EXISTS `auth_items` (
  `name` varchar(64) NOT NULL,
  `type` int(11) NOT NULL,
  `description` text,
  `bizrule` text,
  `data` text
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

--
-- Volcado de datos para la tabla `auth_items`
--

INSERT INTO `auth_items` (`name`, `type`, `description`, `bizrule`, `data`) VALUES
('editar_usuarios', 0, 'Esta operacion es para editar.', NULL, 'N;'),
('rol_edicion', 2, 'Esta tarea es para editar.', NULL, 'N;'),
('tarea_edicion', 1, 'Esta tarea es para editar.', NULL, 'N;');

-- --------------------------------------------------------

--
-- Estructura de tabla para la tabla `auth_relacion`
--

CREATE TABLE IF NOT EXISTS `auth_relacion` (
  `parent` varchar(64) NOT NULL,
  `child` varchar(64) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

--
-- Volcado de datos para la tabla `auth_relacion`
--

INSERT INTO `auth_relacion` (`parent`, `child`) VALUES
('tarea_edicion', 'editar_usuarios'),
('rol_edicion', 'tarea_edicion');

-- --------------------------------------------------------

--
-- Estructura de tabla para la tabla `categorias`
--

CREATE TABLE IF NOT EXISTS `categorias` (
  `id` int(11) NOT NULL,
  `nombre` varchar(255) NOT NULL
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=latin1;

--
-- Volcado de datos para la tabla `categorias`
--

INSERT INTO `categorias` (`id`, `nombre`) VALUES
(1, 'cat prueba 1');

-- --------------------------------------------------------

--
-- Estructura de tabla para la tabla `ciudad`
--

CREATE TABLE IF NOT EXISTS `ciudad` (
  `id` int(100) NOT NULL,
  `nombre` varchar(100) NOT NULL DEFAULT '0'
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=latin1;

--
-- Volcado de datos para la tabla `ciudad`
--

INSERT INTO `ciudad` (`id`, `nombre`) VALUES
(1, 'Madrids'),
(2, 'Lima'),
(3, 'Buenos Aires'),
(4, 'Quito'),
(5, 'Caracas'),
(6, 'Medellin');

-- --------------------------------------------------------

--
-- Estructura de tabla para la tabla `estudios`
--

CREATE TABLE IF NOT EXISTS `estudios` (
  `id` int(11) NOT NULL,
  `usuario_id` int(100) NOT NULL DEFAULT '0',
  `institucion` varchar(255) NOT NULL DEFAULT '0',
  `anio_graduacion` int(4) NOT NULL DEFAULT '0',
  `titulo` varchar(50) NOT NULL DEFAULT '0'
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

-- --------------------------------------------------------

--
-- Estructura de tabla para la tabla `experiencia`
--

CREATE TABLE IF NOT EXISTS `experiencia` (
  `id` int(11) NOT NULL,
  `usuario_id` int(100) NOT NULL DEFAULT '0',
  `empresa` varchar(200) NOT NULL DEFAULT '0',
  `inicio` date NOT NULL DEFAULT '0000-00-00',
  `finalizacion` date NOT NULL DEFAULT '0000-00-00',
  `jefe` varchar(100) NOT NULL DEFAULT '0'
) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=latin1;

--
-- Volcado de datos para la tabla `experiencia`
--

INSERT INTO `experiencia` (`id`, `usuario_id`, `empresa`, `inicio`, `finalizacion`, `jefe`) VALUES
(1, 1, 'empresa1', '2010-11-11', '2015-11-11', 'Osar'),
(2, 1, 'empresa2', '2005-11-11', '2008-11-11', 'pedro'),
(6, 1, 'Empresa3', '2015-09-01', '2015-10-01', 'Oscar'),
(7, 3, 'empresa5', '2015-10-01', '2015-10-24', 'Jefe empresa 5'),
(8, 2, 'empresa6', '2015-10-02', '2015-10-20', 'Jefe empresa 6');

-- --------------------------------------------------------

--
-- Estructura de tabla para la tabla `folio`
--

CREATE TABLE IF NOT EXISTS `folio` (
  `id` int(11) NOT NULL,
  `usuario_id` int(100) NOT NULL DEFAULT '0',
  `lugar` varchar(200) NOT NULL DEFAULT '0',
  `psicologica` int(10) NOT NULL DEFAULT '0',
  `tecnica` int(10) NOT NULL DEFAULT '0',
  `entrevista` int(10) NOT NULL DEFAULT '0',
  `puntaje` int(10) NOT NULL DEFAULT '0'
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=latin1;

--
-- Volcado de datos para la tabla `folio`
--

INSERT INTO `folio` (`id`, `usuario_id`, `lugar`, `psicologica`, `tecnica`, `entrevista`, `puntaje`) VALUES
(1, 1, 'B3', 3, 4, 3, 2),
(2, 2, 'B3', 5, 5, 5, 5),
(3, 2, 'C1', 1000000, 2500, 333333, 1000);

-- --------------------------------------------------------

--
-- Estructura de tabla para la tabla `tareas`
--

CREATE TABLE IF NOT EXISTS `tareas` (
  `id` int(11) NOT NULL,
  `nombre` varchar(255) NOT NULL,
  `descripcion` text NOT NULL
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=latin1;

--
-- Volcado de datos para la tabla `tareas`
--

INSERT INTO `tareas` (`id`, `nombre`, `descripcion`) VALUES
(1, 'task 1', 'descr 1'),
(2, 'task 2', 'descr 2'),
(3, 'task 3', 'descr 3');

-- --------------------------------------------------------

--
-- Estructura de tabla para la tabla `tareas_gii`
--

CREATE TABLE IF NOT EXISTS `tareas_gii` (
  `id` int(11) NOT NULL,
  `nombre` varchar(255) NOT NULL,
  `descripcion` text NOT NULL
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=latin1;

--
-- Volcado de datos para la tabla `tareas_gii`
--

INSERT INTO `tareas_gii` (`id`, `nombre`, `descripcion`) VALUES
(1, 'task1', 'descr1');

-- --------------------------------------------------------

--
-- Estructura de tabla para la tabla `usuarios`
--

CREATE TABLE IF NOT EXISTS `usuarios` (
  `id` int(100) NOT NULL,
  `ciudad_id` int(11) NOT NULL DEFAULT '0',
  `nombre` varchar(100) NOT NULL DEFAULT '0',
  `email` varchar(100) NOT NULL DEFAULT '0',
  `estado` tinyint(1) NOT NULL DEFAULT '0',
  `identificacion` int(100) NOT NULL DEFAULT '0',
  `genero` varchar(1) DEFAULT NULL,
  `username` varchar(255) NOT NULL,
  `password` varchar(255) NOT NULL,
  `session` text NOT NULL
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=latin1;

--
-- Volcado de datos para la tabla `usuarios`
--

INSERT INTO `usuarios` (`id`, `ciudad_id`, `nombre`, `email`, `estado`, `identificacion`, `genero`, `username`, `password`, `session`) VALUES
(1, 1, 'Juan prez', 'juan@gmail.com', 1, 1111114, 'M', 'juan', '123456', '5634c1ac298dc7.68408957'),
(2, 2, 'Pedro', 'pedro@gmail.com', 0, 222222222, 'M', '', '', ''),
(3, 2, 'Otra forma de EDITAR nombres', 'emain@hotmail.co', 1, 99999999, 'H', '', '', '');

-- --------------------------------------------------------

--
-- Estructura de tabla para la tabla `vacantes`
--

CREATE TABLE IF NOT EXISTS `vacantes` (
  `id` int(100) NOT NULL,
  `nombre` varchar(100) NOT NULL DEFAULT '0',
  `descripcion` varchar(200) NOT NULL DEFAULT '0',
  `estado` tinyint(1) NOT NULL
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=latin1;

--
-- Volcado de datos para la tabla `vacantes`
--

INSERT INTO `vacantes` (`id`, `nombre`, `descripcion`, `estado`) VALUES
(1, 'vacnte 1', 'csdc dscdsc dscdsc dscds', 0),
(2, 'vacante 2', 'sjc uasgduy auhdeiy kshdbeij skjd', 0),
(3, 'vacante 3', 'wudhwu uiwhd jduw', 0),
(4, 'vacante 3', 'skdj kdhi ksuhdbwd nsuodb', 0);

-- --------------------------------------------------------

--
-- Estructura de tabla para la tabla `vacantes_usuarios`
--

CREATE TABLE IF NOT EXISTS `vacantes_usuarios` (
  `vacantes_id` int(100) DEFAULT NULL,
  `usuarios_id` int(100) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

--
-- Volcado de datos para la tabla `vacantes_usuarios`
--

INSERT INTO `vacantes_usuarios` (`vacantes_id`, `usuarios_id`) VALUES
(1, 1),
(2, 2);

--
-- Índices para tablas volcadas
--

--
-- Indices de la tabla `auth_asignacion`
--
ALTER TABLE `auth_asignacion`
  ADD PRIMARY KEY (`itemname`,`userid`);

--
-- Indices de la tabla `auth_items`
--
ALTER TABLE `auth_items`
  ADD PRIMARY KEY (`name`);

--
-- Indices de la tabla `auth_relacion`
--
ALTER TABLE `auth_relacion`
  ADD PRIMARY KEY (`parent`,`child`), ADD KEY `child` (`child`);

--
-- Indices de la tabla `categorias`
--
ALTER TABLE `categorias`
  ADD PRIMARY KEY (`id`);

--
-- Indices de la tabla `ciudad`
--
ALTER TABLE `ciudad`
  ADD PRIMARY KEY (`id`);

--
-- Indices de la tabla `estudios`
--
ALTER TABLE `estudios`
  ADD PRIMARY KEY (`id`), ADD KEY `usuario_id` (`usuario_id`);

--
-- Indices de la tabla `experiencia`
--
ALTER TABLE `experiencia`
  ADD PRIMARY KEY (`id`), ADD KEY `usuario_id` (`usuario_id`);

--
-- Indices de la tabla `folio`
--
ALTER TABLE `folio`
  ADD PRIMARY KEY (`id`), ADD KEY `usuario_id` (`usuario_id`);

--
-- Indices de la tabla `tareas`
--
ALTER TABLE `tareas`
  ADD PRIMARY KEY (`id`);

--
-- Indices de la tabla `tareas_gii`
--
ALTER TABLE `tareas_gii`
  ADD PRIMARY KEY (`id`);

--
-- Indices de la tabla `usuarios`
--
ALTER TABLE `usuarios`
  ADD PRIMARY KEY (`id`), ADD KEY `ciudad_id` (`ciudad_id`);

--
-- Indices de la tabla `vacantes`
--
ALTER TABLE `vacantes`
  ADD PRIMARY KEY (`id`);

--
-- Indices de la tabla `vacantes_usuarios`
--
ALTER TABLE `vacantes_usuarios`
  ADD KEY `vacantes_id` (`vacantes_id`), ADD KEY `usuarios_id` (`usuarios_id`);

--
-- AUTO_INCREMENT de las tablas volcadas
--

--
-- AUTO_INCREMENT de la tabla `categorias`
--
ALTER TABLE `categorias`
  MODIFY `id` int(11) NOT NULL AUTO_INCREMENT,AUTO_INCREMENT=2;
--
-- AUTO_INCREMENT de la tabla `ciudad`
--
ALTER TABLE `ciudad`
  MODIFY `id` int(100) NOT NULL AUTO_INCREMENT,AUTO_INCREMENT=7;
--
-- AUTO_INCREMENT de la tabla `estudios`
--
ALTER TABLE `estudios`
  MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;
--
-- AUTO_INCREMENT de la tabla `experiencia`
--
ALTER TABLE `experiencia`
  MODIFY `id` int(11) NOT NULL AUTO_INCREMENT,AUTO_INCREMENT=9;
--
-- AUTO_INCREMENT de la tabla `folio`
--
ALTER TABLE `folio`
  MODIFY `id` int(11) NOT NULL AUTO_INCREMENT,AUTO_INCREMENT=4;
--
-- AUTO_INCREMENT de la tabla `tareas`
--
ALTER TABLE `tareas`
  MODIFY `id` int(11) NOT NULL AUTO_INCREMENT,AUTO_INCREMENT=4;
--
-- AUTO_INCREMENT de la tabla `tareas_gii`
--
ALTER TABLE `tareas_gii`
  MODIFY `id` int(11) NOT NULL AUTO_INCREMENT,AUTO_INCREMENT=2;
--
-- AUTO_INCREMENT de la tabla `usuarios`
--
ALTER TABLE `usuarios`
  MODIFY `id` int(100) NOT NULL AUTO_INCREMENT,AUTO_INCREMENT=4;
--
-- AUTO_INCREMENT de la tabla `vacantes`
--
ALTER TABLE `vacantes`
  MODIFY `id` int(100) NOT NULL AUTO_INCREMENT,AUTO_INCREMENT=5;
--
-- Restricciones para tablas volcadas
--

--
-- Filtros para la tabla `auth_asignacion`
--
ALTER TABLE `auth_asignacion`
ADD CONSTRAINT `auth_asignacion_ibfk_1` FOREIGN KEY (`itemname`) REFERENCES `auth_items` (`name`) ON DELETE CASCADE ON UPDATE CASCADE;

--
-- Filtros para la tabla `auth_relacion`
--
ALTER TABLE `auth_relacion`
ADD CONSTRAINT `auth_relacion_ibfk_1` FOREIGN KEY (`parent`) REFERENCES `auth_items` (`name`) ON DELETE CASCADE ON UPDATE CASCADE,
ADD CONSTRAINT `auth_relacion_ibfk_2` FOREIGN KEY (`child`) REFERENCES `auth_items` (`name`) ON DELETE CASCADE ON UPDATE CASCADE;

--
-- Filtros para la tabla `estudios`
--
ALTER TABLE `estudios`
ADD CONSTRAINT `estudios_ibfk_1` FOREIGN KEY (`usuario_id`) REFERENCES `usuarios` (`id`);

--
-- Filtros para la tabla `experiencia`
--
ALTER TABLE `experiencia`
ADD CONSTRAINT `experiencia_ibfk_1` FOREIGN KEY (`usuario_id`) REFERENCES `usuarios` (`id`);

--
-- Filtros para la tabla `folio`
--
ALTER TABLE `folio`
ADD CONSTRAINT `folio_ibfk_1` FOREIGN KEY (`usuario_id`) REFERENCES `usuarios` (`id`);

--
-- Filtros para la tabla `usuarios`
--
ALTER TABLE `usuarios`
ADD CONSTRAINT `usuarios_ibfk_1` FOREIGN KEY (`ciudad_id`) REFERENCES `ciudad` (`id`);

--
-- Filtros para la tabla `vacantes_usuarios`
--
ALTER TABLE `vacantes_usuarios`
ADD CONSTRAINT `vacantes_usuarios_ibfk_1` FOREIGN KEY (`usuarios_id`) REFERENCES `usuarios` (`id`),
ADD CONSTRAINT `vacantes_usuarios_ibfk_2` FOREIGN KEY (`vacantes_id`) REFERENCES `vacantes` (`id`);

/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;


text:
class AddRefundedBooleanToPaymentDetails < ActiveRecord::Migration
  class PaymentDetail < ActiveRecord::Base
    has_one :refund_detail
  end
  class RefundDetail < ActiveRecord::Base
    belongs_to :payment_detail
  end

  def up
    add_column :payment_details, :refunded, :boolean, default: false
    PaymentDetail.reset_column_information
    PaymentDetail.includes(:refund_detail).where.not(refund_details: {payment_detail_id: nil}).each do |pd|
      pd.update_attribute(:refunded, true)
    end
  end

  def down
    remove_column :payment_details, :refunded
  end
end


text:
package heap.list.merge;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.PriorityQueue;

public class Solution2
{
	/**
	 * Merges sorted lists of {@code Comparable} elements
	 *
	 *
This method performs an n-way sort over set of
	 * previously sorted lists. Useful in external sorting
	 *
	 * @param sortedLists collection of sorted lists
	 * @return sorted list that contains all lists' elements
	 *
	 * @time O(n · log(k))
	 * @space O(k)
	 *
 n - total number of elements
	 *
 k - number of sorted lists
	 **/
	public static <E extends Comparable<E>> List<E> mergeSortedLists(List<List<E>> sortedLists)
	{
		List<E> result = null;

		if (sortedLists != null)
		{
			result = new ArrayList<E>();
			PriorityQueue<ListEntry<E>> minHeap = new PriorityQueue<ListEntry<E>>(sortedLists.size());

			// each iterator points to the currently evaluated element in a sorted list
			List<Iterator<E>> iterators = new ArrayList<>(sortedLists.size());
			for (List<E> list : sortedLists)
			{
				iterators.add(list != null ? list.iterator() : new ArrayList<E>().iterator());
			}

			// fill heap with first elements of each list
			for (int i = 0; i < iterators.size(); i++)
			{
				if (iterators.get(i).hasNext())
				{
					ListEntry<E> entry = new ListEntry<E>(iterators.get(i).next(), i);
					minHeap.add(entry);
				}
			}

			// repeatedly extract the smallest element from the heap and append it to the result
			// if possible, replace missing heap element with a value from the same source list
			while (!minHeap.isEmpty())
			{
				ListEntry<E> entry = minHeap.poll();
				result.add(entry.value);

				if (iterators.get(entry.index).hasNext())
				{
					entry = new ListEntry<E>(iterators.get(entry.index).next(), entry.index);
					minHeap.add(entry);
				}
			}
		}

		return result;
	}

	/**
	 * Class for storing list value, and ID of
	 * the list that the value was taken from.
	 *
	 *

	 *
 <tt>value</tt> - the value taken from list
	 *
 <tt>index</tt> - the ID of the source list
	 *

	 **/
	private static class ListEntry<E extends Comparable<E>> implements Comparable<ListEntry<E>>
	{
		private E value;
		private int index;

		public ListEntry(E value, int index)
		{
			this.value = value;
			this.index = index;
		}

		@Override
		public int compareTo(ListEntry<E> that)
		{
			if (that == null)
			{
				return 1;
			}

			return this.value.compareTo(that.value);
		}

		@Override
		public String toString()
		{
			return "[" + value + " : " + index + "]";
		}
	}
}


text:
import shutil
from pathlib import Path

import pytest
from fontTools.designspaceLib import DesignSpaceDocument
from fontTools.designspaceLib.split import splitInterpolable, splitVariableFonts, convert5to4

from .fixtures import datadir

UPDATE_REFERENCE_OUT_FILES_INSTEAD_OF_TESTING = False

@pytest.mark.parametrize(
    "test_ds,expected_interpolable_spaces",
    [
        (
            "test_v5_aktiv.designspace",
            [
                (
                    {},
                    {
                        "AktivGroteskVF_Italics_Wght",
                        "AktivGroteskVF_Italics_WghtWdth",
                        "AktivGroteskVF_Wght",
                        "AktivGroteskVF_WghtWdth",
                        "AktivGroteskVF_WghtWdthItal",
                    },
                )
            ],
        ),
        (
            "test_v5_sourceserif.designspace",
            [
                (
                    {"italic": 0},
                    {"SourceSerif4Variable-Roman"},
                ),
                (
                    {"italic": 1},
                    {"SourceSerif4Variable-Italic"},
                ),
            ],
        ),
        (
            "test_v5_MutatorSans_and_Serif.designspace",
            [
                (
                    {"serif": 0},
                    {
                        "MutatorSansVariable_Weight_Width",
                        "MutatorSansVariable_Weight",
                        "MutatorSansVariable_Width",
                    },
                ),
                (
                    {"serif": 1},
                    {
                        "MutatorSerifVariable_Width",
                    },
                ),
            ],
        ),
    ],
)
def test_split(datadir, tmpdir, test_ds, expected_interpolable_spaces):
    data_in = datadir / test_ds
    temp_in = Path(tmpdir) / test_ds
    shutil.copy(data_in, temp_in)
    doc = DesignSpaceDocument.fromfile(temp_in)

    for i, (location, sub_doc) in enumerate(splitInterpolable(doc)):
        expected_location, expected_vf_names = expected_interpolable_spaces[i]
        assert location == expected_location
        vfs = list(splitVariableFonts(sub_doc))
        assert expected_vf_names == set(vf[0] for vf in vfs)

        loc_str = "_".join(f"{name}_{value}"for name, value in sorted(location.items()))
        data_out = datadir / "split_output" / f"{temp_in.stem}_{loc_str}.designspace"
        temp_out = Path(tmpdir) / "out" / f"{temp_in.stem}_{loc_str}.designspace"
        temp_out.parent.mkdir(exist_ok=True)
        sub_doc.write(temp_out)

        if UPDATE_REFERENCE_OUT_FILES_INSTEAD_OF_TESTING:
            data_out.write_text(temp_out.read_text(encoding="utf-8"), encoding="utf-8")
        else:
            assert data_out.read_text(encoding="utf-8") == temp_out.read_text(
                encoding="utf-8"
            )

        for vf_name, vf_doc in vfs:
            data_out = (datadir / "split_output" / vf_name).with_suffix(".designspace")
            temp_out = (Path(tmpdir) / "out" / vf_name).with_suffix(".designspace")
            temp_out.parent.mkdir(exist_ok=True)
            vf_doc.write(temp_out)

            if UPDATE_REFERENCE_OUT_FILES_INSTEAD_OF_TESTING:
                data_out.write_text(
                    temp_out.read_text(encoding="utf-8"), encoding="utf-8"
                )
            else:
                assert data_out.read_text(encoding="utf-8") == temp_out.read_text(
                    encoding="utf-8"
                )

@pytest.mark.parametrize(
    "test_ds,expected_vfs",
    [
        (
            "test_v5_aktiv.designspace",
            {
                "AktivGroteskVF_Italics_Wght",
                "AktivGroteskVF_Italics_WghtWdth",
                "AktivGroteskVF_Wght",
                "AktivGroteskVF_WghtWdth",
                "AktivGroteskVF_WghtWdthItal",
            },
        ),
        (
            "test_v5_sourceserif.designspace",
            {
                "SourceSerif4Variable-Italic",
                "SourceSerif4Variable-Roman",
            },
        ),
    ],
)
def test_convert5to4(datadir, tmpdir, test_ds, expected_vfs):
    data_in = datadir / test_ds
    temp_in = tmpdir / test_ds
    shutil.copy(data_in, temp_in)
    doc = DesignSpaceDocument.fromfile(temp_in)

    variable_fonts = convert5to4(doc)

    assert variable_fonts.keys() == expected_vfs
    for vf_name, vf in variable_fonts.items():
        data_out = (datadir / "convert5to4_output" / vf_name).with_suffix(".designspace")
        temp_out = (Path(tmpdir) / "out" / vf_name).with_suffix(".designspace")
        temp_out.parent.mkdir(exist_ok=True)
        vf.write(temp_out)

        if UPDATE_REFERENCE_OUT_FILES_INSTEAD_OF_TESTING:
            data_out.write_text(temp_out.read_text(encoding="utf-8"), encoding="utf-8")
        else:
            assert data_out.read_text(encoding="utf-8") == temp_out.read_text(
                encoding="utf-8"
            )


text:
layout: page
title: "Barbara Buttenfield"
comments: true
description: "blanks"
keywords: "Barbara Buttenfield,CU,Boulder"
---
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script src="https://dl.dropboxusercontent.com/s/pc42nxpaw1ea4o9/highcharts.js?dl=0"></script>
<!-- <script src="../assets/js/highcharts.js"></script> -->
<style type="text/css">@font-face {
	font-family: "Bebas Neue";
	src: url(https://www.filehosting.org/file/details/544349/BebasNeue Regular.otf) format("opentype");
	}
	h1.Bebas {
		font-family: "Bebas Neue", Verdana, Tahoma;
	}
</style>
</head>

#### TEACHING INFORMATION

**College**: College of Arts and Sciences

**Classes taught**: GEOG 3053, GEOG 4100, GEOG 4103, GEOG 4203

#### GEOG 3053: Cartography: Visualization and Information Design

**Terms taught**: Spring 2008, Fall 2008, Spring 2009, Fall 2009, Spring 2010, Spring 2012, Fall 2012, Fall 2015, Fall 2016

**Instructor rating**: 5.28

**Standard deviation in instructor rating**: 0.35

**Average grade** (4.0 scale): 2.86

**Standard deviation in grades** (4.0 scale): 0.15

**Average workload** (raw): 2.91

**Standard deviation in workload** (raw): 0.18

#### GEOG 4100: Special Topics in Geography

**Terms taught**: Spring 2016

**Instructor rating**: 5.64

**Standard deviation in instructor rating**: 0.0

**Average grade** (4.0 scale): 3.31

**Standard deviation in grades** (4.0 scale): 0.0

**Average workload** (raw): 2.67

**Standard deviation in workload** (raw): 0.0

#### GEOG 4103: Introduction to Geographic Information Science

**Terms taught**: Fall 2006, Spring 2008, Fall 2008, Spring 2010, Fall 2011, Spring 2014, Fall 2014, Spring 2016

**Instructor rating**: 5.42

**Standard deviation in instructor rating**: 0.37

**Average grade** (4.0 scale): 3.14

**Standard deviation in grades** (4.0 scale): 0.09

**Average workload** (raw): 3.11

**Standard deviation in workload** (raw): 0.34

#### GEOG 4203: Geographic Information Science: Modeling  Applications

**Terms taught**: Spring 2007, Spring 2009, Fall 2011, Fall 2012, Fall 2013, Fall 2014, Fall 2015, Fall 2016

**Instructor rating**: 5.46

**Standard deviation in instructor rating**: 0.19

**Average grade** (4.0 scale): 3.42

**Standard deviation in grades** (4.0 scale): 0.07

**Average workload** (raw): 3.42

**Standard deviation in workload** (raw): 0.36


text:
var  _ = require('underscore');  //note: requires underscore

(function (exports) {
    "use strict";

    function LinkedList() {
        // pointer to first item
        this._head = null;
        // pointer to the last item
        this._tail = null;
        // length of list
        this._length = 0;
    }

    LinkedList.prototype._createNewNode = function (data) {

       /* return {
            data: data,
            next: null,
            prev: null
        };
        */
        //if data.next/prev already exists, if so, data is already in some list - clone it
        if (data.hasOwnProperty("next") || data.hasOwnProperty("prev")){
            data = _.clone(data);
        }
        data.next = null;
        data.prev = null;

        return data;
};

    /*
     * Appends a node to the end of the list.
     */
    LinkedList.prototype.append = function (data) {
        var node = this._createNewNode(data);

        if (this._length === 0) {

            // first node, so all pointers to this
            this._head = node;
            this._tail = node;
        } else {

            // put on the tail
            this._tail.next = node;
            node.prev = this._tail;
            this._tail = node;
        }

        // update count
        this._length++;

        return node;
    };

    /*
     * Prepends a node to the end of the list.
     */
    LinkedList.prototype.prepend = function (data) {
        var node = this._createNewNode(data);

        if (this.head() === null) {

            // we are empty, so this is the first node
            // use the same logic as append
            this.append(data);
            return this.head();
        } else {

            // place before head
            this._head.prev = node;
            node.next = this._head;
            this._head = node;
        }

        // update count
        this._length++;

        return node;
    };

    /*
     * Returns the node at the specified index. The index starts at 0.
     */
    LinkedList.prototype.item = function (index) {
        if (index >= 0 && index < this._length) {
            var node = this._head;
            while (index--) {
                node = node.next;
            }
            return node;
        }
        return null;
    };

    /*
     * Returns the node at the head of the list.
     */
    LinkedList.prototype.head = function () {
        return this._head;
    };

    /*
     * Returns the node at the tail of the list.
     */
    LinkedList.prototype.tail = function () {
        return this._tail;
    };

    /*
     * Returns the size of the list.
     */
    LinkedList.prototype.size = function () {
        return this._length;
    };

    /*
     * Inserts node with data after the index
     */
    LinkedList.prototype.insertAt = function (index, data) {
        var node = this.item(index);
        //create new node with the data
        var newNode = this._createNewNode(data);

            //insert if empty
        if (node === null){
            this.append(newNode);
            return;
        }
        if (node.prev === null){
            node.prev = newNode;
            newNode.next = node;
            this._head = newNode;
            this._length++;
            return true;
        }
        node.prev.next = newNode;
        newNode.prev = node.prev;
        node.prev = newNode;
        newNode.next = node;
        this._length++;
        return true;
};

    /*
     * Removes the item at the index.
     */
    LinkedList.prototype.removeAt = function (index) {
        if (index >= 0 && index <= this._length) {
            var node = this.item(index - 1);
            //alter parent
            if (node.prev === null){
                node.next.prev = null;
                this._head = node.next;
                this._length--;
                return true;
            }
            if (node.next === null){
                node.prev.next = null;
                this._tail = node.prev;
                this._length--;
                return true;
            }
            node.prev.next = node.next;
            node.next.prev = node.prev;
            this._length--;
            return true;
        }
        return false;

    };

    /*
     * Removes the item with the data.
     */
    LinkedList.prototype.removeWithData = function (item) {
        var node = this.head;
        var index = 0;
        while (node !== null) {
            var data = node.data;
            if (node.data === item){
                //alter parent
                if (node.prev === null){
                    if (node.next === null){ //its the head
                        this._head = null;
                        this._tail = null;
                        this._length = 0;
                    } else {
                        node.next.prev = null;
                        this._head = node.next;
                    }
                    this._length--;
                    return true;
                }
                if (node.next === null){
                    node.prev.next = null;
                    this._tail = node.prev;
                    this._length--;
                    return true;
                }
                node.prev.next = node.next;
                node.next.prev = node.prev;
                this._length--;
                return true;
            }
            node = node.next;
        }
        return false;

    };

    /*
     * Removes the node. Uses ===
     */
    LinkedList.prototype.removeNode = function (otherNode) {
        var node = this.head;
        var index = 0;
        while (node.next !== null) {
            var data = node.data;
            if (node === otherNode){
                //alter parent
                if (node.prev === null){
                    node.next.prev = null;
                    this._head = node.next;
                    this._length--;
                    return true;
                }
                if (node.next === null){
                    node.prev.next = null;
                    this._tail = node.prev;
                    this._length--;
                    return true;
                }
                node.prev.next = node.next;
                node.next.prev = node.prev;
                this._length--;
                return true;
            }
            node = node.next;
        }
        return false;

    };

    LinkedList.prototype.removeHead = function (index) {
        return this.removeAt(0);
    };
    LinkedList.prototype.removeTail = function (index) {
        return this.removeAt(this.size());
    };

    LinkedList.prototype.each = function(fn /*, thisArg */){

        if (typeof fn !== "function")
            throw new TypeError();

        var thisArg = arguments.length >= 2 ? arguments[1] : void 0;
        var node = this._head;
        var idx = 0;
        while (node !== null)
        {
            fn.call(thisArg, node, idx);

            idx++;
            node = node.next;
        }
    };

    LinkedList.prototype.some = function(fn /*, thisArg */){

        if (typeof fn !== "function")
            throw new TypeError();

        var thisArg = arguments.length >= 2 ? arguments[1] : void 0;
        var node = this._head;
        var idx = 0;
        while (node !== null)
        {
            var res = fn.call(thisArg, node, idx++);
            if (res) return res;
            node = node.next;
        }
        return null;
    };

    //like some, but reversed
    LinkedList.prototype.somerev = function(fn /*, thisArg */){

        if (typeof fn !== "function")
            throw new TypeError();

        var thisArg = arguments.length >= 2 ? arguments[1] : void 0;
        var node = this._tail;
        var idx = 0;
        while (node !== null)
        {
            var res = fn.call(thisArg, node, idx++);
            if (res) return res;
            node = node.prev;
        }
        return null;
    };

    LinkedList.prototype.all = function(fn /*, thisArg */){

        if (typeof fn !== "function")
            throw new TypeError();

        var thisArg = arguments.length >= 2 ? arguments[1] : void 0;
        var node = this._head;
        while (node !== null)
        {
            var res = fn.call(thisArg, node);
            if (!res){
                return false;
            }
            node = node.next;
        }
        return true;
    };

    LinkedList.prototype.getAll = function(){
        var result = [];
        var node = this._head;
        while (node !== null){
            result.push(_.clone(node));
            node = node.next;
        }
        return result;
    };

    //desctructively adds this otherList to this list
    LinkedList.prototype.merge = function(otherList){
        var clonedOtherlist = _.clone(otherList);

        if (otherList.size() === 0){
            return this;
        }

        if (this._length === 0) {
            this._head = clonedOtherlist.head();
            this._tail = clonedOtherlist.tail();
        } else {

            // put on the tail
            this._tail.next = clonedOtherlist.head();
            clonedOtherlist.head().prev = this._tail;
            this._tail = clonedOtherlist.tail();
        }

        // update count
        this._length = this._length + clonedOtherlist.size();

        return this;
    };

    //case study then code
    //write an app that drives it

    exports.LinkedList = LinkedList;
})(exports);


text:
package net.fortuna.ical4j.vcard.property;

import java.net.URISyntaxException;
import java.text.ParseException;
import java.util.List;

import net.fortuna.ical4j.model.TextList;
import net.fortuna.ical4j.model.ValidationException;
import net.fortuna.ical4j.vcard.Group;
import net.fortuna.ical4j.vcard.Parameter;
import net.fortuna.ical4j.vcard.Property;
import net.fortuna.ical4j.vcard.PropertyFactory;

/**
 * CATEGORIES property.
 *
 * $Id$
 *
 * Created on 21/10/2008
 *
 * @author Ben
 *
 */
public final class Categories extends Property {

    public static final PropertyFactory<Categories> FACTORY = new Factory();

    private static final long serialVersionUID = -3233034210546002366L;

    private final TextList categories;

    /**
     * @param categories one or more category values
     */
    public Categories(String...categories) {
        super(Id.CATEGORIES);
        if (categories.length == 0) {
            throw new IllegalArgumentException("Must specify at least category value");
        }
        this.categories = new TextList(categories);
    }

    /**
     * Factory constructor.
     * @param params property parameters
     * @param value string representation of a property value
     */
    public Categories(List<Parameter> params, String value) {
        super(Id.CATEGORIES);
        this.categories = new TextList(value);
    }

    /**
     * @return the categories
     */
    public TextList getCategories() {
        return categories;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String getValue() {
        /*
        StringBuilder b = new StringBuilder();
        for (int i = 0; i < categories.length; i++) {
            b.append(categories[i]);
            if (i < categories.length - 1) {
                b.append(',');
            }
        }
        return b.toString();
        */
        return categories.toString();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void validate() throws ValidationException {
        // ; Text parameters allowed
        for (Parameter param : getParameters()) {
            try {
                assertTextParameter(param);
            }
            catch (ValidationException ve) {
                assertPidParameter(param);
            }
        }
    }

    private static class Factory implements PropertyFactory<Categories> {

        /**
         * {@inheritDoc}
         */
        public Categories createProperty(final List<Parameter> params, final String value) {
            return new Categories(params, value);
        }

        /**
         * {@inheritDoc}
         */
        public Categories createProperty(final Group group, final List<Parameter> params, final String value)
                throws URISyntaxException, ParseException {
            // TODO Auto-generated method stub
            return null;
        }
    }
}


text:
package io.github.jonestimd.finance.file;

import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import java.util.Set;
import java.util.stream.Stream;

import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ListMultimap;
import io.github.jonestimd.finance.domain.fileimport.ImportField;
import io.github.jonestimd.finance.domain.fileimport.ImportFieldBuilder;
import org.junit.Test;

import static java.util.Collections.*;
import static org.assertj.core.api.Assertions.*;

public class ImportFieldMapperTest {
    private final ImportField payeeField = new ImportFieldBuilder().label("Payee").get();
    private final Set<ImportField> fields = Collections.singleton(payeeField);

    private final ImportFieldMapper mapper = new ImportFieldMapper(fields);

    @Test
    public void extractsMappedField() throws Exception {
        Iterable<ListMultimap<ImportField, String>> records = mapper.mapFields(Stream.of(ImmutableMap.of("Payee", "some payee")));

        assertThat(records).hasSize(1);
        Map<ImportField, Collection<String>> record = records.iterator().next().asMap();
        assertThat(record.keySet()).containsExactly(payeeField);
        assertThat(record.get(payeeField)).containsExactly("some payee");
    }

    @Test
    public void ignoresUnmappedFields() throws Exception {
        Iterable<ListMultimap<ImportField, String>> records = mapper.mapFields(Stream.of(ImmutableMap.of("Dummy", "xxx")));

        assertThat(records).hasSize(1);
        assertThat(records.iterator().next().asMap()).isEqualTo(singletonMap(payeeField, singletonList("")));
    }
}