text:
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">

    <modelVersion>4.0.0</modelVersion>

	<parent>
        <groupId>com.amee.platform</groupId>
        <artifactId>amee-platform</artifactId>
        <version>3.12.0-SNAPSHOT</version>
    </parent>

	<artifactId>amee-platform-base</artifactId>
	<packaging>jar</packaging>

	<name>AMEE :: Base</name>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
            </plugin>

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
            </plugin>

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-report-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

	<!-- Dependencies. -->
	<dependencies>

		<!-- Compile Dependencies. -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context-support</artifactId>
			<version>${spring.version}</version>
			<exclusions>
				<exclusion>
					<groupId>commons-logging</groupId>
					<artifactId>commons-logging</artifactId>
				</exclusion>
			</exclusions>
		</dependency>
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>jcl-over-slf4j</artifactId>
			<version>${slf4j.version}</version>
			<scope>runtime</scope>
		</dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>${slf4j.version}</version>
        </dependency>
		<dependency>
			<groupId>commons-codec</groupId>
			<artifactId>commons-codec</artifactId>
			<version>${commons-codec.version}</version>
		</dependency>
		<dependency>
			<groupId>org.apache.commons</groupId>
			<artifactId>commons-lang3</artifactId>
			<version>${commons-lang.version}</version>
		</dependency>
		<dependency>
			<groupId>commons-io</groupId>
			<artifactId>commons-io</artifactId>
			<version>${commons-io.version}</version>
		</dependency>
		<dependency>
			<groupId>javax.mail</groupId>
			<artifactId>mail</artifactId>
			<version>${javax.mail.version}</version>
		</dependency>
		<dependency>
			<groupId>net.sf.ehcache</groupId>
			<artifactId>ehcache-core</artifactId>
			<version>${ehcache.version}</version>
		</dependency>
		<dependency>
			<groupId>net.spy</groupId>
			<artifactId>spymemcached</artifactId>
			<version>${spymemcached.version}</version>
		</dependency>
		<dependency>
			<groupId>org.json</groupId>
			<artifactId>json</artifactId>
			<version>${org.json.version}</version>
		</dependency>
		<dependency>
			<groupId>org.jdom</groupId>
			<artifactId>jdom2</artifactId>
			<version>${org.jdom2.version}</version>
		</dependency>
		<dependency>
			<groupId>commons-cli</groupId>
			<artifactId>commons-cli</artifactId>
			<version>${commons-cli.version}</version>
		</dependency>
		<dependency>
			<groupId>joda-time</groupId>
			<artifactId>joda-time</artifactId>
			<version>${joda-time.version}</version>
		</dependency>
		<dependency>
			<groupId>org.aspectj</groupId>
			<artifactId>aspectjrt</artifactId>
			<version>${org-aspectj.version}</version>
		</dependency>
		<dependency>
			<groupId>org.restlet</groupId>
			<artifactId>org.restlet</artifactId>
			<version>${restlet.version}</version>
		</dependency>

		<!-- Test Dependencies. -->
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>${junit.version}</version>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>org.mockito</groupId>
			<artifactId>mockito-all</artifactId>
			<version>${org-mockito.version}</version>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-test</artifactId>
			<version>${spring.version}</version>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>org.aspectj</groupId>
			<artifactId>aspectjweaver</artifactId>
			<version>${org-aspectj.version}</version>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>ch.qos.logback</groupId>
			<artifactId>logback-classic</artifactId>
			<version>${logback.version}</version>
			<scope>test</scope>
			<!-- http://stackoverflow.com/a/9093936 -->
		</dependency>
    </dependencies>
</project>


text:
@interface ObjSqliteDBTest : SenTestCase {

}

@end

redpajama_set_name: RedPajamaGithub


text:
// Type definitions for automapper-ts
// Project: https://github.com/loedeman/AutoMapper
// Definitions by: Bert Loedeman <https://github.com/loedeman>
// Definitions: https://github.com/borisyankov/DefinitelyTyped

declare module AutoMapperJs {
    /**
     * AutoMapper implementation, for both creating maps and performing maps. Comparable usage and functionality to the original
     * .NET AutoMapper library is the pursuit of this implementation.
     */
    class AutoMapper {
        /**
         * Initializes the mapper with the supplied configuration.
         * @param {(config: IConfiguration) => void} Configuration function to call.
         */
        initialize(configFunction: (config: IConfiguration) => void): void;

        /**
         * Create a createMap curry function which expects only a destination key.
         * @param {string} sourceKey The map source key.
         * @returns {(destinationKey: string) => ICreateMapFluentFunctions}
         */
        createMap(sourceKey: string | (new() => any)): (destinationKey: string | (new() => any)) => ICreateMapFluentFunctions;

        /**
         * Create a mapping profile.
         * @param {string} sourceKey The map source key.
         * @param {string} destinationKey The map destination key.
         * @returns {Core.ICreateMapFluentFunctions}
         */
        createMap(sourceKey: string | (new() => any), destinationKey: string | (new() => any)): ICreateMapFluentFunctions;

        /**
         * Create a map curry function which expects a destination key and a source object.
         * @param sourceKey Source key, for instance the source type name.
         * @returns {(destinationKey: string, sourceObject: any) => any}
         */
        map(sourceKey: string | (new() => any)): (destinationKey: string | (new() => any), sourceObject: any) => any;

        /**
         * Create a map curry function which expects only a source object.
         * @param sourceKey Source key, for instance the source type name.
         * @param destinationKey Destination key, for instance the destination type name.
         * @returns {(sourceObject: any) => any}
         */
        map(sourceKey: string | (new() => any), destinationKey: string | (new() => any)): (sourceObject: any) => any;

        /**
         * Execute a mapping from the source object to a new destination object with explicit mapping configuration and supplied mapping options (using createMap).
         * @param sourceKey Source key, for instance the source type name.
         * @param destinationKey Destination key, for instance the destination type name.
         * @param sourceObject The source object to map.
         * @returns {any} Destination object.
         */
        map(sourceKey: string | (new() => any), destinationKey: string | (new() => any), sourceObject: any): any;

        /**
         * Create a mapAsync curry function which expects a destination key, a source object and a callback function.
         * @param sourceKey Source key, for instance the source type name.
         * @returns {(destinationKey: string, sourceObject: any, callback: IMapCallback) => void}
         */
        mapAsync(sourceKey: string | (new() => any)): (destinationKey: string | (new() => any), sourceObject: any, callback: IMapCallback) => void;

        /**
         * Create a map curry function which expects only a source object and a callback function.
         * @param sourceKey Source key, for instance the source type name.
         * @param destinationKey Destination key, for instance the destination type name.
         * @param sourceObject The source object to map.
         * @returns {(callback: IMapCallback) => void}
         */
        mapAsync(sourceKey: string | (new() => any), destinationKey: string | (new() => any), sourceObject: any): (callback: IMapCallback) => void;

        /**
         * Create a map curry function which expects only a source object and a callback function.
         * @param sourceKey Source key, for instance the source type name.
         * @param destinationKey Destination key, for instance the destination type name.
         * @returns {(sourceObject: any, callback: IMapCallback) => void}
         */
        mapAsync(sourceKey: string | (new() => any), destinationKey: string | (new() => any)): (sourceObject: any, callback: IMapCallback) => void;

        /**
         * Execute an asynchronous mapping from the source object to a new destination object with explicit mapping configuration and supplied mapping options (using createMap).
         * @param sourceKey Source key, for instance the source type name.
         * @param destinationKey Destination key, for instance the destination type name.
         * @param sourceObject The source object to map.
         * @param {IMapCallback} callback The callback to call when asynchronous mapping is complete.
         */
        mapAsync(sourceKey: string | (new() => any), destinationKey: string | (new() => any), sourceObject: any, callback: IMapCallback): void;

        /**
         * Validates mapping configuration by dry-running. Since JS does not
         * fully support typing, it only checks if properties match on both
         * sides. The function needs IMapping.sourceTypeClass and
         * IMapping.destinationTypeClass to function.
         * @param {boolean} strictMode Whether or not to fail when properties
         *                             sourceTypeClass or destinationTypeClass
         *                             are unavailable.
         */
        assertConfigurationIsValid(strictMode?: boolean): void;
    }

    class AsyncAutoMapper {
        /* For Test Purposes Only */
    }

    /**
     * Converts source type to destination type instead of normal member mapping
     */
    class TypeConverter implements ITypeConverter {
        /**
         * Performs conversion from source to destination type.
         * @param {IResolutionContext} resolutionContext Resolution context.
         * @returns {any} Destination object.
         */
        convert(resolutionContext: IResolutionContext): any;
    }

    export class Profile implements IProfile {
        /** Profile name */
        public profileName: string;

        /** Naming convention for source members */
        public sourceMemberNamingConvention: INamingConvention;

        /** Naming convention for destination members */
        public destinationMemberNamingConvention: INamingConvention;

        /**
         * Create a createMap curry function which expects only a destination key.
         * @param {string} sourceKey The map source key.
         * @returns {(destinationKey: string) => ICreateMapFluentFunctions}
         */
        protected createMap(sourceKey: string): (destinationKey: string) => ICreateMapFluentFunctions;

        /**
         * Create a mapping profile.
         * @param {string} sourceKey The map source key.
         * @param {string} destinationKey The map destination key.
         * @returns {Core.ICreateMapFluentFunctions}
         */
        protected createMap(sourceKey: string, destinationKey: string): ICreateMapFluentFunctions;

        /**
         * Implement this method in a derived class and call the CreateMap method to associate that map with this profile.
         * Avoid calling the AutoMapper class / automapper instance from this method.
         */
        public configure(): void;
    }

    /**
     * Defines the PascalCase naming convention strategy.
     */
    class PascalCaseNamingConvention implements INamingConvention {
        /** Regular expression on how to tokenize a member. */
        splittingExpression: RegExp;

        /** Character to separate on. */
        separatorCharacter: string;

        /**
         * Transformation function called when this convention is the destination naming convention.
         * @param {string[]} sourcePropertyNameParts Array containing tokenized source property name parts.
         * @returns {string} Destination property name
         */
        transformPropertyName(sourcePropertyNameParts: string[]): string;
    }

    /**
     * Defines the camelCase naming convention strategy.
     */
    class CamelCaseNamingConvention implements INamingConvention {
        /** Regular expression on how to tokenize a member. */
        splittingExpression: RegExp;

        /** Character to separate on. */
        separatorCharacter: string;

        /**
         * Transformation function called when this convention is the destination naming convention.
         * @param {string[]} sourcePropertyNameParts Array containing tokenized source property name parts.
         * @returns {string} Destination property name
         */
        transformPropertyName(sourcePropertyNameParts: string[]): string;
    }

    interface IProperty {
        name: string;
        metadata: IPropertyMetadata;
        level: number;
        sourceMapping: boolean;
        ignore: boolean;
        async: boolean;
        children?: IProperty[];
        destinations?: IProperty[];
        conversionValuesAndFunctions: any[];
        conditionFunction?: (sourceObject: any) => boolean;
    }

    interface IPropertyMetadata {
        mapping: IMapping;
        root: IProperty;
        parent: IProperty;
        destinations: {[name: string]: IPropertyDestinationMetadata};
        destinationCount: number;
    }

    interface IPropertyDestinationMetadata {
        source: IProperty;
        destination: IProperty;
    }

    interface IMemberMappingMetaData {
        destination: string;
        source: string;
        sourceMapping: boolean;
        ignore: boolean;
        async: boolean;
        condition: (sourceObject: any) => boolean;
    }

    /**
     * Member mapping properties.
     */
    interface IForMemberMapping {
        /** The source member property name. */
        sourceProperty: string;
        /** The destination member property name parts for nested property support (e.g. 'type.name'). */
        destinationProperty: string;
        /** Source or destination mapping. */
        sourceMapping: boolean;
        /** All mapping values and/or functions resulting from stacked for(Source)Member calls. */
        mappingValuesAndFunctions: Array<any>;
        /** Whether or not this destination property must be ignored. */
        ignore: boolean;
        /** Whether or not this member mapping has an asynchronous mapping function. */
        async: boolean;
        /**
         * The object will only be mapped when the condition is met.
         * @param {any} sourceObject The source object to check.
         * @returns {boolean}
         */
        conditionFunction: (sourceObject: any) => boolean;
    }

    /**
     * Interface for returning an object with available 'sub' functions to enable method chaining (e.g. automapper.createMap().forMember().forMember() ...)
     */
    interface ICreateMapFluentFunctions {
        /**
         * Customize configuration for an individual destination member.
         * @param sourceProperty The destination member property name.
         * @param valueOrFunction The value or function to use for this individual member.
         * @returns {IAutoMapperCreateMapChainingFunctions}
         */
        forMember: (sourceProperty: string, valueOrFunction: any |
                     ((opts: IMemberConfigurationOptions) => any) |
                     ((opts: IMemberConfigurationOptions, cb: IMemberCallback) => void)) => ICreateMapFluentFunctions;

        /**
         * Customize configuration for an individual source member.
         * @param sourceProperty The source member property name.
         * @param sourceMemberConfigFunction The function to use for this individual member.
         * @returns {IAutoMapperCreateMapChainingFunctions}
         */
        forSourceMember: (sourceProperty: string,
                          sourceMemberConfigFunction: ((opts: ISourceMemberConfigurationOptions) => any) |
                                                      ((opts: ISourceMemberConfigurationOptions, cb: IMemberCallback) => void)
                         ) => ICreateMapFluentFunctions;

        /**
         * Customize configuration for all destination members.
         * @param func The function to use for this individual member.
         * @returns {IAutoMapperCreateMapChainingFunctions}
         */
        forAllMembers: (func: (destinationObject: any, destinationPropertyName: string, value: any) => void) => ICreateMapFluentFunctions;

        /**
         * Ignore all members not specified explicitly.
         */
        ignoreAllNonExisting: () => ICreateMapFluentFunctions;

        /**
         * Skip normal member mapping and convert using a custom type converter (instantiated during mapping).
         * @param typeConverterClassOrFunction The converter class or function to use when converting.
         */
        convertUsing: (typeConverterClassOrFunction: ((resolutionContext: IResolutionContext) => any) |
                                                     ((resolutionContext: IResolutionContext, callback: IMapCallback) => void) |
                                                     ITypeConverter |
                                                     (new() => ITypeConverter)
                      ) => void;

        /**
         * Specify to which class type AutoMapper should convert. When specified, AutoMapper will create an instance of the given type, instead of returning a new object literal.
         * @param typeClass The destination type class.
         * @returns {IAutoMapperCreateMapChainingFunctions}
         */
        convertToType: (typeClass: new () => any) => ICreateMapFluentFunctions;

        /**
         * Specify which profile should be used when mapping.
         * @param {string} profileName The profile name.
         * @returns {IAutoMapperCreateMapChainingFunctions}
         */
        withProfile: (profileName: string) => void;
    }

    /**
     * The mapping configuration for the current mapping keys/types.
     */
    interface IMapping {
        /** The mapping source key. */
        sourceKey: string;

        /** The mapping destination key. */
        destinationKey: string;

        /** The mappings for forAllMembers functions. */
        forAllMemberMappings: Array<(destinationObject: any, destinationPropertyName: string, value: any) => void>;

        properties: IProperty[];

        /**
         * Skip normal member mapping and convert using a type converter.
         * @param resolutionContext Context information regarding resolution of a destination value
         * @returns {any} Destination object.
         */
        typeConverterFunction: ((resolutionContext: IResolutionContext) => any) |
                               ((resolutionContext: IResolutionContext, callback: IMapCallback) => void);

        /** The source type class to convert from. */
        sourceTypeClass: any;

        /** The destination type class to convert to. */
        destinationTypeClass: any;

        /** The profile used when mapping. */
        profile?: IProfile;

        /** Whether or not to ignore all properties not specified using createMap. */
        ignoreAllNonExisting?: boolean;

        /** Whether or not an mapping has to be asynchronous. */
        async: boolean;

        /*
         * PERFORMANCE ENHANCEMENTS
         */

        /**
         * Item mapping function to use.
         */
        mapItemFunction: IMapItemFunction | IAsyncMapItemFunction;
    }

    // export interface IMappingMapOptimized extends IMapping {
    //     final: boolean;
    //     forMemberMappingsArray: Array<IForMemberMapping>;
    // }

    /**
     * Context information regarding resolution of a destination value
     */
    export interface IResolutionContext {
        /** Source value */
        sourceValue: any;

        /** Destination value */
        destinationValue: any;

        /** Source property name */
        sourcePropertyName?: string;

        /** Destination property name */
        destinationPropertyName?: string;

        /** Index of current collection mapping */
        arrayIndex?: number;
    }

    /**
     * Configuration options for forMember mapping function.
     */
    interface IMemberConfigurationOptions {
        /**
         * Map from a custom source property name.
         * @param sourcePropertyName The source property to map.
         */
        mapFrom: (sourcePropertyName: string) => void;

        /**
         * When this configuration function is used, the (destination) property is ignored
         * when mapping.
         */
        ignore?: () => void;

        /**
         * If specified, the property will only be mapped when the condition is fulfilled.
         */
        condition: (predicate: ((sourceObject: any) => boolean)) => void;

        /** The source object to map. */
        sourceObject: any;

        /** The source property to map. */
        sourcePropertyName: string;

        /**
         * The intermediate destination property value, used for stacking multiple for(Source)Member calls
         * while elaborating the intermediate result.
         */
        intermediatePropertyValue: any;
    }

    /**
     * Configuration options for forSourceMember mapping function.
     */
    interface ISourceMemberConfigurationOptions {
        /**
         * When this configuration function is used, the source property is ignored
         * when mapping.
         */
        ignore: () => void;
    }

    /**
     * Member callback interface
     */
    interface IMemberCallback {
        /**
         * Callback function to call when the async operation is executed.
         * @param {any} callbackValue Callback value to be used as output for the for(Source)Member call.
         */
        (callbackValue: any): void;
    }

    /**
     * Member callback interface
     */
    interface IMapCallback {
        /**
         * Callback function to call when the async operation is executed.
         * @param {any} result Callback value to be used as output for the mapAsync call.
         */
        (result: any): void;
    }

    /**
     * Converts source type to destination type instead of normal member mapping
     */
    export interface ITypeConverter {
        /**
         * Performs conversion from source to destination type.
         * @param {IResolutionContext} resolutionContext Resolution context.
         * @returns {any} Destination object.
         */
        convert: (resolutionContext: IResolutionContext) => any;
    }

    /**
     * Defines a naming convention strategy.
     */
    export interface INamingConvention {
        /** Regular expression on how to tokenize a member. */
        splittingExpression: RegExp;

        /** Character to separate on. */
        separatorCharacter: string;

        /**
         * Transformation function called when this convention is the destination naming convention.
         * @param {string[]} sourcePropertyNameParts Array containing tokenized source property name parts.
         * @returns {string} Destination property name
         */
        transformPropertyName: (sourcePropertyNameParts: string[]) => string;
    }

    /**
     * Configuration for profile-specific maps.
     */
    export interface IConfiguration {
        /**
         * Add an existing profile
         * @param profile {IProfile} Profile to add.
         */
        addProfile(profile: IProfile): void;

        /**
         * Create a createMap curry function which expects only a destination key.
         * @param {string} sourceKey The map source key.
         * @returns {(destinationKey: string) => IAutoMapperCreateMapChainingFunctions}
         */
        createMap?(sourceKey: string): (destinationKey: string) => ICreateMapFluentFunctions;

        /**
         * Create a mapping profile.
         * @param {string} sourceKey The map source key.
         * @param {string} destinationKey The map destination key.
         * @returns {Core.IAutoMapperCreateMapChainingFunctions}
         */
        createMap?(sourceKey: string, destinationKey: string): ICreateMapFluentFunctions;
    }

    /**
     * Provides a named configuration for maps. Naming conventions become scoped per profile.
     */
    export interface IProfile {
        /** Profile name */
        profileName: string;

        /** Naming convention for source members */
        sourceMemberNamingConvention: INamingConvention;

        /** Naming convention for destination members */
        destinationMemberNamingConvention: INamingConvention;

        /**
         * Implement this method in a derived class and call the CreateMap method to associate that map with this profile.
         * Avoid calling the AutoMapper class / automapper instance from this method.
         */
        configure: () => void;
    }

    export interface IMapItemFunction {
        (mapping: IMapping, sourceObject: any, destinationObject: any): any;
    }

    export interface IAsyncMapItemFunction {
        (mapping: IMapping, sourceObject: any, destinationObject: any, callback: IMapCallback): void;
    }

    interface ICreateMapParameters {
        mapping: IMapping;
        destinationProperty: string;
        conversionValueOrFunction: any;
        sourceMapping: boolean;
        fluentFunctions: ICreateMapFluentFunctions;
    }

    interface IGetOrCreatePropertyParameters {
        propertyNameParts: string[];
        mapping: IMapping;
        parent?: IProperty;
        propertyArray: IProperty[];
        destination?: string;
        sourceMapping: boolean;
    }

    interface ICreatePropertyParameters {
        name: string;
        mapping: IMapping;
        parent: IProperty;
        propertyArray: IProperty[];
        sourceMapping: boolean;
    }
}

declare var automapper: AutoMapperJs.AutoMapper;


text:
'use strict';

var minilog = require('minilog')
  , log = minilog('traverson');

function FinalAction(walker) {
  this.walker = walker;
}

FinalAction.prototype.get = function(nextStep, callback) {
  log.debug('next step: ' + JSON.stringify(nextStep, null, 2));
  this.walker.process(nextStep, function(err, step) {
    log.debug('walker.process returned');
    if (err) { return callback(err, step.response, step.uri); }
    if (!step.response && step.doc) {
      log.debug('faking HTTP response for embedded resource');
      step.response = {
        statusCode: 200,
        body: JSON.stringify(step.doc),
        remark: 'This is not an actual HTTP response. The resource you ' +
          'requested was an embedded resource, so no HTTP request was ' +
          'made to acquire it.'
      };
    }
    callback(null, step.response);
  });
};

FinalAction.prototype.getResource = function(nextStep, callback) {
  // TODO Remove duplication: This duplicates the get/checkHttpStatus/parse
  // sequence from the Walker's walk method.
  var self = this;
  log.debug('next step: ' + JSON.stringify(nextStep));
  this.walker.process(nextStep, function(err, step) {
    log.debug('walker.process returned');
    if (err) { return callback(err, step.response, step.uri); }

    if (step.doc) {
      // return an embedded doc immediately
      return callback(null, step.doc);
    }

    var resource;
    try {
      self.walker.checkHttpStatus(step);
      resource = self.walker.parse(step);
      return callback(null, resource);
    } catch (e) {
      return callback(e, e.doc);
    }
  });
};

FinalAction.prototype.getUri = function(nextStep, callback) {
  var self = this;
  log.debug('returning uri');
  if (nextStep.uri) {
    return callback(null, nextStep.uri);
  } else if (nextStep.doc &&
    nextStep.doc._links &&
    nextStep.doc._links.self &&
    nextStep.doc._links.self.href) {
    return callback(null, self.walker.startUri +
        nextStep.doc._links.self.href);
  } else {
    return callback(new Error('You requested an URI but the last ' +
        'resource is an embedded resource and has no URI of its own ' +
        '(that is, it has no link with rel=\"self\"'));
  }
};

FinalAction.prototype.walkAndExecute = function(body, request, method,
    callback) {
  var self = this;
  this.walker.walk(function(err, nextStep, lastStep) {
    log.debug('walker.walk returned');
    if (err) { return callback(err, lastStep.response, lastStep.uri); }
    log.debug('executing final request with step: ' +
        JSON.stringify(nextStep));
    self.executeRequest(nextStep.uri, request, method, body, callback);
  });
};

FinalAction.prototype.executeRequest = function(uri, request, method, body,
    callback) {
  var options;
  if (body) {
    options = { body: JSON.stringify(body) };
  } else {
    options = {};
  }
  log.debug('request to ' + uri + ' with options ' + JSON.stringify(options));
  method.call(request, uri, options, function(err, response) {
    log.debug('request to ' + uri + ' succeeded');
    if (err) { return callback(err, response, uri); }
    return callback(null, response, uri);
  });
};

module.exports = FinalAction;


text:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;

namespace GitHub.secile.Avi
{
    class MjpegWriter
    {
        private AviWriter aviWriter;

        /// Create with video stream.
        public MjpegWriter(System.IO.Stream outputAvi, int width, int height, int fps)
            : this(outputAvi, new AviWriter.VideoFormat() { Width = width, Height = height, FramesPerSec = fps }) { }

        /// Create with video stream.
        public MjpegWriter(System.IO.Stream outputAvi, AviWriter.VideoFormat videoFormat)
            : this(outputAvi, videoFormat, null) { }

        /// Create with video and audio stream.
        public MjpegWriter(System.IO.Stream outputAvi, AviWriter.VideoFormat videoFormat, AviWriter.AudioFormat audioFormat)
        {
            aviWriter = new AviWriter(outputAvi, "MJPG", videoFormat, audioFormat);
        }

        /// Add image to video stream.
        public void AddImage(Bitmap bmp)
        {
            using (var ms = new System.IO.MemoryStream())
            {
                bmp.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
                aviWriter.AddImage(ms.GetBuffer());
            }
        }

        /// Add audio data. Use when BitsPerSample = 8.
        /// <param name="data">8bit(0 to 255, base line = 128) wave pcm audio data. if stereo (Channels = 2), data order is LRLR...</param>
        public void AddAudio(byte[] data)
        {
            aviWriter.AddAudio(data);
        }

        /// Add audio data. Use when BitsPerSample = 16.
        /// <param name="data">16bit(-32767 to 32767) wave pcm audio data. if stereo (Channels = 2), data order is LRLR...</param>
        public void AddAudio(short[] data)
        {
            var byte_data = new byte[data.Length * 2];
            for (int i = 0; i < data.Length; i++)
            {
                byte_data[(i * 2) + 0] = (byte)(data[i] & 0xFF);
                byte_data[(i * 2) + 1] = (byte)(data[i] >> 8);
            }
            aviWriter.AddAudio(byte_data);
        }

        public void Close()
        {
            aviWriter.Close();
        }
    }
}


text:
import webob.exc

from nova.api.openstack import common
from nova.api.openstack.compute.views import images as views_images
from nova.api.openstack import wsgi
from nova.api.openstack import xmlutil
from nova import exception
from nova import flags
import nova.image.glance
from nova.openstack.common import log as logging
import nova.utils

LOG = logging.getLogger(__name__)
FLAGS = flags.FLAGS

SUPPORTED_FILTERS = {
    'name': 'name',
    'status': 'status',
    'changes-since': 'changes-since',
    'server': 'property-instance_uuid',
    'type': 'property-image_type',
    'minRam': 'min_ram',
    'minDisk': 'min_disk',
}

def make_image(elem, detailed=False):
    elem.set('name')
    elem.set('id')

    if detailed:
        elem.set('updated')
        elem.set('created')
        elem.set('status')
        elem.set('progress')
        elem.set('minRam')
        elem.set('minDisk')

        server = xmlutil.SubTemplateElement(elem, 'server', selector='server')
        server.set('id')
        xmlutil.make_links(server, 'links')

        elem.append(common.MetadataTemplate())

    xmlutil.make_links(elem, 'links')

image_nsmap = {None: xmlutil.XMLNS_V11, 'atom': xmlutil.XMLNS_ATOM}

class ImageTemplate(xmlutil.TemplateBuilder):
    def construct(self):
        root = xmlutil.TemplateElement('image', selector='image')
        make_image(root, detailed=True)
        return xmlutil.MasterTemplate(root, 1, nsmap=image_nsmap)

class MinimalImagesTemplate(xmlutil.TemplateBuilder):
    def construct(self):
        root = xmlutil.TemplateElement('images')
        elem = xmlutil.SubTemplateElement(root, 'image', selector='images')
        make_image(elem)
        xmlutil.make_links(root, 'images_links')
        return xmlutil.MasterTemplate(root, 1, nsmap=image_nsmap)

class ImagesTemplate(xmlutil.TemplateBuilder):
    def construct(self):
        root = xmlutil.TemplateElement('images')
        elem = xmlutil.SubTemplateElement(root, 'image', selector='images')
        make_image(elem, detailed=True)
        return xmlutil.MasterTemplate(root, 1, nsmap=image_nsmap)

class Controller(wsgi.Controller):
    """Base controller for retrieving/displaying images."""

    _view_builder_class = views_images.ViewBuilder

    def __init__(self, image_service=None, **kwargs):
        """Initialize new `ImageController`.

        :param image_service: `nova.image.glance:GlanceImageService`

        """
        super(Controller, self).__init__(**kwargs)
        self._image_service = (image_service or
                               nova.image.glance.get_default_image_service())

    def _get_filters(self, req):
        """
        Return a dictionary of query param filters from the request

        :param req: the Request object coming from the wsgi layer
        :retval a dict of key/value filters
        """
        filters = {}
        for param in req.params:
            if param in SUPPORTED_FILTERS or param.startswith('property-'):
                # map filter name or carry through if property-*
                filter_name = SUPPORTED_FILTERS.get(param, param)
                filters[filter_name] = req.params.get(param)

        # ensure server filter is the instance uuid
        filter_name = 'property-instance_uuid'
        try:
            filters[filter_name] = filters[filter_name].rsplit('/', 1)[1]
        except (AttributeError, IndexError, KeyError):
            pass

        filter_name = 'status'
        if filter_name in filters:
            # The Image API expects us to use lowercase strings for status
            filters[filter_name] = filters[filter_name].lower()

        return filters

    @wsgi.serializers(xml=ImageTemplate)
    def show(self, req, id):
        """Return detailed information about a specific image.

        :param req: `wsgi.Request` object
        :param id: Image identifier
        """
        context = req.environ['nova.context']

        try:
            image = self._image_service.show(context, id)
        except (exception.NotFound, exception.InvalidImageRef):
            explanation = _("Image not found.")
            raise webob.exc.HTTPNotFound(explanation=explanation)

        return self._view_builder.show(req, image)

    def delete(self, req, id):
        """Delete an image, if allowed.

        :param req: `wsgi.Request` object
        :param id: Image identifier (integer)
        """
        context = req.environ['nova.context']
        try:
            self._image_service.delete(context, id)
        except exception.ImageNotFound:
            explanation = _("Image not found.")
            raise webob.exc.HTTPNotFound(explanation=explanation)
        return webob.exc.HTTPNoContent()

    @wsgi.serializers(xml=MinimalImagesTemplate)
    def index(self, req):
        """Return an index listing of images available to the request.

        :param req: `wsgi.Request` object

        """
        context = req.environ['nova.context']
        filters = self._get_filters(req)
        params = req.GET.copy()
        page_params = common.get_pagination_params(req)
        for key, val in page_params.iteritems():
            params[key] = val

        try:
            images = self._image_service.detail(context, filters=filters,
                                                **page_params)
        except exception.Invalid as e:
            raise webob.exc.HTTPBadRequest(explanation=str(e))
        return self._view_builder.index(req, images)

    @wsgi.serializers(xml=ImagesTemplate)
    def detail(self, req):
        """Return a detailed index listing of images available to the request.

        :param req: `wsgi.Request` object.

        """
        context = req.environ['nova.context']
        filters = self._get_filters(req)
        params = req.GET.copy()
        page_params = common.get_pagination_params(req)
        for key, val in page_params.iteritems():
            params[key] = val
        try:
            images = self._image_service.detail(context, filters=filters,
                                                **page_params)
        except exception.Invalid as e:
            raise webob.exc.HTTPBadRequest(explanation=str(e))

        return self._view_builder.detail(req, images)

    def create(self, *args, **kwargs):
        raise webob.exc.HTTPMethodNotAllowed()

def create_resource():
    return wsgi.Resource(Controller())


text:
<!DOCTYPE html>

<title>2011 IL Senate Redistricting Plan</title>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />

<link href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8/themes/base/jquery-ui.css" rel="stylesheet" type="text/css"/>

<link href='/css/old_maps/master.css' media='all' rel='stylesheet' type='text/css' />

2011 IL Senate Redistricting Plan

			Back to derekeder.com »

				Show layers

				<input id="districts-2011" name="districts-2011" type="checkbox" onclick="toggle2011();" /> 2011 Senate Redistricting Plan

				<input id="districts-2001" name="districts-2001" type="checkbox" onclick="toggle2001();" /> 2001 Senate Boundaries

Search below to see where you fall in the new IL senate redistricting plan.

Address

<input class='txt hint' type="text" title="Enter an address or an intersection …" id="txtSearchAddress" onkeydown="if (event.keyCode == 13) document.getElementById('btnSearch').click()"/>

 within …

						<select id='ddlRadius'>
							<option value='400'>2 blocks</option>
							<option value='805'>1/2 mile</option>
							<option value='1610'>1 mile</option>
							<option value='3220'>2 miles</option>
							<option value='8046'>5 miles</option>
						</select>

					<input class="btn" type="button" id="btnSearch" value="Search" onclick="doSearch();" />
					reset map

From the Chicago News Cooperative ...

llinois Senate Democrats released a proposed map of revised state legislative districts Thursday, laying out the General Assembly's political
					boundaries for the next 10 years and setting off a political wrangle in Springfield to determine the final territorial borders.

The new map protects federally-mandated Latino and black districts, mostly in Chicago and its near suburbs. It was designed to give Democratic
					incumbents an edge in elections over the next decade by including pockets of heavily-Democratic voters in each district. It comes at the expense
					of Republicans, who played no role in the redistricting process.

Data from ilsenateredistricting.com and geodata.gov.

					View the raw data in Fusion Tables: 2001 | 2011. Map by Derek Eder.


text:
declare namespace json2csv {
  interface IField {
    label?: string;
    value: string;
    default?: string;
  }

  interface IOptions {
    data: any[];
    fields?: (string | IField)[];
    filedNames?: string[];
    del?: string;
    defaultValue?: string;
    quotes?: string;
    doubleQuotes?: string;
    hasCSVColumnTitle?: boolean;
    eol?: string;
    newLine?: string;
    flatten?: boolean;
    excelStrings?: boolean;
    includeEmptyRows?: boolean;
  }

  interface ICallback {
    (error: Error, csv: string): void;
  }

  export function json2csv(options: IOptions, callback: ICallback): void;
  export function json2csv(options: IOptions): string;
}

export = json2csv.json2csv;


text:
package biz

const (
	ServiceStatusKey = "/service_status"
)

const (
	StatusBootStart = iota
	StatusBootEnd   = iota
)


text:
In this tutorial, I'll cover the tools that I use the most in my day-to-day life as an Erlang developer. All or most of the topics that make the cut share the following characteristics:

- they're built specifically for Erlang (i.e. no text-editors, no git, etc.).
- they're not tailored to a particular kind of application (i.e. you can use them to develop _any kind_ of Erlang application).

---

## Working in the Shell

Like many other languages, the most common way to interact with an Erlang VM is through the Erlang shell. You can use it to test code, learn how to use Erlang, and debug production systems. The Erlang shell is a powerful thing, but you can add much more power to it with the three tools that I will show you below.

![I see a blondie](https://c2.staticflickr.com/8/7059/6886658738_d371a49e54_b.jpg)

### 1. [user_default](http://erlang.org/doc/man/erl.html#id191234)

In general, to evaluate functions outside a module in Erlang you have to prepend their names with the corresponding module name. For example, if you want to sum up a list, you have to do the following:

```erlang
1> lists:sum([1, 2, 3]).
6
2>
```

But you'll notice that for certain functions in the shell, you don't need explicit definitions. For example:

```erlang
1> c(your_module).
{ok,your_module}
2> h().
1: c(your_module)
-> {ok,your_module}
ok
3> e(1).
{ok,your_module}
4>
```

Where do such functions live? They're defined in the [shell_default](https://github.com/erlang/otp/blob/maint/lib/stdlib/src/shell_default.erl) module. You can add your own default functions as well. To do that, you have to create and load a module called `user_default`. As an example, I like to run bash commands when using the Erlang shell; I don't want to leave the shell just to copy a file. Erlang/OTP gives you a a function to do that: `os:cmd/1`, but that will not print out the output of your command. Instead this command will return that output as a string. You have to print the string to see the output properly.

So, using **`user_default`**, I added the following lines to my **`user_default.erl`** file:

```erlang
-module(user_default).
-export([cmd/1].

cmd(Cmd) -> io:format("~s~n", [os:cmd(Cmd)]).
```

Now I can run, execute, and *print* the results of `os:cmd/1` using my shell:

```erlang
1> c(user_default).
{ok, user_default}
2> cmd("cat user_default.erl").
-module(user_default).
-export([cmd/1].

cmd(Cmd) -> io:format("~s~n", [os:cmd(Cmd)]).

ok
3>
```

### 2. [~/.erlang](http://erlang.org/doc/man/erl.html#id191234)

But then, I have to manually load `user_default` in every single shell that I open. **`~/.erlang`** to the rescue! `~/.erlang` is a file that works almost like `~/.bashrc` for bash. Upon starting, the shell reads `~/.erlang` and evaluates each one of the expressions it finds there as if they were inputted to the shell.

So, I added the following lines to that file:

```erlang
UD = "/path/to/my/user_default".
shell_default:c(UD).
```

My `~/.erlang` is actually more complicated than that, but the `shell_default` should give you the gist of my modifications. Now, every shell that I open comes with support for `cmd/1`.

### 3. [erlang-history](https://github.com/ferd/erlang-history)

One of the most annoying things about the Erlang shell is that it does not keep track of command history very well. In fact, default settings will erase all command history upon closing the shell. I've seen many devs working around this limitation by having a notebook of erlang expressions from which they copy & paste into the console every time. (Some of them use `user_default` and/or `~/.erlang` for that.)

But still, it's not a real solution, right? To properly fix the issue, right after installing a new version of Erlang/OTP, **I install [erlang-history](https://github.com/ferd/erlang-history).** It's a really tiny almost-invisible hack to the Erlang/OTP distribution with one simple purpose: to keep track of your previous commands in your Erlang shells and let you reuse them. Simple, yet amazingly useful.

---

## Managing your Apps

As soon as you move past the simple examples and into the realm of OTP apps, you'll be much better off working with a build tool that can help you organize your code, manage dependencies, build releases, run tests, and more.

![Dangerous to go Alone](http://www.tierragamer.com/wp-content/uploads/2016/02/its-dangerous-to-go-alone-take-this.jpg)

When working with Erlang, you can either embrace the _Makefile_ or try get as far away from it as possible.

### 4. [erlang.mk](https://erlang.mk/)

If using Makefiles to build and manage your projects seems natural to you, you will probably like [erlang.mk](https://erlang.mk/). `erlang.mk` is basically a big Makefile script that you can include in your own Makefile with something like:

```Makefile
PROJECT=your_app
include erlang.mk
```

With that, you get access to many commands, like
* `$ make` to build your project
* `$ make tests` to run your test suites
* `$ make rel` to generate a release

You can find the whole list using `$ make help`, and you can, of course, add more by just extending your Makefile.

`erlang.mk` also provides a plugin infrastructure, where you can add build tools, like [hexer.mk](https://github.com/inaka/hexer.mk) or [elvis.mk](https://github.com/inaka/elvis.mk).

The best thing about `erlang.mk` is that it provides the necessary support for building almost any existing Erlang library, regardless of the tool that library owners use to maintain it. With `erlang.mk` you can include applications built with **rebar**, **rebar3**, **erlang.mk** (as expected :P), ad-hoc **Makefiles**, and others in your depositories. You can download deps from **github**, **hex.pm**, **bitbucket**, your local filesystem and many other places. Clearly `erlang.mk` makes Erlang vastly more versatile.

### 5. [rebar3](http://www.rebar3.org/)

Now, if Makefiles are not your thing and you prefer to use _the official build tool_ (since March 2016) sponsored by the Erlang/OTP team, then [rebar3](http://www.rebar3.org/) is your way to go.

**rebar3** is written entirely in Erlang and the idea is that you can use it _without_ adding any Makefile to your project.

Once you [install it](http://www.rebar3.org/v3.0/docs#installing-binary) in your system, you should add a `rebar.config` file in the root folder of your project. A minimal one looks something like this (although even the options below are optional):

```erlang
{deps, []}.
{erl_opts, [debug_info]}.
{cover_enabled, true}.
```

You can find the list of all the options you can speficy [here](http://www.rebar3.org/docs/configuration).
Then, you can run commands like the ones below in your shell:
* `$ rebar3 compile` to fetch deps and build your project
* `$ rebar3 ct` to run your tests
* `$ rebar3 release` to generate a release

Of course, `$ rebar3 help` gives you the list of all available commands. And, just like `erlang.mk`, `rebar3` is also extensible through [plugins](http://www.rebar3.org/docs/using-available-plugins).

One of the best things about `rebar3` is that, by using `rebar.lock`, it provides _repeatable builds_. That way, once you're sure your project works as expected, you can be sure it will keep working as expected no matter how many times or in how many different places you compile it.

---

## Ensuring Code Quality

I've personally stated a couple of times online (in [interviews](https://www.functionalgeekery.com/functional-geekery-episode-43-brujo-benavides/) and blog posts) how important it is (especially if you work on open-source projects) to maintain high code quality. Erlang comes with several tools that will help you with that. Erlang tools can even help you detect bugs that you'll probably find at runtime… without running your system!

![Paddin](https://i.ytimg.com/vi/8ktYyme_sUw/maxresdefault.jpg)

### 6. [dialyzer](http://erlang.org/doc/man/dialyzer.html)

**Dialyzer** is a static analysis tool that will help you identify type inconsistencies in your code, like when you are passing a `binary()` as the parameter to a function that expects a `string()`. This used to be a very very slow tool, but it has since been highly optimized and now runs smoothly, especially if you run it frequently. Plus, it's integrated in both [`rebar3`](https://www.rebar3.org/docs/commands#dialyzer) and [`erlang.mk`](https://erlang.mk/guide/dialyzer.html). (Follow the links to learn more.)

If you use **dialyzer** (`dia.erl`), you'll see results like the one below.

```erlang
  Checking whether the PLT dia.plt is up-to-date... yes
  Proceeding with analysis...
    compile    (+0.09s):   0.02s (   1 modules)
    clean      (+0.00s):   0.00s
    remote     (+0.00s):   0.18s
    order      (+0.00s):   0.00s
    typesig    (+0.12s):   0.01s (      3 SCCs)
    order      (+0.00s):   0.00s
    refine     (+0.00s):   0.01s (   1 modules)
    warning    (+0.00s):   0.00s (   1 modules)
              (+ 0.71s)

dia.erl:5: Function bad/0 has no local return
dia.erl:5: The call lists:flatten(<<_:168>>) will never return since it differs in the
            1st argument from the success typing arguments: ([any()])
 done in 0m1.16s
done (warnings were emitted)
```

In this case in line 5 of `dia.erl`, we are calling `lists:flatten/1` with a 168-bit long binary (`<<_:168>>`) when that function expects a list (`[any()]`) as its parameter. This warning was **not** raised at compile time, but using **dialyzer** you can find it **before** it pops up during run time.

### 7. [xref](http://erlang.org/doc/man/xref.html)

A much simpler tool that's been packed in the Erlang/OTP distribution is **`xref`**. `xref` is a cross-reference tool that analyses your code and finds calls to unexistent functions, deprecated functions and other similar things. It doesn't search as deeply as dialyzer, but it will spot obvious bugs in no time.

`xref` is also integrated with [`rebar3`](https://www.rebar3.org/docs/commands#xref) and [`erlang.mk`](https://erlang.mk/guide/xref.html) (The documentation is not there yet, but it uses [`xref_runner`](https://github.com/inaka/xref_runner) to check your code).

`xref` can find errors like:

```erlang
…
===> Running cross reference analysis...
===> Warning: your_module:your_function/1 calls undefined function this_function:doesnt_exist/1 (Xref)
…
```

There `xref` detected that we're calling a function that doesn't exist from within the code of `your_module:your_function/1`. Again, that's something that the compiler __will not__ warn you about.

### 8. [elvis](http://github.com/inaka/elvis)

Besides analyzing your code in search for bugs with `xref` and dialyzer, you can ensure that the code in your project is maintainable. **elvis** is a command-line tool (and an Erlang application as well) that you can use to verify the compliance of your code to certain style rules, which you pre-define in your `elvis.config` file. There is a plugin for [`rebar3`](https://github.com/project-fifo/rebar3_lint) and another one for [`erlang.mk`](https://github.com/inaka/elvis.mk). You can also use **elvis [online](http://elvis.inakalabs.com)** to check your github pull requests.

Its output looks like the following:

```erlang
Loading files...
Loading src/dia.erl
Applying rules...
# src/dia.erl [FAIL]
  - no_tabs
    - Line 33 has a tab at column 0.
```

In this case, elvis is detecting the usage of tabs for indentation which is something that's specified as invalid in the project's `elvis.config` file.

---

## Debugging your Servers

The next group of tools assume that you already created your app, packed it up as a release, and deployed it to some server. They also assume that the app's been running for a while, but has started behaving strangely. So you need to _debug_ it.

First, you connect to your server with a [remote shell](http://erlang.org/doc/man/erl.html#id186912) (See the link for the `-remsh` command). Then, you use Erlang's [dbg](http://erlang.org/doc/man/dbg.html).

Alas, **dbg** is not a very intuitive, simple debugging tool. It's really powerful, but there are simpler tools for the task at hand. I'll show you 2 of them below.

![investigating…](https://upload.wikimedia.org/wikipedia/commons/1/13/Special_Agent_Adam_Deem_of_Air_Force_Office_of_Special_Investigation_Detachment_219.jpg)

### 9. [redbug](https://hex.pm/packages/eper)

**redbug** is a debugging application which is quite similar to **dbg**, but with a more intuitive interface. It comes with **eper** but, to be honest, `redbug` is the only `eper` component I've ever used. With `redbug`, you can specify a trace pattern as a string, and it will print out a message in your console everytime a function call matching that pattern is evaluated. It looks like this:

```erlang
1> redbug:start("your_module:your_private_function->return").
{156,1}
2> your_module:your_public_function().
% 19:55:12 <0.1.0>({erlang,apply,4})
% your_module:your_private_function(some, parameters)

% 19:55:12 <0.1.0>({erlang,apply,4})
% your_module:your_private_function/2 -> ok
ok
3>
```

I actually tend to always use the same options when starting `redbug`. You can check the available startup options using `redbug:help()`. As such, I've added this start code to my [user_default](#1-a-href-http-erlang-org-doc-man-erl-html-id191234-target-_blank-user_default-nbsp-span-class-glyphicon-glyphicon-new-window-aria-hidden-true-style-font-size-10px-span-a-) (Don't do this in production, kids!!):

```
redbug(What) ->
  catch redbug:stop(),
  timer:sleep(100),
  redbug:start(What, [{time, 9999999}, {msgs, 9999999}, {print_msec, true}]).
```

Now I can easily get `redbug` going.:

```erlang
4> redbug("your_module:your_private_function->return").
{156,1}
5> your_module:your_public_function().
% 19:59:13 <0.1.0>({erlang,apply,4})
% your_module:your_private_function(some, parameters)

% 19:59:13 <0.1.0>({erlang,apply,4})
% your_module:your_private_function/2 -> ok
ok
6>
```

### 10. [recon](https://hex.pm/packages/recon)

But tracing function calls is just one of the many things you can do to check the health of your Erlang servers. [Fred Hebert](https://twitter.com/mononcqc/) recollected tons of experiences dealing with that in both a great book ([Stuff Goes Bad: Erlang In Anger](https://www.erlang-in-anger.com/)) and a great tool: [**recon**](http://ferd.github.io/recon/).

With **recon** you can do many things, you can: trace function calls (just like `redbug`), recover the source code of your compiled modules, check app memory consumption, figure out message queue lengths, clean up binary memory, find leaks and much more. I strongly recommend you to read the book and play around with the different `recon` tools described in it. You'll want to know them by heart if your server starts behaving erratically.

---

## Bonus Tracks

Now some pointers that don't _really_ fit in the list above, but deserve to be mentioned anyway.

![Bonus](http://www.picserver.org/images/highway/phrases/bonus.jpg)

### 11. [Meta Testing](https://github.com/inaka/katana-test)

If you use TDD (even if you just use [common test](http://erlang.org/doc/man/common_test.html) to test your Erlang apps and you are interested in maintaining your [code quality](#ensuring-code-quality) using the tools I mentioned above, you have to check [katana-test](https://github.com/inaka/katana-test). With the code below, you'll be dialyzing, `xref`ing, and rocking your code every time you run your tests.

```erlang
-module(your_meta_SUITE).

-include_lib("mixer/include/mixer.hrl").
-mixin([ktn_meta_SUITE]).

-export([init_per_suite/1]).

init_per_suite(Config) -> [{application, your_app} | Config].
```

I call that **Meta Testing**, and I've written two blog posts about it already. Check them out [here](http://inaka.net/blog/2015/07/17/erlang-meta-test/) and [here](http://inaka.net/blog/2015/11/13/erlang-meta-test-revisited/).

### 12. The Community

No list of great Erlang things will be complete without a shout out to the great community of developers behind it. If you're going to work on Erlang or even if you're just approaching the language and you want to know what it's all about, _you have to meet the erlangers_.

There are a couple of ways to acoomplish that:
* The [erlang-questions](http://erlang.org/mailman/listinfo/erlang-questions) mailing list is the most popular and arguably the _official_ communication medium for the community. Yes, it's a mailing list. No, it will not fill up your inbox like spam.
* We also have an [IRC room](http://irc.lc/freenode/erlang/t4nk@@@) on _freenode_ and a [ server](erlanger.slack.com) on Slack where we constantly meet.
* And you can find some of us on [ErlangCentral](http://erlangcentral.org), too.

If you're serious about Erlang development, keep an eye on those platforms and stay connected with us for updates and other opportunities!

### 13. [Guidelines](https://github.com/inaka/erlang_guidelines)

Finally, I want to mention the Erlang Guidelines, published by Inaka [on github](https://github.com/inaka/erlang_guidelines). As I said [in the mailing list](http://erlang.org/pipermail/erlang-questions/2014-September/080935.html) when we first talked about them:
> [erlang_guidelines] is the set of standards that we (at Inaka) enforce in our Erlang code.
> […]
> It will only reflect the ideas of the ~8 erlangers that were/are working at Inaka. We accept contributions because we love good and constructive debate, but we don't expect anybody […] to like [our guidelines] :)

In other words, the guidelines on that repo don't need to be **your** guidelines, but you should have **some** guidelines of your own. Forking that repo and then adapting its contents to your ideas may be a good way to start. Others have done [exactly that](https://github.com/inaka/erlang_guidelines/network) already.
As [Iñaki](https://twitter.com/iraunkortasuna) once explained:

> Code formatting, spacing, layout and _
"making the code look good"_ is **not** the goal of having guidelines. Similarly, the idea is not to engage in bondage programming in which everyone is forced to do something they don't want, but to have a baseline of order and agreed-upon-terms.
>
> The purpose of having consensus and following it is to **free up energy**, not to consume it in favor of poorly-defined or subjective goals such as _"it looks better"_. Having each one one make up his/her own rules _"and damn the rest"_ is just as antisocial as forcing everyone to adhere to strict guidelines which dictate where you put your commas or spacing. Discipline provides freedom
to the group, because once you achieve consensus on a matter, the effort of dealing with other's trespasses is greater than the effort of keeping oneself from trespassing.
>
> Issues such as line length restrictions are a means to an end: they make the code easier to change, debug, and extend to respond faster to requirement changes. To agree with any of this, one must acknowledge that programming is a **social endeavor**, and group behaviour applies. It may be easier to write for you, at this time, but others will have to read it. This is the sole objective of code guidelines.

___

Hopefully this guide cleared up some of the questions you may have had regarding Erlang-based application development and also boosted your interest in creating Erlang apps! Thank you for reading, and please leave your comments and feedback in the discussion section below.


text:
"""
WSGI config for swarfarm project.

It exposes the WSGI callable as a module-level variable named ``application``.

For more information on this file, see
https://docs.djangoproject.com/en/1.8/howto/deployment/wsgi/
"""

import os,sys
sys.path.append("/var/www/swarfarm")
from django.core.wsgi import get_wsgi_application
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "swarfarm.settings")
application = get_wsgi_application()


text:
<?php

namespace Thytanium\ModelGenerator;

use Illuminate\Support\ServiceProvider;

/**
 * @package ModelGenerator
 * @author Alejandro González thytanium@gmail.com
 * @license MIT http://opensource.org/licenses/MIT
 * @link http://www.github.com/thytanium/model-generator
 */
class ModelGeneratorServiceProvider extends ServiceProvider
{
    protected $defer = true;

    /**
     * Register the service provider.
     *
     * @return void
     */
    public function register()
    {
        // TODO: Implement register() method.
        $this->app->bind('ModelGenerator',
        /**
         * @param $app
         * @return ModelGenerator
         */
        function ($app) {
            return new ModelGenerator($app['files']);
        });
    }

    /**
     * Boot the service provider
     *
     * @return void
     */
    public function boot()
    {
        //Register commands
        $this->commands([
            'Thytanium\ModelGenerator\Commands\GenerateModels',
        ]);
    }

    /**
     * Get the services provided by the provider
     * @return array
     */
    public function provides()
    {
        return ['Thytanium\ModelGenerator\ModelGenerator'];
    }
}


text:
namespace Knowledge.Prospector.Languages
{
	/// <summary>
	/// Summary description for Russian.
	/// </summary>
	public class Russian : Language, ILanguage
	{
		#region SingleTone

		/// <summary>
		/// Hide constructor
		/// </summary>
		private Russian() { }

		/// <summary>
		/// Used for storing single exemplar of class
		/// </summary>
		private static Russian _instance;

		/// <summary>
		/// Not more then one instance at one time
		/// </summary>
		/// <returns>Exemplar of class</returns>
		public static Russian GetInstance()
		{
			if (_instance == null)
			{
				_instance = new Russian();
			}
			return _instance;
		}

		#endregion

		#region ILanguage Members

		public override string Name
		{
			get { return "Russian"; }
		}

		#endregion
}
}


text:
package java.util;

import com.facebook.infer.builtins.InferUndefined;

public abstract class Vector<E> {

  protected E[] elementData;

  E elementData(int index) {
    return (E) elementData[index];
  }

  public Enumeration<E> elements() {
    return new Enumeration<E>() {
      int count;

      public boolean hasMoreElements() {
        return count > 0;
      }

      public E nextElement() {
        if (count > 0) return (E) InferUndefined.object_undefined();
        else throw new NoSuchElementException();
      }
    };
  }

  public E get(int index) {
    return elementData(index);
  }

  public int size() {
    return InferUndefined.nonneg_int();
  }
}


text:
#pragma once
#include <aws/appmesh/AppMesh_EXPORTS.h>
#include <aws/appmesh/model/TcpRouteAction.h>
#include <aws/appmesh/model/TcpRouteMatch.h>
#include <aws/appmesh/model/TcpTimeout.h>
#include <utility>

namespace Aws
{
namespace Utils
{
namespace Json
{
  class JsonValue;
  class JsonView;
} // namespace Json
} // namespace Utils
namespace AppMesh
{
namespace Model
{

  /**
   *
An object that represents a TCP route type.

See Also:
   AWS
   * API Reference

   */
  class AWS_APPMESH_API TcpRoute
  {
  public:
    TcpRoute();
    TcpRoute(Aws::Utils::Json::JsonView jsonValue);
    TcpRoute& operator=(Aws::Utils::Json::JsonView jsonValue);
    Aws::Utils::Json::JsonValue Jsonize() const;

    /**
     *
The action to take if a match is determined.

     */
    inline const TcpRouteAction& GetAction() const{ return m_action; }

    /**
     *
The action to take if a match is determined.

     */
    inline bool ActionHasBeenSet() const { return m_actionHasBeenSet; }

    /**
     *
The action to take if a match is determined.

     */
    inline void SetAction(const TcpRouteAction& value) { m_actionHasBeenSet = true; m_action = value; }

    /**
     *
The action to take if a match is determined.

     */
    inline void SetAction(TcpRouteAction&& value) { m_actionHasBeenSet = true; m_action = std::move(value); }

    /**
     *
The action to take if a match is determined.

     */
    inline TcpRoute& WithAction(const TcpRouteAction& value) { SetAction(value); return *this;}

    /**
     *
The action to take if a match is determined.

     */
    inline TcpRoute& WithAction(TcpRouteAction&& value) { SetAction(std::move(value)); return *this;}

    /**
     *
An object that represents the criteria for determining a request match.

     */
    inline const TcpRouteMatch& GetMatch() const{ return m_match; }

    /**
     *
An object that represents the criteria for determining a request match.

     */
    inline bool MatchHasBeenSet() const { return m_matchHasBeenSet; }

    /**
     *
An object that represents the criteria for determining a request match.

     */
    inline void SetMatch(const TcpRouteMatch& value) { m_matchHasBeenSet = true; m_match = value; }

    /**
     *
An object that represents the criteria for determining a request match.

     */
    inline void SetMatch(TcpRouteMatch&& value) { m_matchHasBeenSet = true; m_match = std::move(value); }

    /**
     *
An object that represents the criteria for determining a request match.

     */
    inline TcpRoute& WithMatch(const TcpRouteMatch& value) { SetMatch(value); return *this;}

    /**
     *
An object that represents the criteria for determining a request match.

     */
    inline TcpRoute& WithMatch(TcpRouteMatch&& value) { SetMatch(std::move(value)); return *this;}

    /**
     *
An object that represents types of timeouts.

     */
    inline const TcpTimeout& GetTimeout() const{ return m_timeout; }

    /**
     *
An object that represents types of timeouts.

     */
    inline bool TimeoutHasBeenSet() const { return m_timeoutHasBeenSet; }

    /**
     *
An object that represents types of timeouts.

     */
    inline void SetTimeout(const TcpTimeout& value) { m_timeoutHasBeenSet = true; m_timeout = value; }

    /**
     *
An object that represents types of timeouts.

     */
    inline void SetTimeout(TcpTimeout&& value) { m_timeoutHasBeenSet = true; m_timeout = std::move(value); }

    /**
     *
An object that represents types of timeouts.

     */
    inline TcpRoute& WithTimeout(const TcpTimeout& value) { SetTimeout(value); return *this;}

    /**
     *
An object that represents types of timeouts.

     */
    inline TcpRoute& WithTimeout(TcpTimeout&& value) { SetTimeout(std::move(value)); return *this;}

  private:

    TcpRouteAction m_action;
    bool m_actionHasBeenSet = false;

    TcpRouteMatch m_match;
    bool m_matchHasBeenSet = false;

    TcpTimeout m_timeout;
    bool m_timeoutHasBeenSet = false;
  };

} // namespace Model
} // namespace AppMesh
} // namespace Aws


text:
<?php

namespace Cerbero\FluentApi\Clients;

use Closure;

/**
 * Interface for clients able to perform asynchronous calls.
 *
 */
interface AsyncClientInterface extends ClientInterface
{
    /**
     * Process the HTTP request asynchronously.
     *
     * @author    Andrea Marco Sartori
     * @param    string    $verb
     * @param    string    $endpoint
     * @param    array    $options
     * @param    Closure    $success
     * @param    Closure|null    $failure
     * @return    mixed
     */
    public function then($verb, $endpoint, array $options = [], Closure $success, Closure $failure = null);
}


text:
require File.expand_path("helper", File.dirname(__FILE__))

class TestDistributedInternals < Test::Unit::TestCase

  include Helper::Distributed

  def test_provides_a_meaningful_inspect
    nodes = ["redis://127.0.0.1:#{PORT}/15", *NODES]
    redis = Redis::Distributed.new nodes

    assert_equal "#<Redis client v#{Redis::VERSION} for #{redis.nodes.map(&:id).join(', ')}>", redis.inspect
  end

  def test_default_as_urls
    nodes = ["redis://127.0.0.1:#{PORT}/15", *NODES]
    redis = Redis::Distributed.new nodes
    assert_equal ["redis://127.0.0.1:#{PORT}/15", *NODES], redis.nodes.map { |node| node.client.id}
  end

  def test_default_as_config_hashes
    nodes = [OPTIONS.merge(:host => '127.0.0.1'), OPTIONS.merge(:host => 'somehost', :port => PORT.next)]
    redis = Redis::Distributed.new nodes
    assert_equal ["redis://127.0.0.1:#{PORT}/15","redis://somehost:#{PORT.next}/15"], redis.nodes.map { |node| node.client.id }
  end

  def test_as_mix_and_match
    nodes = ["redis://127.0.0.1:7389/15", OPTIONS.merge(:host => 'somehost'), OPTIONS.merge(:host => 'somehost', :port => PORT.next)]
    redis = Redis::Distributed.new nodes
    assert_equal ["redis://127.0.0.1:7389/15", "redis://somehost:#{PORT}/15", "redis://somehost:#{PORT.next}/15"], redis.nodes.map { |node| node.client.id }
  end

  def test_override_id
    nodes = [OPTIONS.merge(:host => '127.0.0.1', :id => "test"), OPTIONS.merge( :host => 'somehost', :port => PORT.next, :id => "test1")]
    redis = Redis::Distributed.new nodes
    assert_equal redis.nodes.first.client.id, "test"
    assert_equal redis.nodes.last.client.id,  "test1"
    assert_equal "#<Redis client v#{Redis::VERSION} for #{redis.nodes.map(&:id).join(', ')}>", redis.inspect
  end

  def test_can_be_duped_to_create_a_new_connection
    redis = Redis::Distributed.new(NODES)

    clients = redis.info[0]["connected_clients"].to_i

    r2 = redis.dup
    r2.ping

    assert_equal clients + 1, redis.info[0]["connected_clients"].to_i
  end

  def test_keeps_options_after_dup
    r1 = Redis::Distributed.new(NODES, :tag => /^(\w+):/)

    assert_raise(Redis::Distributed::CannotDistribute) do
      r1.sinter("foo", "bar")
    end

    assert_equal [], r1.sinter("baz:foo", "baz:bar")

    r2 = r1.dup

    assert_raise(Redis::Distributed::CannotDistribute) do
      r2.sinter("foo", "bar")
    end

    assert_equal [], r2.sinter("baz:foo", "baz:bar")
  end
end


text:
import {timeout} from './lib/utils';
import faye from 'faye';

let ble_sint16 = ['getInt16', 2, true];
let ble_uint8 = ['getUint8', 1];
let ble_uint16 = ['getUint16', 2, true];
let ble_uint32 = ['getUint32', 4, true];
// TODO: paired 12bit uint handling
let ble_uint24 = ['getUint8', 3];

// https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.characteristic.cycling_power_measurement.xml
let cycling_power_measurement = [
  [0, [ [ble_sint16, 'instantaneous_power'] ]],
  [1, [ [ble_uint8, 'pedal_power_balance'] ]],
  [2, [ /* Pedal Power Balance Reference */]],
  [4, [ [ble_uint16, 'accumulated_torque'] ]],
  [8, [ /* Accumulated Torque Source */]],
  [16, [ [ble_uint32, 'cumulative_wheel_revolutions'], [ble_uint16, 'last_wheel_event_time'] ]],
  [32, [ [ble_uint16, 'cumulative_crank_revolutions'], [ble_uint16, 'last_crank_event_time'] ]],
  [64, [ [ble_sint16, 'maximum_force_magnitude'], [ble_sint16, 'minimum_force_magnitude'] ]],
  [128, [ [ble_sint16, 'maximum_torque_magnitude'], [ble_sint16, 'minimum_torque_magnitude'] ]],
  [256, [ [ble_uint24, 'maximum_minimum_angle'] ]],
  [512, [ [ble_uint16, 'top_dead_spot_angle'] ]],
  [1024, [ [ble_uint16, 'bottom_dead_spot_angle'] ]],
  [2048, [ [ble_uint16, 'accumulated_energy'] ]],
  [4096, [ /* Offset Compensation Indicator */]]
];

// https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.characteristic.csc_measurement.xml
let csc_measurement = [
  [1, [ [ble_uint32, 'cumulative_wheel_revolutions'], [ble_uint16, 'last_wheel_event_time'] ]],
  [2, [ [ble_uint16, 'cumulative_crank_revolutions'], [ble_uint16, 'last_crank_event_time'] ]]
];

let ant_manufacturers = {
  1: 'garmin',
  2: 'garmin_fr405_antfs',
  3: 'zephyr',
  4: 'dayton',
  5: 'idt',
  6: 'srm',
  7: 'quarq',
  8: 'ibike',
  9: 'saris',
  10: 'spark_hk',
  11: 'tanita',
  12: 'echowell',
  13: 'dynastream_oem',
  14: 'nautilus',
  15: 'dynastream',
  16: 'timex',
  17: 'metrigear',
  18: 'xelic',
  19: 'beurer',
  20: 'cardiosport',
  21: 'a_and_d',
  22: 'hmm',
  23: 'suunto',
  24: 'thita_elektronik',
  25: 'gpulse',
  26: 'clean_mobile',
  27: 'pedal_brain',
  28: 'peaksware',
  29: 'saxonar',
  30: 'lemond_fitness',
  31: 'dexcom',
  32: 'wahoo_fitness',
  33: 'octane_fitness',
  34: 'archinoetics',
  35: 'the_hurt_box',
  36: 'citizen_systems',
  37: 'magellan',
  38: 'osynce',
  39: 'holux',
  40: 'concept2',
  42: 'one_giant_leap',
  43: 'ace_sensor',
  44: 'brim_brothers',
  45: 'xplova',
  46: 'perception_digital',
  47: 'bf1systems',
  48: 'pioneer',
  49: 'spantec',
  50: 'metalogics',
  51: '4iiiis',
  52: 'seiko_epson',
  53: 'seiko_epson_oem',
  54: 'ifor_powell',
  55: 'maxwell_guider',
  56: 'star_trac',
  57: 'breakaway',
  58: 'alatech_technology_ltd',
  59: 'mio_technology_europe',
  60: 'rotor',
  61: 'geonaute',
  62: 'id_bike',
  63: 'specialized',
  64: 'wtek',
  65: 'physical_enterprises',
  66: 'north_pole_engineering',
  67: 'bkool',
  68: 'cateye',
  69: 'stages_cycling',
  70: 'sigmasport',
  71: 'tomtom',
  72: 'peripedal',
  73: 'wattbike',
  76: 'moxy',
  77: 'ciclosport',
  78: 'powerbahn',
  79: 'acorn_projects_aps',
  80: 'lifebeam',
  81: 'bontrager',
  82: 'wellgo',
  83: 'scosche',
  84: 'magura',
  85: 'woodway',
  86: 'elite',
  87: 'nielsen_kellerman',
  88: 'dk_city',
  89: 'tacx',
  90: 'direction_technology',
  91: 'magtonic',
  92: '1partcarbon',
  93: 'inside_ride_technologies',
  94: 'sound_of_motion',
  95: 'stryd',
  96: 'icg',
  97: 'MiPulse',
  98: 'bsx_athletics',
  99: 'look',
  100: 'campagnolo_srl',
  101: 'body_bike_smart',
  102: 'praxisworks',
  103: 'limits_technology',
  104: 'topaction_technology',
  105: 'cosinuss',
  106: 'fitcare',
  107: 'magene',
  108: 'giant_manufacturing_co',
  109: 'tigrasport',
  110: 'salutron',
  111: 'technogym',
  112: 'bryton_sensors',
  113: 'latitude_limited',
  114: 'soaring_technology',
  115: 'igpsport',
  116: 'thinkrider',
  117: 'gopher_sport',
  118: 'waterrower',
  255: 'development',
  257: 'healthandlife',
  258: 'lezyne',
  259: 'scribe_labs',
  260: 'zwift',
  261: 'watteam',
  262: 'recon',
  263: 'favero_electronics',
  264: 'dynovelo',
  265: 'strava',
  266: 'precor',
  267: 'bryton',
  268: 'sram',
  269: 'navman',
  270: 'cobi',
  271: 'spivi',
  272: 'mio_magellan',
  273: 'evesports',
  274: 'sensitivus_gauge',
  275: 'podoon',
  276: 'life_time_fitness',
  277: 'falco_e_motors',
  278: 'minoura',
  279: 'cycliq',
  280: 'luxottica',
  281: 'trainer_road',
  282: 'the_sufferfest',
  283: 'fullspeedahead',
  284: 'virtualtraining',
  285: 'feedbacksports',
  286: 'omata',
  287: 'vdo',
  5759: 'actigraphcorp'
};

class BleCharacteristicParser {
  getData(dataview) {
    let offset = 0;
    let mask;
    if(this.mask_size === 16) {
      mask = dataview.getUint16(0, true);
      offset += 2;
    } else {
      mask = dataview.getUint8(0);
      offset += 1;
    }

    let fieldArrangement = [];

    // Contains required fields
    if(this.fields[0][0] === 0) {
      for(let fdesc of this.fields[0][1]) {
        fieldArrangement.push(fdesc);
      }
    }

    for(let [flag, fieldDescriptions] of this.fields) {
      if(mask & flag) {
        for(let fdesc of fieldDescriptions) {
          fieldArrangement.push(fdesc);
        }
      }
    }

    let data = {};
    for(let field of fieldArrangement) {
      var [[accessor, fieldSize, endianness], fieldName] = field;
      let value;
      if(endianness) {
        value = dataview[accessor](offset, endianness);
      } else {
        value = dataview[accessor](offset);
      }

      data[fieldName] = value;
      offset += fieldSize;
    }

    return data;
  }
}

class CyclingSpeedCadenceMeasurementParser extends BleCharacteristicParser {
  constructor () {
    super();
    this.fields = csc_measurement;
    this.mask_size = 8;
  }
}

export class CyclingPowerMeasurementParser extends BleCharacteristicParser {
  constructor () {
    super();
    this.fields = cycling_power_measurement;
    this.mask_size = 16;
  }
}

export class Meter {
  constructor () {
    this.listeners = {};
    this.timeoutID = undefined;
    this.milliTimeout = 8000;
  }

  clearValueOnTimeout(value) {
    if(this.timeoutID !== undefined) {
      clearTimeout(this.timeoutID);
    }
    this.timeoutID = setTimeout(() => {
      this.timeoutID = undefined;
      if(value.constructor === Array) {
        for(let v of value) {
          this.dispatch(v, 0);
        }
      } else {
        this.dispatch(value, 0);
      }
    }, this.milliTimeout);
  }

  addListener(type, callback) {
    if(!(type in this.listeners)) {
      this.listeners[type] = [];
    }

    this.listeners[type].push(callback);
  }

  dispatch(type, value) {
    if(!(type in this.listeners)) {
      this.listeners[type] = [];
    }

    for(let l of this.listeners[type]) {
      l(value);
    }
  }
}

export class BleMeter extends Meter {
  constructor (device, server, service, characteristic) {
    super();

    this.device = device;
    this.server = server;
    this.service = service;
    this.characteristic = characteristic;

    this.name = this.device.name;
    this.id = this.device.id;

    this.listening = false;

    this.device.addEventListener('gattserverdisconnected', e => {
      this.gattserverdisconnected(e)
        .catch(error => {
          console.log("Error: ", error);
        });
    });
  }

  async gattserverdisconnected(e) {
    console.log('Reconnecting');
    this.server = await this.device.gatt.connect();
    this.service = await this.server.getPrimaryService(this.serviceId);
    this.characteristic = await this.service.getCharacteristic(this.characteristicId);
    if(this.listening) {
      this.listening = false;
      this.listen();
    }
  }
}

export class BlePowerCadenceMeter extends BleMeter {
  constructor (device, server, service, characteristic) {
    super(device, server, service, characteristic);

    this.serviceId = 0x1818;
    this.characteristicId = 0x2A63;
    this.parser = new CyclingPowerMeasurementParser();

    this.lastCrankRevolutions = 0;
    this.lastCrankTime = 0;
    this.lastWheelRevolutions = 0;
    this.lastWheelTime = 0;
  }

  listen() {
    if(!this.listening) {
      this.characteristic.addEventListener('characteristicvaluechanged', event => {
        let data = this.parser.getData(event.target.value);
        let power = data['instantaneous_power'];
        let crankRevolutions = data['cumulative_crank_revolutions'];
        let crankTime = data['last_crank_event_time'];
        let wheelRevolutions = data['cumulative_wheel_revolutions'];
        let wheelTime = data['last_wheel_event_time'];

        /* Crank Calc */
        if(this.lastCrankTime > crankTime) {
          this.lastCrankTime = this.lastCrankTime - 65536;
        }
        if(this.lastCrankRevolutions > crankRevolutions) {
          this.lastCrankRevolutions = this.lastCrankRevolutions - 65536;
        }

        let revs = crankRevolutions - this.lastCrankRevolutions;
        let duration = (crankTime - this.lastCrankTime) / 1024;
        let rpm = 0;
        if(duration > 0) {
          rpm = (revs / duration) * 60;
        }

        this.lastCrankRevolutions = crankRevolutions;
        this.lastCrankTime = crankTime;
        /* End Crank Calc */

        /* Wheel Calc */
        if(wheelRevolutions !== undefined && wheelTime !== undefined) {
            if(this.lastWheelTime > wheelTime) {
                this.lastWheelTime = this.lastWheelTime - 65536;
            }
            if(this.lastWheelRevolutions > wheelRevolutions) {
                this.lastWheelRevolutions = this.lastWheelRevolutions - 65536;
            }

            let wheelRevs = wheelRevolutions - this.lastWheelRevolutions;
            let wheelDuration = (wheelTime - this.lastWheelTime) / 1024;
            let wheelRpm = 0;
            if(wheelDuration > 0) {
                wheelRpm = (wheelRevs / wheelDuration) * 60;
            }

            this.lastWheelRevolutions = wheelRevolutions;
            this.lastWheelTime = wheelTime;

            this.dispatch('wheelrpm', wheelRpm);
        }
        /* End Wheel Calc */

        this.dispatch('power', power);
        this.dispatch('cadence', rpm);
        this.clearValueOnTimeout(['power', 'cadence', 'wheelrpm']);
      });
      this.characteristic.startNotifications();
      this.listening = true;
    }
  }

}

export class BlePowerMeter extends BleMeter {
  constructor (device, server, service, characteristic) {
    super(device, server, service, characteristic);

    this.serviceId = 0x1818;
    this.characteristicId = 0x2A63;
    this.parser = new CyclingPowerMeasurementParser();
  }

  listen() {
    if(!this.listening) {
      this.characteristic.addEventListener('characteristicvaluechanged', event => {
        let data = this.parser.getData(event.target.value);
        let power = data['instantaneous_power'];
        this.dispatch('power', power);
        this.clearValueOnTimeout('power');
      });
      this.characteristic.startNotifications();
      this.listening = true;
    }
  }

}

export class BleCadenceMeter extends BleMeter  {
  constructor (device, server, service, characteristic) {
    super(device, server, service, characteristic);

    this.serviceId = 0x1816;
    this.characteristicId = 0x2A5B;
    this.parser = new CyclingSpeedCadenceMeasurementParser();

    this.lastCrankRevolutions = 0;
    this.lastCrankTime = 0;
    this.lastWheelRevolutions = 0;
    this.lastWheelTime = 0;
  }

  listen() {
    if(!this.listening) {
      this.characteristic.addEventListener('characteristicvaluechanged', event => {
        let data = this.parser.getData(event.target.value);
        let crankRevolutions = data['cumulative_crank_revolutions'];
        let crankTime = data['last_crank_event_time'];
        let wheelRevolutions = data['cumulative_wheel_revolutions'];
        let wheelTime = data['last_wheel_event_time'];

        if(crankRevolutions !== undefined && crankTime !== undefined) {
            if(this.lastCrankTime > crankTime) {
                this.lastCrankTime = this.lastCrankTime - 65536;
            }
            if(this.lastCrankRevolutions > crankRevolutions) {
                this.lastCrankRevolutions = this.lastCrankRevolutions - 65536;
            }

            let revs = crankRevolutions - this.lastCrankRevolutions;
            let duration = (crankTime - this.lastCrankTime) / 1024;
            let rpm = 0;
            if(duration > 0) {
                rpm = (revs / duration) * 60;
            }

            this.lastCrankRevolutions = crankRevolutions;
            this.lastCrankTime = crankTime;

            this.dispatch('cadence', rpm);
        }

        if(wheelRevolutions !== undefined && wheelTime !== undefined) {
            if(this.lastWheelTime > wheelTime) {
                this.lastWheelTime = this.lastWheelTime - 65536;
            }
            if(this.lastWheelRevolutions > wheelRevolutions) {
                this.lastWheelRevolutions = this.lastWheelRevolutions - 65536;
            }

            let wheelRevs = wheelRevolutions - this.lastWheelRevolutions;
            let wheelDuration = (wheelTime - this.lastWheelTime) / 1024;
            let wheelRpm = 0;
            if(wheelDuration > 0) {
                wheelRpm = (wheelRevs / wheelDuration) * 60;
            }

            this.lastWheelRevolutions = wheelRevolutions;
            this.lastWheelTime = wheelTime;

            this.dispatch('wheelrpm', wheelRpm);
        }

        this.clearValueOnTimeout(['cadence', 'wheelrpm']);
      });
      this.characteristic.startNotifications();
      this.listening = true;
    }
  }

}

export class BleHRMeter extends BleMeter {
  constructor (device, server, service, characteristic) {
    super(device, server, service, characteristic);

    this.serviceId = 0x180D;
    this.characteristicId = 0x2A37;
  }

  listen() {
    if(!this.listening) {
      this.characteristic.addEventListener('characteristicvaluechanged', event => {
        let hr = event.target.value.getUint8(1);
        this.dispatch('hr', hr);
        this.clearValueOnTimeout('hr');
      });
      this.characteristic.startNotifications();
      this.listening = true;
    }
  }

}

export class VirtualPowerMeter extends Meter {
  constructor () {
    super();
    this.listening = false;
    this.watts = 0;

    this.id = 'virtual';
    this.name = 'Virtual Power Meter';
  }

  listen() {
    if(!this.listening) {
      document.getElementById('ui-vpower-container').style.display = 'block';
      let $vpower = document.getElementById('vpower');
      $vpower.value = this.watts;
      $vpower.onchange = e => {
        this.watts = parseInt($vpower.value);
      };

      setInterval(() => {
        this.dispatch('power', this.watts);
      }, 750);

      this.listening = true;
    }
  }

}

export class CycleopsMagnetoPowerCurve extends Meter {
    constructor () {
        super();
        this.listening = false;

        this.id = 'cycleopsmagnetopowercurve';
        this.name = 'Cycleops Magneto Power Curve';
    }

    listen(opts) {
      if(!this.listening) {
        let cadenceMeter = opts.cadenceMeter;
        if(cadenceMeter !== undefined) {
            cadenceMeter.addListener('wheelrpm', (wheelrpm) => {
                // Hardcoded to 28mm tires
                let wheelCircumference = 2136;
                let kph = (wheelCircumference * wheelrpm * 60) / 1000000;
                let watts = this.Exponential_DoubleAsymptoticExponentialB_model(kph);
                if(watts < 0) {
                    watts = 0;
                }
                this.dispatch('power', watts);
                this.clearValueOnTimeout('power');
            });

            this.listening = true;
        }
      }
    }

    // Derived from data found here:
    //    https://machiine.com/2018/how-accurate-is-zwifts-power-estimate-for-classic-trainers/
    // Curve fitting utilizing:
    //    http://zunzun.com/
    Exponential_DoubleAsymptoticExponentialB_model(x_in) {
        let temp;
        temp = 0.0;

        // coefficients
        let a = -4.2557472799016870E+02;
        let b = 1.6719781580876170E-02;
        let c = -7.3525587442334214E+01;
        let d = -1.3986922573862917E-01;

        temp = a * (1.0 - Math.exp(b * x_in)) + c * (1.0 - Math.exp(d * x_in));
        return temp;
    }

  }

export class AntMeter extends Meter {
  constructor (type, manId, modelNum, deviceId) {
    super();

    this.type = type;
    this.manId = manId;
    this.modelNum = modelNum;
    this.deviceId = deviceId;

    this.setName();
  }

  listen() {}

  setName() {
    let nameManufacturer = 'Unknown';
    if(this.manId in ant_manufacturers) {
      nameManufacturer = ant_manufacturers[this.manId]
        .split('_')
        .map(word => {
            return word[0].toUpperCase() + word.substr(1);
        })
        .join(' ');
    }

    this.name = nameManufacturer + ' - ' + this.deviceId;
  }
}

export class AntPowerMeter extends AntMeter {
  constructor (id, type, manId, modelNum, deviceId) {
    super(type, manId, modelNum, deviceId);

    this.id = id;
  }

  antMessage(message) {
    let power = message.Power;
    if(power !== undefined) {
      this.dispatch('power', power);
      this.clearValueOnTimeout('power');
    }
  }
}

export class AntCadenceMeter extends AntMeter  {
  constructor (id, type, manId, modelNum, deviceId) {
    super(type, manId, modelNum, deviceId);

    this.id = id;

    this.lastWheelRevolutions = 0;
    this.lastWheelTime = 0;
  }

  antMessage(message) {
    let cadence = undefined;
    if(message.Cadence !== undefined) {
      cadence = message.Cadence;
    }
    if(message.CalculatedCadence !== undefined) {
      cadence = message.CalculatedCadence;
    }
    if(cadence !== undefined) {
      this.dispatch('cadence', cadence);
    }

    let wheelTime = message.SpeedEventTime;
    let wheelRevolutions = message.CumulativeSpeedRevolutionCount;
    if(wheelRevolutions !== undefined && wheelTime !== undefined && this.lastWheelTime !== wheelTime) {
        if(this.lastWheelTime > wheelTime) {
            this.lastWheelTime = this.lastWheelTime - 65536;
        }
        if(this.lastWheelRevolutions > wheelRevolutions) {
            this.lastWheelRevolutions = this.lastWheelRevolutions - 65536;
        }

        let wheelRevs = wheelRevolutions - this.lastWheelRevolutions;
        let wheelDuration = (wheelTime - this.lastWheelTime) / 1024;
        let wheelRpm = 0;
        if(wheelDuration > 0) {
            wheelRpm = (wheelRevs / wheelDuration) * 60;
        }

        this.lastWheelRevolutions = wheelRevolutions;
        this.lastWheelTime = wheelTime;

        this.dispatch('wheelrpm', wheelRpm);
    }

    this.clearValueOnTimeout(['cadence', 'wheelrpm']);
  }
}

export class AntHRMeter extends AntMeter {
  constructor (id, type, manId, modelNum, deviceId) {
    super(type, manId, modelNum, deviceId);

    this.id = id;
  }

  antMessage(message) {
    let hr = message.ComputedHeartRate;
    if(hr !== undefined) {
      this.dispatch('hr', hr);
      this.clearValueOnTimeout('hr');
    }
  }
}

export class AntMeterLocator {
  constructor (url='http://localhost:8000/') {
    this.url = url;
    this.listeners = {};
    this.devicesByType = {};
    this.devices = {};

    if(!this.url.startsWith('http')) {
      this.url = 'http://' + this.url;
    }

    if(!this.url.endsWith('/')) {
      this.url = this.url + '/';
    }

    this.meterClasses = {
      'hr': AntHRMeter,
      'bike_power': AntPowerMeter,
      'speed_cadence': AntCadenceMeter,
    }
  }

  addListener(type, callback) {
    if(!(type in this.listeners)) {
      this.listeners[type] = [];
    }

    this.listeners[type].push(callback);
  }

  dispatch(type, value) {
    if(!(type in this.listeners)) {
      this.listeners[type] = [];
    }

    for(let l of this.listeners[type]) {
      l(value);
    }
  }

  scan() {
    let client = new faye.Client(this.url, {timeout: 120, retry: 10});
    client.on('transport:down', (error) => {
      this.dispatch('error', error);
    });

    client.subscribe('/*', message => {
      const msg = JSON.parse(message.text);
      let msgTypes = [msg.type];
      if(msg.type === 'bike_power' && (msg.Cadence || msg.CalculatedCadence)) {
        msgTypes.push('speed_cadence');
      }

      for(let type of msgTypes) {
        let meterId = type + msg.DeviceID;
        if(!(meterId in this.devicesByType) && type in this.meterClasses) {
          let meter = new this.meterClasses[type](meterId, type, msg.ManId, msg.ModelNum, msg.DeviceID);
          if(!(msg.DeviceID in this.devices)) {
            this.devices[msg.DeviceID] = [];
          }
          this.devices[msg.DeviceID].push(meter);
          this.devicesByType[meterId] = meter;
          this.dispatch(type, meter);
        }
      }

      if(msg.DeviceID in this.devices) {
        for(let meter of this.devices[msg.DeviceID]) {
          meter.antMessage(msg);
        }
      }

      if(msg.ManId !== undefined || msg.ModelNum !== undefined) {
        if(msg.DeviceID in this.devices) {
          for(let meter of this.devices[msg.DeviceID]) {
            let nameChange = false;
            if(msg.ManId !== undefined && msg.ManId !== meter.manId) {
              meter.manId = msg.ManId;
              nameChange = true;
            }
            if(msg.ModelNum !== undefined && msg.ModelNum !== meter.modelNum) {
              meter.modelNum = msg.ModelNum;
              nameChange = true;
            }

            if(nameChange) {
              meter.setName();
              this.dispatch('namechange', meter);
            }
          }
        }
      }
    });
  }
}

//
//  Meter for BH Fitness BladeZ Indoor Cycling bikes that support a Class Bluetooth wireless connection.  These
//  bikes use the Serial Port Profile of the classic bluetooth spec. that be read and written to via the Web
//  Serial API ( https://codelabs.developers.google.com/codelabs/web-serial/ ) and
//  ( https://wicg.github.io/serial/ ).  This code has only been tested with a BladeZ r500i.
//
export class BHBladeZBikeMeter extends Meter {
    constructor (port) {
        super();

        this.port = port;
        this.name = 'BH BladeZ Bike Meter';
        this.id = 'BHBladeZBikeMeter';
        this.listening = false;

        this.inputStream = this.port.readable;
        this.reader = this.inputStream.getReader();

        this.outputStream = this.port.writable;

        this.initCommandsRaw = [ [ 85, 12, 1, -1 ], [ 85, -69, 1, -1 ], [ 85, 36, 1, -1 ], [ 85, 37, 1, -1 ], [ 85, 38, 1, -1 ], [ 85, 39, 1, -1 ], [ 85, 2, 1, -1 ], [ 85, 3, 1, -1 ], [ 85, 4, 1, -1 ], [ 85, 6, 1, -1 ], [ 85, 31, 1, -1 ], [ 85, -96, 1, -1 ], [ 85, -80, 1, -1 ], [ 85, -78, 1, -1 ], [ 85, -77, 1, -1 ], [ 85, -76, 1, -1 ], [ 85, -75, 1, -1 ], [ 85, -74, 1, -1 ], [ 85, -73, 1, -1 ], [ 85, -72, 1, -1 ], [ 85, -71, 1, -1 ], [ 85, -70, 1, -1 ], [ 85, 11, 1, -1 ], [ 85, 24, 1, -1 ], [ 85, 25, 1, -1 ], [ 85, 26, 1, -1 ], [ 85, 27, 1, -1 ] ];
        this.initCommands = [];

        this.keepAliveCommandRaw = [ 85, 23, 1, 1 ];
        this.keepAliveCommand = new Int8Array(this.keepAliveCommandRaw.length);

        this.startCommandRaw = [ 85, 10, 1, 1 ];
        this.startCommand = new Int8Array(this.startCommandRaw.length);

        this.setinclineCommandRaw = [ 85, 17, 1, 15 ];
        this.setinclineCommand = new Int8Array(this.setinclineCommandRaw.length);

        this.resetCommandRaw = [ 85, 10, 1, 2 ];
        this.resetCommand = new Int8Array(this.resetCommandRaw.length);

        this.setUserDataCommandRaw = [ 85, 1, 6, 35, 0, 250, 0, 74, 0];
        this.setUserDataCommand = new Int8Array(this.setUserDataCommandRaw.length);

        this.setActionModeCommandRaw = [ 85, 21, 1, 0 ];
        this.setActionModeCommand = new Int8Array(this.setActionModeCommandRaw.length);

        this.queryPulseTypeCommandRaw = [ 85, 7, 1, -1 ];
        this.queryPulseTypeCommand = new Int8Array(this.queryPulseTypeCommandRaw.length);
    }

    listen() {
        if(!this.listening) {
            this.listening = true;
            this.initializeDevice().catch(console.error);
        }
    }

    async initializeDevice() {
        this.initializeCommands();

        this.readLoop().catch(console.error);

        for(let c of this.initCommands) {
            await this.writeToStream(c);
        }

        await timeout(1000);

        await this.writeToStream(this.keepAliveCommand);

        await timeout(5000);

        await this.writeToStream(this.resetCommand);

        await timeout(500);

        await this.writeToStream(this.setUserDataCommand);

        await timeout(500);

        await this.writeToStream(this.setActionModeCommand);

        await timeout(500);

        await this.writeToStream(this.setinclineCommand);

        await timeout(500);

        await this.writeToStream(this.startCommand);

        await timeout(500);

        await this.writeToStream(this.queryPulseTypeCommand);

        await timeout(1000);

        this.maintainKeepAlive().catch(console.error);
    }

    initializeCommands() {
        for(let commandRaw of this.initCommandsRaw) {
            let command = new Int8Array(commandRaw.length);
            commandRaw.forEach((b,i) => {
                command[i] = b;
            });
            this.initCommands.push(command);
        }
        this.initCommandsRaw = null;

        this.keepAliveCommandRaw.forEach((b,i) => {
            this.keepAliveCommand[i] = b;
        });
        this.keepAliveCommandRaw = null;

        this.startCommandRaw.forEach((b,i) => {
            this.startCommand[i] = b;
        });
        this.startCommandRaw = null;

        this.setinclineCommandRaw.forEach((b,i) => {
            this.setinclineCommand[i] = b;
        });
        this.setinclineCommandRaw = null;

        this.resetCommandRaw.forEach((b,i) => {
            this.resetCommand[i] = b;
        });
        this.resetCommandRaw = null;

        this.setUserDataCommandRaw.forEach((b,i) => {
            this.setUserDataCommand[i] = b;
        });
        this.setUserDataCommandRaw = null;

        this.setActionModeCommandRaw.forEach((b,i) => {
            this.setActionModeCommand[i] = b;
        });
        this.setActionModeCommandRaw = null;

        this.queryPulseTypeCommandRaw.forEach((b,i) => {
            this.queryPulseTypeCommand[i] = b;
        });
        this.queryPulseTypeCommandRaw = null;
    }

    async writeToStream(...chunks) {
        const writer = this.outputStream.getWriter();
        for(let chunk of chunks) {
          await writer.write(chunk);
        }
        writer.releaseLock();
    }

    async maintainKeepAlive() {
        while (true) {
            await timeout(5000);
            await this.writeToStream(this.keepAliveCommand);
        }
    }

    async readLoop() {
        while (true) {
            const { value, done } = await this.reader.read();
            if (value) {
                let length = value.length;
                let str = "";
                for(let v of value) {
                    v = v.toString(16);
                    if(v.length === 1) {
                        v = "0"+v;
                    }
                    str = str + v;
                }

                let position = str.indexOf('550d');
                if(position !== -1) {
                    let offset = position/2;
                    if(length >= offset + 16) {
                        offset += 3;
                        let ab = value.buffer.slice(offset);
                        const vals8 = new Int8Array(ab);
                        const level = vals8[8];
                        const rpm = vals8[10] & 0xFF;
                        const cal = (new DataView(ab.slice(4,6))).getInt16(0, false);
                        const time = (new DataView(ab.slice(0,2))).getInt16(0, false);
                        const watts = (new DataView(ab.slice(11,13))).getInt16(0, false);

                        this.dispatch('power', watts);
                        this.dispatch('cadence', rpm);
                        this.clearValueOnTimeout(['power', 'cadence']);
                    }
                }
            }
            if (done) {
                this.reader.releaseLock();
                break;
            }
        }
    }
}