<commit_before><big><h1 align="center">mcp</h1></big>

<p align="center">
  <a href="https://npmjs.org/package/mcp">
    <img src="https://img.shields.io/npm/v/mcp.svg?style=flat-square"
         alt="NPM Version">
  </a>

  <a href="https://coveralls.io/r/bingomanatee/mcp">
    <img src="https://img.shields.io/coveralls/bingomanatee/mcp.svg?style=flat-square"
         alt="Coverage Status">
  </a>

  <a href="https://travis-ci.org/bingomanatee/mcp">
    <img src="https://img.shields.io/travis/bingomanatee/mcp.svg?style=flat-square"
         alt="Build Status">
  </a>

  <a href="https://npmjs.org/package/mcp">
    <img src="http://img.shields.io/npm/dm/mcp.svg?style=flat-square"
         alt="Downloads">
  </a>

  <a href="https://david-dm.org/bingomanatee/mcp.svg">
    <img src="https://david-dm.org/bingomanatee/mcp.svg?style=flat-square"
         alt="Dependency Status">
  </a>

  <a href="https://github.com/bingomanatee/mcp/blob/master/LICENSE">
    <img src="https://img.shields.io/npm/l/mcp.svg?style=flat-square"
         alt="License">
  </a>
</p>

<p align="center"><big>
a flow control system for JS/Node.js
</big></p>


## Install

```sh
npm i -D mcp
```

## Usage

```js
import {MCP} from "mcp"

let chessPieceState = new MCP("inbox");

chessPieceState.mcpFromState("inbox").mcpChangeState("onboard");
chessPieceState.mcpFromState("onboard")

```

## License

MIT © [dedelhar](http://www.wonderlandlabs.com)

[npm-url]: https://npmjs.org/package/mcp
[npm-image]: https://img.shields.io/npm/v/mcp.svg?style=flat-square

[travis-url]: https://travis-ci.org/bingomanatee/mcp
[travis-image]: https://img.shields.io/travis/bingomanatee/mcp.svg?style=flat-square

[coveralls-url]: https://coveralls.io/r/bingomanatee/mcp
[coveralls-image]: https://img.shields.io/coveralls/bingomanatee/mcp.svg?style=flat-square
<commit_msg>expanded example in readme<commit_after><big><h1 align="center">mcp</h1></big>

<p align="center">
  <a href="https://npmjs.org/package/mcp">
    <img src="https://img.shields.io/npm/v/mcp.svg?style=flat-square"
         alt="NPM Version">
  </a>

  <a href="https://coveralls.io/r/bingomanatee/mcp">
    <img src="https://img.shields.io/coveralls/bingomanatee/mcp.svg?style=flat-square"
         alt="Coverage Status">
  </a>

  <a href="https://travis-ci.org/bingomanatee/mcp">
    <img src="https://img.shields.io/travis/bingomanatee/mcp.svg?style=flat-square"
         alt="Build Status">
  </a>

  <a href="https://npmjs.org/package/mcp">
    <img src="http://img.shields.io/npm/dm/mcp.svg?style=flat-square"
         alt="Downloads">
  </a>

  <a href="https://david-dm.org/bingomanatee/mcp.svg">
    <img src="https://david-dm.org/bingomanatee/mcp.svg?style=flat-square"
         alt="Dependency Status">
  </a>

  <a href="https://github.com/bingomanatee/mcp/blob/master/LICENSE">
    <img src="https://img.shields.io/npm/l/mcp.svg?style=flat-square"
         alt="License">
  </a>
</p>

<p align="center"><big>
a flow control system for JS/Node.js
</big></p>


## Install

```sh
npm i -D mcp
```

## Usage

```js
import {MCP} from "mcp"

let chessPieceState = new MCP("inbox");

chessPieceState.mcpFromState("inbox").mcpChangeState("onboard");
chessPieceState.mcpFromState("onboard")

```

Why MCP?

State machines are a part of a larger family of domain management. Observing state change is a very nuanced business 
and the standard eventEmitter filters are not up to the task of the kind of variations that state observations provide.

while complex listener logic can handle a lot, there's no reason why the common patterns of state observations can't be
inserted into the logic of the state machine itself. 

### Use case: the rat and the radio. 

Scientists want to find out of rats like country western music or rock and roll. They set up a radio to change randomly
between songs from a collection of country music and rock. (Both provided by k-tel of course.) 

The songs last an average of four minutes. The rat is given a lever that when he hits the lever, will advance to the 
next song. The next selection is random -- the rat is not guaranteed that he won't advance from counry to country
or from rock to rock, but of course there is a 50/50 chance that he will change themes and songs (and a 100% chance
that he will not have to listen to whatever he is listening to. 

The state machine looks like this: 

``` javsacript
import {MCP} from 'mcp';

const radio = new MCP();
var ratAdvancesCountry = 0;
var ratAdvancesRock = 0;

radio.mcpWhen('leverhit').mcpStateIs('nextsong')
  .mcpWhen('choosecountry').mcpStateIs('countryplaying')
  .mcpWhen('chooserock').mcpStateIs('rockplaying')
  .mcpWhen('songOver').mcpStateIs('nextSong')
  
  .mcpWatchState('nextsong', () => {
  	if (Math.random() > 0.5) mcp.chooseeCountry()
  	else mcp.chooseRock();
  })
  .mcpWatchAction('leverHit', () => {
  	if (mcp.mcpState === 'countryplaying') {
  	++ ratAdvancesCountry;
  	} else if (mcp.mcpState === 'rockPlaying') {
  	++ ratAdvancesRock;
  	}
  }) 
```

this example shows both the utility of watching actions (the rat hitting the lever, which is data, 
whereas the song just running out is not useful to the study*) and states (a song change, which
triggers a random song selection) 

Even more specific watchers can be used instead of the last watcher:

``` javascript
radio.mcpWatch({action: 'leverHit', fromState: 'countryplaying'} () => ++ ratAdvancesCountry)
     .mcpWatch({action: 'leverHit', fromState: 'rockPlaying'}    () => ++ ratAdvancesRodck);
```

This very compressed use of the event system shows how nuanced use of the event watchers can express
a very rich vocabulary of observational technique. 

*although it might be useful in combination with the state 
-- a rat letting a country song run its course indicates that the rat likes country, 
similarly with rock, but the lever data is kind of redundant with this information.

## License

MIT © [Wonderland Labs](http://www.wonderlandlabs.com)

[npm-url]: https://npmjs.org/package/mcp
[npm-image]: https://img.shields.io/npm/v/mcp.svg?style=flat-square

[travis-url]: https://travis-ci.org/bingomanatee/mcp
[travis-image]: https://img.shields.io/travis/bingomanatee/mcp.svg?style=flat-square

[coveralls-url]: https://coveralls.io/r/bingomanatee/mcp
[coveralls-image]: https://img.shields.io/coveralls/bingomanatee/mcp.svg?style=flat-square

{'fraction_non_alphanumeric': 0.15382200596452678, 'fraction_numerical': 0.0023544184586407157, 'mean_word_length': 4.0212765957446805, 'pattern_counts': {'":': 0, '<': 59, '<?xml version=': 0, '>': 64, 'https://': 34, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2027571', 'n_tokens_mistral': 2331, 'n_tokens_neox': 2217, 'n_words': 547}