Skip to content
This repository has been archived by the owner on Sep 13, 2019. It is now read-only.

Commit

Permalink
Merge pull request #20 from Floofies/master
Browse files Browse the repository at this point in the history
Added map, added strategy exporter, finished contributing doc
  • Loading branch information
Floofies authored Sep 4, 2017
2 parents 70bd5d4 + 0a5b45e commit a076247
Show file tree
Hide file tree
Showing 4 changed files with 1,017 additions and 814 deletions.
123 changes: 116 additions & 7 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -1,20 +1,129 @@
# :pencil2: Contributing
## Pre-requisites
Contributing to the project is very easy. Additions to the library are handled via a standard Strategy Pattern. Unit testing is handled with `jasmine`.

# Testing & Building
### Pre-requisites
- `node`
- `make`

### Testing
## Testing
> The makefile installs a local copy of `jasmine` to run tests.
**Node Tests**: `make test`

**Browser Tests**: Open `SpecRunner.html` in a web browser.

### Building
## Production Build
> The makefile installs a local copy of `uglify-es` for beautification/minification.
**Production Build**: `make prod`
Saves comment-less and minified versions of `src/differentia.js` into a `prod-build` directory.
**Production Build**: `make prod` or `make prod clean`

Creates a `prod-build` directory to build the production release into. Saves `src/differentia.js` into `prod-build/src`, then comment-less and minified versions into `prod-build/lib`. Also includes `package.json`, `README.md`, and `spec` in the root directory.

Add `clean` at the end to remove `node_modules`.

# Adding Algorithms
To add an algorithm to the library, you must use the Strategy Pattern together with `runStrategy`, which is the primary gateway for your algorithms to interact with and use the `iddfs` iterator. Your algorithm will be tightly coupled to the the `iddfs` iterator, and you should make use of one of the many properties made available through it's `state` object. An algorithm may "steer" the search algorithm by directly mutating certain properties of `state`. See documentation for `iddfs` in `README.md` for more information.

All strategies added to the `strategies` object will be automatically revealed to the end-user via their `interface` properties. Once you add a strategy, you should also include it's name in `spec/Spec.js` in the first unit test, as part of the `modules` array; the test will verify that your strategy is accessible.

You should also write a unit test for your algorithm at the bottom of the file, using `describe`, `it`, and `expect` in nested order. There is a generic `diff` function available specifically for unit tests, in case you need to check one object against another. (Do not use the `diff` function provided by `differentia`, or any other function in the module, to do this verification).

Here is a basic example of a `jasmine` unit test:

```JavaScript
describe("two plus two", function () {
it("should equal four", function () {
expect(2+2).toBe(4);
});
});
```

## Creating a Strategy Object
A Strategy is an object with the following properties:

Property|Data Type|Description
---|---|---
`interface`|Function|The interface function revealed by `module.exports` and the global `differentia` namespace, to be exposed to and directly run by the end-user. The function must contain a call to `runStrategy`, supplying it's parent object as the first parameter.
`entry`|Function|(*Optional*) A Call-With-Current-State callback to run with the first iterator state, only once. This function cannot return values.
`main`|Function|A Call-With-Current-State callback to run on every iteraton. If this function returns something other than `undefined`, it will be returned to the user's caller.

`entry` and `main` recieve a single `state` argument, the iterator state flyweight Object, which is a single object the iterator actively mutates per-iteration. See documentation for `iddfs` in `README.md` for more information.

---

Your Strategy's `interface` function must call `runStrategy` to use the `iddfs` iterator:

### `runStrategy`

*Function*
```JavaScript
runStrategy( strategy, parameters );
```
An IOC wrapper to the `iddfs` iterator. (See documentation for `iddfs` in `README.md` for more information.). `runStrategy` advances the `iddfs` iterator and executes Call-With-Current-State callbacks supplied in `strategy`. The state flyweight object is passed to `strategy.main`, which is executed for each element, and `strategy.entry`, which is only executed for the first element. If `strategy.main` returns something other than `undefined`, it will be returned to the caller.

#### Parameters
- **`strategy`** Object

The strategy Object.

- **`parameters`** Object

Avaiable to callbacks via `state.parameters`. It consists of the following properties, but may contain any number of custom properties:

Property|Data Type|Description
---|---|---
`subject`|Object/Array|The Object or Array to traverse/iterate.
`search`|Object/Array|(*Optional*) A search index specifying the paths to traverse, and property accessors to enumerate. All other properties are ignored.

---

## Example Strategy

This example is an algorithm that overwrites every Primitive of an Object tree with "Hello World".

```JavaScript
// Our test Object
var subject = {
greetings1: [
"Good Afternoon"
],
greetings2: [
"Good Morning"
]
};

// Define your Strategy, adding it to the "strategies" object. "main" and "interface" properties are required.
strategies.myStrategy = {
interface: function (object) {
// Here we call "runStrategy" and include our Strategy as parameter 1
runStrategy(strategies.myStrategy, {
subject: object
});
},
main: function (state) {
// This function will be executed for every iteration
// Only overwrite what is not an Object/Array
if (!state.isContainer) {
// This assignment is equal to 'object.greetingsN[0] = "Hello World"'
state.tuple.subject[state.accessor] = "Hello World";
}
}
};

// Runs the Strategy. This function is exposed to the end-user.
strategies.myStrategy.interface(subject);

### Clean Build/Test
Add `clean` at the end to remove `node_modules` afterwards.
// We can now see the Primitives were overwritten with "Hello World".
console.log(subject);
/*
"{
greetings1: [
"Hello World"
],
greetings2: [
"Hello World"
]
}"
*/
```
Loading

0 comments on commit a076247

Please sign in to comment.