text:
/// <reference path="../../localtypings/pxtarget.d.ts" />

import * as React from "react"
import * as data from "./data"
import * as editor from "./toolboxeditor"
import * as sui from "./sui"
import * as core from "./core"

import Util = pxt.Util;

export const enum CategoryNameID {
    Loops = "loops",
    Logic = "logic",
    Variables = "variables",
    Maths = "Math",
    Functions = "functions",
    Arrays = "arrays",
    Text = "text",
    Extensions = "addpackage"
}

// this is a supertype of pxtc.SymbolInfo (see partitionBlocks)
export interface BlockDefinition {
    qName?: string;
    name: string;
    pyName?: string;
    namespace?: string;
    type?: string;
    snippet?: string;
    snippetName?: string;
    pySnippet?: string;
    pySnippetName?: string;
    snippetOnly?: boolean;
    attributes: {
        block?: string;
        blockId?: string;
        blockNamespace?: string;
        color?: string;
        weight?: number;
        advanced?: boolean;
        jsDoc?: string;
        blockBuiltin?: boolean;
        deprecated?: boolean;
        blockHidden?: boolean;
        group?: string;
        subcategory?: string;
        topblockWeight?: number;
    };
    retType?: string;
    blockXml?: string;
    builtinBlock?: boolean;
    builtinField?: [string, string];
}

export interface ButtonDefinition {
    name: string;
    type: "button";
    attributes: {
        blockId?: string;
        label?: string;
        weight?: number;
    }
    callback?: () => void;
}

export interface BuiltinCategoryDefinition {
    name: string;
    nameid: string;
    blocks: (BlockDefinition | ButtonDefinition)[];
    groups?: string[];
    attributes: pxtc.CommentAttrs;
    removed?: boolean;
    custom?: boolean; // Only add blocks defined in .blocks and don't query nsMap for more
    customClick?: (theEditor: editor.ToolboxEditor) => boolean; // custom handler
}

export interface ToolboxProps {
    editorname: string;
    parent: editor.ToolboxEditor;
}

export interface ToolboxState {
    showAdvanced?: boolean;
    visible?: boolean;
    loading?: boolean;
    selectedItem?: string;
    expandedItem?: string;
    height?: number;

    categories?: ToolboxCategory[];
    showSearchBox?: boolean;

    hasSearch?: boolean;
    focusSearch?: boolean;
    searchBlocks?: pxtc.service.SearchInfo[]; // block ids

    hasError?: boolean;
}

export class Toolbox extends data.Component<ToolboxProps, ToolboxState> {

    private rootElement: HTMLElement;

    private selectedItem: CategoryItem;
    private selectedIndex: number;
    private items: ToolboxCategory[];

    constructor(props: ToolboxProps) {
        super(props);
        this.state = {
            categories: [],
            visible: false,
            loading: false,
            showAdvanced: false
        }

        this.setSelection = this.setSelection.bind(this);
        this.advancedClicked = this.advancedClicked.bind(this);
        this.recipesClicked = this.recipesClicked.bind(this);
        this.recoverToolbox = this.recoverToolbox.bind(this);
    }

    getElement() {
        return this.rootElement;
    }

    hide() {
        this.setState({ visible: false })
    }

    showLoading() {
        this.setState({ visible: true, loading: true });
    }

    show() {
        this.setState({ visible: true })
    }

    setSelectedItem(item: CategoryItem) {
        this.selectedItem = item;
    }

    setPreviousItem() {
        if (this.selectedIndex > 0) {
            const newIndex = --this.selectedIndex;
            // Check if the previous item has a subcategory
            let previousItem = this.items[newIndex];
            this.setSelection(previousItem, newIndex);
        } else if (this.state.showSearchBox) {
            // Focus the search box if it exists
            const searchBox = this.refs.searchbox as ToolboxSearch;
            if (searchBox) searchBox.focus();
        }
    }

    setNextItem() {
        if (this.items.length - 1 > this.selectedIndex) {
            const newIndex = ++this.selectedIndex;
            this.setSelection(this.items[newIndex], newIndex);
        }
    }

    setSearch() {
        // Focus the search box if it exists
        const searchBox = this.refs.searchbox as ToolboxSearch;
        if (searchBox) searchBox.focus();
    }

    clear() {
        this.clearSelection();
        this.selectedIndex = 0;
        this.selectedTreeRow = undefined;
    }

    clearSelection() {
        this.setState({ selectedItem: undefined, expandedItem: undefined, focusSearch: false })
    }

    clearSearch() {
        this.setState({ hasSearch: false, searchBlocks: undefined, focusSearch: false });
    }

    setSelection(treeRow: ToolboxCategory, index: number, force?: boolean) {
        const { editorname, parent } = this.props;
        const { nameid, subns, customClick } = treeRow;

        pxt.tickEvent(`${editorname}.toolbox.click`, undefined, { interactiveConsent: true });

        let id = subns ? nameid + subns : nameid;

        if (this.state.selectedItem == id && !force) {
            this.clearSelection();

            // Hide flyout
            this.closeFlyout();
        } else {
            let handled = false;
            if (customClick) {
                handled = customClick(parent);
                if (handled) return;
            }

            if (!handled) {
                this.setState({ selectedItem: id, expandedItem: nameid, focusSearch: false })
                this.selectedIndex = index;
                this.selectedTreeRow = treeRow;
                if (treeRow.advanced && !this.state.showAdvanced) this.showAdvanced();

                if (!customClick) {
                    // Show flyout
                    this.showFlyout(treeRow);
                }
            }
        }
    }

    focus() {
        if (!this.rootElement) return;
        if (this.selectedItem && this.selectedItem.getTreeRow()) {
            // Focus the selected item
            const selectedItem = this.selectedItem.props.treeRow;
            const selectedItemIndex = this.items.indexOf(selectedItem);
            this.setSelection(selectedItem, selectedItemIndex, true);
        } else {
            // Focus first item in the toolbox
            this.selectFirstItem();
        }
    }

    selectFirstItem() {
        if (this.items[0]) {
            this.setSelection(this.items[0], 0, true);
        }
    }

    moveFocusToFlyout() {
        const { parent } = this.props;
        parent.moveFocusToFlyout();
    }

    componentDidUpdate(prevProps: ToolboxProps, prevState: ToolboxState) {
        if (prevState.visible != this.state.visible
            || prevState.loading != this.state.loading
            || prevState.showAdvanced != this.state.showAdvanced
            || this.state.expandedItem != prevState.expandedItem) {
            this.props.parent.resize();
        }
        if (this.state.hasSearch && this.state.searchBlocks != prevState.searchBlocks) {
            // Referesh search items
            this.refreshSearchItem();
        } else if (prevState.hasSearch && !this.state.hasSearch && this.state.selectedItem == 'search') {
            // No more search
            this.closeFlyout();
        }
    }

    componentDidCatch(error: any, info: any) {
        // Log what happened
        const { editorname } = this.props;
        pxt.tickEvent(`${editorname}.toolbox.crashed`, { error: error });

        // Update error state
        this.setState({ hasError: true });
    }

    recoverToolbox() {
        // Recover from above error state
        this.setState({ hasError: false });
    }

    advancedClicked() {
        const { editorname } = this.props;
        pxt.tickEvent(`${editorname}.advanced`, undefined, { interactiveConsent: true });
        this.showAdvanced();
    }

    recipesClicked() {
        const { editorname } = this.props;
        pxt.tickEvent(`${editorname}.recipes`);
        this.props.parent.parent.showRecipesDialog();
    }

    showAdvanced() {
        const { parent } = this.props;
        if (this.selectedItem && this.selectedItem.props.treeRow
            && this.selectedItem.props.treeRow.advanced) {
            this.clear();
            this.closeFlyout();
        }
        this.setState({ showAdvanced: !this.state.showAdvanced });
    }

    getSearchBlocks(): BlockDefinition[] {
        const { parent } = this.props;
        const { searchBlocks } = this.state;
        return searchBlocks.map(searchResult => {
            return {
                name: searchResult.qName,
                attributes: {
                    blockId: searchResult.id
                },
                builtinBlock: searchResult.builtinBlock,
                builtinField: searchResult.field
            }
        });
    }

    refreshSelection() {
        const { parent } = this.props;
        if (!this.state.selectedItem || !this.selectedTreeRow) return;
        if (this.selectedTreeRow.customClick) {
            this.selectedTreeRow.customClick(parent);
        } else {
            this.showFlyout(this.selectedTreeRow);
        }
    }

    refreshSearchItem() {
        const searchTreeRow = ToolboxSearch.getSearchTreeRow();
        this.showFlyout(searchTreeRow);
    }

    private selectedTreeRow: ToolboxCategory;
    private showFlyout(treeRow: ToolboxCategory) {
        const { parent } = this.props;
        // const t0 = performance.now();
        parent.showFlyout(treeRow);
        // const t1 = performance.now();
        // pxt.debug("perf: call to showFlyout took " + (t1 - t0) + " milliseconds.");
    }

    closeFlyout() {
        const { parent } = this.props;
        parent.closeFlyout();
    }

    hasAdvancedCategories() {
        const { categories } = this.state;
        return categories.some(category => category.advanced);
    }

    getNonAdvancedCategories() {
        const { categories } = this.state;
        return categories.filter(category => !category.advanced);
    }

    getAdvancedCategories() {
        const { categories } = this.state;
        return categories.filter(category => category.advanced);
    }

    private getAllCategoriesList(visibleOnly?: boolean): ToolboxCategory[] {
        const { categories, hasSearch, expandedItem } = this.state;
        const categoriesList: ToolboxCategory[] = [];
        if (hasSearch) categoriesList.push(ToolboxSearch.getSearchTreeRow());
        categories.forEach(category => {
            categoriesList.push(category);
            if (category.subcategories &&
                (!visibleOnly || visibleOnly && category.nameid == expandedItem)) {
                category.subcategories.forEach(subcategory => {
                    categoriesList.push(subcategory);
                })
            }
        })
        return categoriesList;
    }

    shouldComponentUpdate(nextProps: ToolboxProps, nextState: ToolboxState) {
        if (this.state != nextState) return true;
        return false;
    }

    handleRootElementRef = (c: HTMLDivElement) => {
        this.rootElement = c;
    }

    isRtl() {
        const { editorname } = this.props;
        return editorname == 'monaco' ? false : Util.isUserLanguageRtl();
    }

    renderCore() {
        const { editorname, parent } = this.props;
        const { showAdvanced, visible, loading, selectedItem, expandedItem, hasSearch, showSearchBox, hasError } = this.state;
        if (!visible) return

        const theme = pxt.appTarget.appTheme;
        const tutorialOptions = parent.parent.state.tutorialOptions;
        const inTutorial = !!tutorialOptions && !!tutorialOptions.tutorial
        const hasTopBlocks = !!theme.topBlocks && !inTutorial;

        if (loading || hasError) return

            {loading ?

 : undefined}
            {hasError ?

                {lf("Toolbox crashed..")}
                <sui.Button icon='refresh' onClick={this.recoverToolbox}
                    text={lf("Reload")} className='fluid' />

 : undefined}

;

        const hasAdvanced = this.hasAdvancedCategories();

        let nonAdvancedCategories = this.getNonAdvancedCategories();
        const advancedCategories = hasAdvanced ? this.getAdvancedCategories() : [];

        this.items = this.getAllCategoriesList();

        const hasRecipes = !!theme.recipes && !inTutorial && this.items.length > 0;

        const searchTreeRow = ToolboxSearch.getSearchTreeRow();
        const topBlocksTreeRow = {
            nameid: 'topblocks',
            name: lf("{id:category}Basic"),
            color: pxt.toolbox.getNamespaceColor('topblocks'),
            icon: pxt.toolbox.getNamespaceIcon('topblocks')
        };

        const appTheme = pxt.appTarget.appTheme;
        const classes = sui.cx([
            'pxtToolbox',
            appTheme.invertedToolbox ? 'invertedToolbox' : '',
            appTheme.coloredToolbox ? 'coloredToolbox' : ''
        ])

        let index = 0;
        return <div ref={this.handleRootElementRef} className={classes} id={`${editorname}EditorToolbox`}>
            <ToolboxStyle categories={this.items} />
            {showSearchBox ? <ToolboxSearch ref="searchbox" parent={parent} toolbox={this} editorname={editorname} /> : undefined}

                    {hasSearch ? <CategoryItem key={"search"} toolbox={this} index={index++} selected={selectedItem == "search"} treeRow={searchTreeRow} onCategoryClick={this.setSelection} /> : undefined}
                    {hasTopBlocks ? <CategoryItem key={"topblocks"} toolbox={this} selected={selectedItem == "topblocks"} treeRow={topBlocksTreeRow} onCategoryClick={this.setSelection} /> : undefined}
                    {nonAdvancedCategories.map((treeRow) => (
                        <CategoryItem key={treeRow.nameid} toolbox={this} index={index++} selected={selectedItem == treeRow.nameid} childrenVisible={expandedItem == treeRow.nameid} treeRow={treeRow} onCategoryClick={this.setSelection}>
                            {treeRow.subcategories ? treeRow.subcategories.map((subTreeRow) => (
                                <CategoryItem key={subTreeRow.nameid + subTreeRow.subns} index={index++} toolbox={this} selected={selectedItem == (subTreeRow.nameid + subTreeRow.subns)} treeRow={subTreeRow} onCategoryClick={this.setSelection} />
                            )) : undefined}
                        </CategoryItem>
                    ))}
                    {hasAdvanced || hasRecipes ? <TreeSeparator key="advancedseparator" /> : undefined}
                    {hasRecipes ? <CategoryItem toolbox={this} treeRow={{ nameid: "", name: pxt.toolbox.recipesTitle(), color: pxt.toolbox.getNamespaceColor('recipes'), icon: pxt.toolbox.getNamespaceIcon('recipes') }} onCategoryClick={this.recipesClicked} /> : undefined}
                    {hasAdvanced ? <CategoryItem toolbox={this} treeRow={{ nameid: "", name: pxt.toolbox.advancedTitle(), color: pxt.toolbox.getNamespaceColor('advanced'), icon: pxt.toolbox.getNamespaceIcon(showAdvanced ? 'advancedexpanded' : 'advancedcollapsed') }} onCategoryClick={this.advancedClicked} /> : undefined}
                    {showAdvanced ? advancedCategories.map((treeRow) => (
                        <CategoryItem key={treeRow.nameid} toolbox={this} index={index++} selected={selectedItem == treeRow.nameid} childrenVisible={expandedItem == treeRow.nameid} treeRow={treeRow} onCategoryClick={this.setSelection}>
                            {treeRow.subcategories ? treeRow.subcategories.map((subTreeRow) => (
                                <CategoryItem key={subTreeRow.nameid} toolbox={this} index={index++} selected={selectedItem == (subTreeRow.nameid + subTreeRow.subns)} treeRow={subTreeRow} onCategoryClick={this.setSelection} />
                            )) : undefined}
                        </CategoryItem>
                    )) : undefined}

    }
}

export interface CategoryItemProps extends TreeRowProps {
    toolbox: Toolbox;
    childrenVisible?: boolean;
    onCategoryClick?: (treeRow: ToolboxCategory, index: number) => void;
    index?: number;
}

export interface CategoryItemState {
    selected?: boolean;
}

export class CategoryItem extends data.Component<CategoryItemProps, CategoryItemState> {
    private treeRowElement: TreeRow;

    constructor(props: CategoryItemProps) {
        super(props);
        this.state = {
            selected: props.selected
        }

        this.handleClick = this.handleClick.bind(this);
        this.handleKeyDown = this.handleKeyDown.bind(this);
    }

    getTreeRow() {
        return this.treeRowElement;
    }

    componentWillReceiveProps(nextProps: CategoryItemProps) {
        const newState: CategoryItemState = {};
        if (nextProps.selected != undefined) {
            newState.selected = nextProps.selected;
        }
        if (Object.keys(newState).length > 0) this.setState(newState)
    }

    componentDidUpdate(prevProps: CategoryItemProps, prevState: CategoryItemState) {
        const { toolbox } = this.props;
        if (this.state.selected) {
            this.props.toolbox.setSelectedItem(this);
            if (!toolbox.state.focusSearch) this.focusElement();
        }
    }

    focusElement() {
        this.treeRowElement.focus();
    }

    handleClick(e: React.MouseEvent<any>) {
        const { treeRow, onCategoryClick, index } = this.props;
        if (onCategoryClick) onCategoryClick(treeRow, index);

        e.preventDefault();
        e.stopPropagation();
    }

    handleKeyDown(e: React.KeyboardEvent<HTMLElement>) {
        const { toolbox, childrenVisible } = this.props;
        const isRtl = Util.isUserLanguageRtl();

        const charCode = core.keyCodeFromEvent(e);
        if (charCode == 40) { //  DOWN
            this.nextItem();
        } else if (charCode == 38) { // UP
            this.previousItem();
        } else if ((charCode == 39 && !isRtl) || (charCode == 37 && isRtl)) { // (LEFT & LTR) || (RIGHT & RTL)
            // Focus inside flyout
            toolbox.moveFocusToFlyout();
        } else if (charCode == 27) { // ESCAPE
            // Close the flyout
            toolbox.closeFlyout();
        } else if (charCode == core.ENTER_KEY || charCode == core.SPACE_KEY) {
            sui.fireClickOnEnter.call(this, e);
        } else if (charCode == core.TAB_KEY
            || charCode == 37 /* Left arrow key */
            || charCode == 39 /* Left arrow key */
            || charCode == 17 /* Ctrl Key */
            || charCode == 16 /* Shift Key */
            || charCode == 91 /* Cmd Key */) {
            // Escape tab and shift key
        } else {
            toolbox.setSearch();
        }
    }

    previousItem() {
        const { toolbox, childrenVisible } = this.props;
        const editorname = toolbox.props.editorname;

        pxt.tickEvent(`${editorname}.toolbox.keyboard.prev"`, undefined, { interactiveConsent: true });
        toolbox.setPreviousItem();
    }

    nextItem() {
        const { toolbox, childrenVisible } = this.props;
        const editorname = toolbox.props.editorname;

        pxt.tickEvent(`${editorname}.toolbox.keyboard.next"`, undefined, { interactiveConsent: true });
        toolbox.setNextItem();
    }

    handleTreeRowRef = (c: TreeRow) => {
        this.treeRowElement = c;
    }

    renderCore() {
        const { toolbox, childrenVisible } = this.props;
        const { selected } = this.state;

        return <TreeItem>
            <TreeRow ref={this.handleTreeRowRef} isRtl={toolbox.isRtl()} {...this.props} selected={selected}
                onClick={this.handleClick} onKeyDown={this.handleKeyDown} />
            <TreeGroup visible={childrenVisible}>
                {this.props.children}
            </TreeGroup>
        </TreeItem>
    }
}

export interface ToolboxCategory {
    nameid: string;
    subns?: string;

    name?: string;
    color?: string;
    icon?: string;

    groups?: string[];
    groupIcons?: string[];
    groupHelp?: string[];
    labelLineWidth?: string;

    blocks?: BlockDefinition[];
    subcategories?: ToolboxCategory[];

    customClick?: (theEditor: editor.ToolboxEditor) => boolean;
    advanced?: boolean; /*@internal*/
}

export interface TreeRowProps {
    treeRow: ToolboxCategory;
    onClick?: (e: React.MouseEvent<any>) => void;
    onKeyDown?: (e: React.KeyboardEvent<any>) => void;
    selected?: boolean;
    isRtl?: boolean;
}

export class TreeRow extends data.Component<TreeRowProps, {}> {

    private treeRow: HTMLElement;

    constructor(props: TreeRowProps) {
        super(props);
        this.state = {
        }

        this.onmouseenter = this.onmouseenter.bind(this);
        this.onmouseleave = this.onmouseleave.bind(this);
    }

    focus() {
        if (this.treeRow) this.treeRow.focus();
    }

    getProperties() {
        const { treeRow } = this.props;
        return treeRow;
    }

    onmouseenter() {
        const appTheme = pxt.appTarget.appTheme;
        const metaColor = this.getMetaColor();
        const invertedMultipler = appTheme.blocklyOptions
            && appTheme.blocklyOptions.toolboxOptions
            && appTheme.blocklyOptions.toolboxOptions.invertedMultiplier || 0.3;

        if (appTheme.invertedToolbox) {
            this.treeRow.style.backgroundColor = pxt.toolbox.fadeColor(metaColor || '#ddd', invertedMultipler, false);
        }
    }

    onmouseleave() {
        const appTheme = pxt.appTarget.appTheme;
        const metaColor = this.getMetaColor();
        if (appTheme.invertedToolbox) {
            this.treeRow.style.backgroundColor = (metaColor || '#ddd');
        }
    }

    getMetaColor() {
        const { color } = this.props.treeRow;
        return pxt.toolbox.convertColor(color) || pxt.toolbox.getNamespaceColor('default');
    }

    handleTreeRowRef = (c: HTMLDivElement) => {
        this.treeRow = c;
    }

    renderCore() {
        const { selected, onClick, onKeyDown, isRtl } = this.props;
        const { nameid, subns, name, icon } = this.props.treeRow;
        const appTheme = pxt.appTarget.appTheme;
        const metaColor = this.getMetaColor();

        const invertedMultipler = appTheme.blocklyOptions
            && appTheme.blocklyOptions.toolboxOptions
            && appTheme.blocklyOptions.toolboxOptions.invertedMultiplier || 0.3;

        let treeRowStyle: React.CSSProperties = {
            paddingLeft: '0px'
        }
        let treeRowClass = 'blocklyTreeRow';
        if (appTheme.invertedToolbox) {
            // Inverted toolbox
            treeRowStyle.backgroundColor = (metaColor || '#ddd');
            treeRowStyle.color = '#fff';
        } else {
            if (appTheme.coloredToolbox) {
                // Colored toolbox
                treeRowStyle.color = `${metaColor}`;
            }
            const border = `8px solid ${metaColor}`;
            if (isRtl) {
                treeRowStyle.borderRight = border;
            } else {
                treeRowStyle.borderLeft = border;
            }
        }

        // Selected
        if (selected) {
            treeRowClass += ' blocklyTreeSelected';
            if (appTheme.invertedToolbox) {
                treeRowStyle.backgroundColor = `${pxt.toolbox.fadeColor(metaColor, invertedMultipler, false)}`;
            } else {
                treeRowStyle.backgroundColor = (metaColor || '#ddd');
            }
            treeRowStyle.color = '#fff';
        }

        // Icon
        const iconClass = `blocklyTreeIcon${subns ? 'more' : icon ? (nameid || icon).toLowerCase() : 'Default'}`.replace(/\s/g, '');
        let iconContent = subns ? pxt.toolbox.getNamespaceIcon('more') : icon || pxt.toolbox.getNamespaceIcon('default');
        let iconImageStyle: JSX.Element;
        if (iconContent.length > 1) {
            // It's probably an image icon, and not an icon code
            iconImageStyle =
            iconContent = undefined;
        }

        return

            {iconImageStyle}
            <span style={{ display: 'inline-block' }} className={`blocklyTreeIcon ${iconClass}`} role="presentation">{iconContent}
            {name ? name : `${Util.capitalize(subns || nameid)}`}

    }
}

export class TreeSeparator extends data.Component<{}, {}> {
    renderCore() {
        return <TreeItem>

        </TreeItem>
    }
}

export interface TreeItemProps {
    selected?: boolean;
    children?: any;
}

export class TreeItem extends data.Component<TreeItemProps, {}> {
    renderCore() {
        const { selected } = this.props;
        return

            {this.props.children}

    }
}

export interface TreeGroupProps {
    visible?: boolean;
    children?: any;
}

export class TreeGroup extends data.Component<TreeGroupProps, {}> {
    renderCore() {
        const { visible } = this.props;
        return

            {this.props.children}

    }
}

export interface ToolboxSearchProps {
    parent: editor.ToolboxEditor;
    editorname: string;
    toolbox: Toolbox;
}

export interface ToolboxSearchState {
    searchAccessibilityLabel?: string;
}

export class ToolboxSearch extends data.Component<ToolboxSearchProps, ToolboxSearchState> {

    constructor(props: ToolboxSearchProps) {
        super(props);
        this.state = {
        }

        this.searchImmediate = this.searchImmediate.bind(this);
        this.handleKeyDown = this.handleKeyDown.bind(this);
        this.handleChange = this.handleChange.bind(this);
    }

    static getSearchTreeRow(): ToolboxCategory {
        return {
            nameid: 'search',
            name: lf("{id:category}Search"),
            color: pxt.toolbox.getNamespaceColor('search'),
            icon: pxt.toolbox.getNamespaceIcon('search')
        }
    }

    private search = Util.debounce(() => {
        this.searchImmediate();
    }, 300, false);

    handleChange() {
        this.search();
    }

    handleKeyDown(e: React.KeyboardEvent<any>) {
        const { toolbox } = this.props;
        let charCode = (typeof e.which == "number") ? e.which : e.keyCode
        if (charCode === 40 /* Down Key */) {
            // Select first item in the toolbox
            toolbox.selectFirstItem();
        }
    }

    focus() {
        (this.refs.searchInput as HTMLInputElement).focus();
    }

    searchImmediate() {
        const { parent, toolbox, editorname } = this.props;
        const searchTerm = (this.refs.searchInput as HTMLInputElement).value;

        let searchAccessibilityLabel = '';
        let hasSearch = false;

        pxt.tickEvent(`${editorname}.search`, undefined, { interactiveConsent: true });

        // Execute search
        parent.searchAsync(searchTerm)
            .done((blocks) => {
                if (blocks.length == 0) {
                    searchAccessibilityLabel = lf("No search results...");
                } else {
                    searchAccessibilityLabel = lf("{0} result matching '{1}'", blocks.length, searchTerm.toLowerCase());
                }
                hasSearch = searchTerm != '';

                const newState: ToolboxState = {};
                newState.hasSearch = hasSearch;
                newState.searchBlocks = blocks;
                newState.focusSearch = true;
                if (hasSearch) newState.selectedItem = 'search';
                toolbox.setState(newState);

                this.setState({ searchAccessibilityLabel: searchAccessibilityLabel });
            });
    }

    renderCore() {
        const { searchAccessibilityLabel } = this.state;
        return

                <input ref="searchInput" type="text" placeholder={lf("Search...")}
                    onFocus={this.searchImmediate} onKeyDown={this.handleKeyDown} onChange={this.handleChange}
                    id="blocklySearchInputField" className="blocklySearchInputField"
                    aria-label={lf("Search")}
                    autoComplete="off" autoCorrect="off" autoCapitalize="off" spellCheck={false} />

 {searchAccessibilityLabel}

    }
}

export class ToolboxTrashIcon extends data.Component<{}, {}> {

    renderCore() {
        return

    }
}

interface ToolboxStyleProps {
    categories: ToolboxCategory[];
}

export class ToolboxStyle extends data.Component<ToolboxStyleProps, {}> {
    renderCore() {
        const { categories } = this.props;
        // Add inline CSS for each category used so that the tutorial engine is able to render blocks
        // and assosiate them with a specific category
        return
    }
}


text:
import unittest
import slice_miseq
import os
import tempfile
import csv
import hyphy_handler
import shutil
OUT_DIR = os.path.dirname(os.path.realpath(__file__)) + os.sep + "out"

class TestSliceMiSeq(unittest.TestCase):

    def setUp(self):
        if not os.path.exists(OUT_DIR):
            shutil.rmtree(OUT_DIR)
            os.makedirs(OUT_DIR)

        self.windows = [
            # Window0:  all good
            {"syn_subs": 40.0, "nonsyn_subs":30.0, "exp_syn_subs":10.0, "exp_nonsyn_subs":10.0, "treelen":100.0, "reads":40, "startcdn":1, "endcdn":2},
             # Window1:  low nonsyn
            {"syn_subs": 40.0, "nonsyn_subs":0.4, "exp_syn_subs":10.0, "exp_nonsyn_subs":10.0, "treelen":100.0, "reads":40, "startcdn":2, "endcdn":4},
            # Window2:  all good
            {"syn_subs": 50.0, "nonsyn_subs":60.0, "exp_syn_subs":10.0, "exp_nonsyn_subs":10.0, "treelen":100.0, "reads":50, "startcdn":2, "endcdn":3},
            # Window3:  low syn
            {"syn_subs": 0.1, "nonsyn_subs":50.0, "exp_syn_subs":10.0, "exp_nonsyn_subs":10.0, "treelen":100.0, "reads":50, "startcdn":2, "endcdn":3}
        ]

        # Site-Window Coverage.  Each window repeats the same values for every site it covers
        # Site  0   1   2   3
        # Win0  *   *
        # Win1      *   *   *
        # Win2      *   *
        # Win3      *   *
        # The i'th index represents which windows cover the i'th site
        self.site_2_window = [[0], [0, 1, 2, 3], [1, 2, 3], [1]]

    def test_site_dnds_info_dnds(self):
        site_dnds_info = slice_miseq.SiteDnDsInfo()
        windows = self.windows

        for window in windows:
            site_dnds_info.add_window(
                dnds=(window["nonsyn_subs"]*window["exp_syn_subs"])/(window["syn_subs"]*window["exp_nonsyn_subs"]),
                dn_minus_ds=((window["nonsyn_subs"]/window["exp_nonsyn_subs"]) - (window["syn_subs"]/window["exp_syn_subs"]))/window["treelen"],
                reads=window["reads"],
                syn_subs=window["syn_subs"], nonsyn_subs=window["nonsyn_subs"],
                exp_syn_subs=window["exp_syn_subs"], exp_nonsyn_subs=window["exp_nonsyn_subs"])

        # Include all windows, weight dn/ds by subs
        exp_total_subs = sum([window["nonsyn_subs"] + window["syn_subs"] for window in windows])
        expected_ave = 0
        for window in windows:
            expected_ave += window["nonsyn_subs"]*window["exp_syn_subs"]*(window["nonsyn_subs"]+window["syn_subs"])/(window["syn_subs"]*window["exp_nonsyn_subs"]*exp_total_subs)

        actual_ave = site_dnds_info.get_ave_dnds_weightby_subs(is_exclude_low_sub=False)
        self.assertAlmostEqual(expected_ave, actual_ave, places=10,
                               msg="Expected average dn/ds weighted by subs=" + str(expected_ave) +
                                   " but got " + str(actual_ave))

        # Include all windows, weight dn/ds by reads
        exp_total_reads = sum([window["reads"] for window in windows])
        expected_ave = 0
        for window in windows:
            expected_ave += window["nonsyn_subs"]*window["exp_syn_subs"]*window["reads"]/(window["syn_subs"]*window["exp_nonsyn_subs"]*exp_total_reads)

        actual_ave = site_dnds_info.get_ave_dnds_weightby_reads(is_exclude_low_sub=False)
        self.assertAlmostEqual(expected_ave, actual_ave, places=10,
                               msg="Expected average dn/ds weighted by reads=" + str(expected_ave) +
                                   " but got " + str(actual_ave))

        # Exclude low sub windows, weight dn-ds by subs
        exp_total_subs =sum([window["nonsyn_subs"] + window["syn_subs"] for window in [windows[0], windows[2]]])
        expected_ave = 0
        for window in [windows[0], windows[2]]:
            expected_ave += window["nonsyn_subs"]*window["exp_syn_subs"]*(window["nonsyn_subs"]+window["syn_subs"])/(window["syn_subs"]*window["exp_nonsyn_subs"]*exp_total_subs)

        actual_ave = site_dnds_info.get_ave_dnds_weightby_subs(is_exclude_low_sub=True)
        self.assertAlmostEqual(expected_ave, actual_ave, places=10,
                               msg="Expected average dn/ds weighted by subs, exclude low sub sites=" + str(expected_ave) +
                                   " but got " + str(actual_ave))

        # Exclude low sub windows, weight dn/ds by subs
        exp_total_reads = sum([window["reads"] for window in [windows[0], windows[2]]])
        expected_ave = 0
        for window in [windows[0], windows[2]]:
            expected_ave += window["nonsyn_subs"]*window["exp_syn_subs"]*window["reads"]/(window["syn_subs"]*window["exp_nonsyn_subs"]*exp_total_reads)

        actual_ave = site_dnds_info.get_ave_dnds_weightby_reads(is_exclude_low_sub=True)
        self.assertAlmostEqual(expected_ave, actual_ave, places=10,
                               msg="Expected average dn/ds weighted by reads, exclude low sub sites=" + str(expected_ave) +
                                   " but got " + str(actual_ave))

    def test_site_dnds_info_dnMinusDs(self):
        site_dnds_info = slice_miseq.SiteDnDsInfo()
        windows = self.windows

        for window in windows:
            site_dnds_info.add_window(
                dnds=(window["nonsyn_subs"]*window["exp_syn_subs"])/(window["syn_subs"]*window["exp_nonsyn_subs"]),
                dn_minus_ds=((window["nonsyn_subs"]/window["exp_nonsyn_subs"]) - (window["syn_subs"]/window["exp_syn_subs"]))/window["treelen"],
                reads=window["reads"],
                syn_subs=window["syn_subs"], nonsyn_subs=window["nonsyn_subs"],
                exp_syn_subs=window["exp_syn_subs"], exp_nonsyn_subs=window["exp_nonsyn_subs"])

        # Include all windows, weight dn-ds/treelen by subs
        exp_total_subs = sum([window["nonsyn_subs"] + window["syn_subs"] for window in windows])
        expected_ave = 0
        for window in windows:
            expected_ave += ((window["nonsyn_subs"]/window["exp_nonsyn_subs"]) - (window["syn_subs"]/window["exp_syn_subs"]))*(window["nonsyn_subs"]+window["syn_subs"])/(window["treelen"]*exp_total_subs)

        actual_ave = site_dnds_info.get_ave_dn_minus_ds_weightby_subs(is_exclude_low_sub=False)
        self.assertAlmostEqual(expected_ave, actual_ave, places=10,
                               msg="Expected average dn-ds weighted by subs=" + str(expected_ave) +
                                   " but got " + str(actual_ave))

        # Include all windows, weight dn-ds/treelen by reads
        exp_total_reads = sum([window["reads"] for window in windows])
        expected_ave = 0
        for window in windows:
            expected_ave += ((window["nonsyn_subs"]/window["exp_nonsyn_subs"]) - (window["syn_subs"]/window["exp_syn_subs"]))*(window["reads"])/(window["treelen"]*exp_total_reads)

        actual_ave = site_dnds_info.get_ave_dn_minus_ds_weightby_reads(is_exclude_low_sub=False)
        self.assertAlmostEqual(expected_ave, actual_ave, places=10,
                               msg="Expected average dn-ds weighted by reads=" + str(expected_ave) +
                                   " but got " + str(actual_ave))

        # Exclude low sub windows, weight dn-ds/treelen by subs
        exp_total_subs =sum([window["nonsyn_subs"] + window["syn_subs"] for window in [windows[0], windows[2]]])
        expected_ave = 0
        for window in [windows[0], windows[2]]:
            expected_ave += ((window["nonsyn_subs"]/window["exp_nonsyn_subs"]) - (window["syn_subs"]/window["exp_syn_subs"]))*(window["nonsyn_subs"]+window["syn_subs"])/(window["treelen"]*exp_total_subs)

        actual_ave = site_dnds_info.get_ave_dn_minus_ds_weightby_subs(is_exclude_low_sub=True)
        self.assertAlmostEqual(expected_ave, actual_ave, places=10,
                               msg="Expected average dn-ds weighted by subs, exclude low sub sites=" + str(expected_ave) +
                                   " but got " + str(actual_ave))

        # Exclude low sub windows, weight dn-ds/treelen by reads
        exp_total_reads = sum([window["reads"] for window in [windows[0], windows[2]]])
        expected_ave = 0
        for window in [windows[0], windows[2]]:
            expected_ave += ((window["nonsyn_subs"]/window["exp_nonsyn_subs"]) - (window["syn_subs"]/window["exp_syn_subs"]))*(window["reads"])/(window["treelen"]*exp_total_reads)

        actual_ave = site_dnds_info.get_ave_dn_minus_ds_weightby_reads(is_exclude_low_sub=True)
        self.assertAlmostEqual(expected_ave, actual_ave, places=10,
                               msg="Expected average dn-ds weighted by reads, exclude low sub sites=" + str(expected_ave) +
                                   " but got " + str(actual_ave))

    def test_site_dnds_info_(self):
        site_dnds_info = slice_miseq.SiteDnDsInfo()
        windows = self.windows
        expected_windows = len(windows)
        actual_windows = site_dnds_info.get_window_coverage()
        self.assertEqual(expected_windows, actual_windows,
                               msg="Expected total windows covering site=" + str(expected_windows) +
                                   " but got " + str(actual_windows))

    def test_site_dnds_info_reads(self):
        site_dnds_info = slice_miseq.SiteDnDsInfo()
        windows = self.windows
        expected_ave = sum([window["reads"] for window in windows])/len(windows)
        actual_ave = site_dnds_info.get_ave_read_coverage()
        self.assertEqual(expected_ave, actual_ave,
                               msg="Expected ave reads covering site=" + str(expected_ave) +
                                   " but got " + str(actual_ave))

    def test_site_dnds_info_nonsyn(self):
        site_dnds_info = slice_miseq.SiteDnDsInfo()
        windows = self.windows
        expected_ave = sum([window["nonsyn"] for window in windows])/len(windows)
        actual_ave = site_dnds_info.get_ave_nonsyn_subs()
        self.assertEqual(expected_ave, actual_ave,
                               msg="Expected ave nonsynonymous substitutions at site=" + str(expected_ave) +
                                   " but got " + str(actual_ave))

    def test_site_dnds_info_syn(self):
        site_dnds_info = slice_miseq.SiteDnDsInfo()
        windows = self.windows
        expected_ave = sum([window["syn"] for window in windows])/len(windows)
        actual_ave = site_dnds_info.get_ave_syn_subs()
        self.assertEqual(expected_ave, actual_ave,
                               msg="Expected ave synonymous substitutions at site=" + str(expected_ave) +
                                   " but got " + str(actual_ave))

    def test_site_dnds_info_sub(self):
        site_dnds_info = slice_miseq.SiteDnDsInfo()
        windows = self.windows
        expected_ave = sum([window["syn"]+window["nonsyn"] for window in windows])/len(windows)
        actual_ave = site_dnds_info.get_ave_subs()
        self.assertEqual(expected_ave, actual_ave,
                               msg="Expected ave substitutions at site=" + str(expected_ave) +
                                   " but got " + str(actual_ave))

    def test_tabulate_dnds(self):
        # Site-Window Coverage
        # Site  1   2   3   4
        # Win0  *   *
        # Win1      *   *   *
        # Win2      *   *
        # Win3      *   *
        tmpfilenames = []
        for window in self.windows:
            startnuc = (window["startcdn"]*3) - 2
            endnuc = window["endcdn"]*3
            tmpfile = tempfile.NamedTemporaryFile(delete=False, dir=OUT_DIR,
                                                  suffix=".{}_{}.dnds.tsv".format(startnuc, endnuc))
            writer = csv.DictWriter(tmpfile, fieldnames=[hyphy_handler.HYPHY_TSV_N_COL,
                                                         hyphy_handler.HYPHY_TSV_S_COL,
                                                         hyphy_handler.HYPHY_TSV_EXP_N_COL,
                                                         hyphy_handler.HYPHY_TSV_EXP_S_COL,
                                                         hyphy_handler.HYPHY_TSV_DN_COL,
                                                         hyphy_handler.HYPHY_TSV_DS_COL,
                                                         hyphy_handler.HYPHY_TSV_SCALED_DN_MINUS_DS_COL],
                                    delimiter="\t")
            writer.writeheader()

            # Each window has the same values repeated for every site it covers
            for cdn_site in range(window["startcdn"], window["endcdn"]+1):
                outrow = dict()
                outrow[hyphy_handler.HYPHY_TSV_N_COL] = window["nonsyn_subs"]
                outrow[hyphy_handler.HYPHY_TSV_S_COL] = window["syn_subs"]
                outrow[hyphy_handler.HYPHY_TSV_EXP_N_COL] = window["exp_nonsyn_subs"]
                outrow[hyphy_handler.HYPHY_TSV_EXP_S_COL] = window["exp_syn_subs"]
                outrow[hyphy_handler.HYPHY_TSV_DN_COL] = window["nonsyn_subs"]/window["exp_nonsyn_subs"]
                outrow[hyphy_handler.HYPHY_TSV_DS_COL] = window["syn_subs"]/window["exp_syn_subs"]
                outrow[hyphy_handler.HYPHY_TSV_SCALED_DN_MINUS_DS_COL] = ((window["nonsyn_subs"]/window["exp_nonsyn_subs"])-(window["syn_subs"]/window["exp_syn_subs"]))/window["treelen"]
                writer.writerow(outrow)

            tmpfile.flush()  # flush to os
            os.fsync(tmpfile.file.fileno())  # flush to disk
            tmpfile.close()

            # Create a fake window slice fasta.  We only care about the read depth is truthful.
            # We don't care if the fasta substitutions match the window substitutions
            tmpfastafile = tmpfile.name.replace(".dnds.tsv", ".fasta")
            with open(tmpfastafile, 'w') as fh_fasta:
                num_codons = window["endcdn"] - window["startcdn"] + 1
                for i in range(window["reads"]):
                    fh_fasta.write(">Read" + str(i) + "\n")
                    fh_fasta.write("ACT"*num_codons + "\n")

            tmpfilenames.extend([tmpfile.name, tmpfastafile])

        COMMENTS = "My comments"
        REF = "MyRef"
        REF_NUC_LEN = 12
        OUTPUT_CSV = OUT_DIR + os.sep + "test_tabulate_dnds.csv"
        slice_miseq.tabulate_dnds(dnds_tsv_dir=OUT_DIR, ref=REF,ref_nuc_len=REF_NUC_LEN,
                                  output_csv_filename=OUTPUT_CSV,
                                  comments=COMMENTS)

        # Check that the file exists
        self.assertTrue(os.path.exists(OUTPUT_CSV) and os.path.getsize(OUTPUT_CSV) > 0,
                        msg="Unable to write to dn/ds summary csv file")

        # verify contents
        with open(OUTPUT_CSV, 'rU') as fh_in_tabulate_csv:
            reader = csv.DictReader(filter(lambda row: row[0]!='#', fh_in_tabulate_csv))
            for site_0based, row in enumerate(reader):
                self.assertEqual(row["Site"], str(site_0based+1),
                                 "Expected Sites to be in order.  Expect site=" + str(site_0based+1) + " but got " + row["Site"])

                exp_total_subs_hisub = 0
                exp_total_subs_losub = 0
                exp_total_reads_hisub = 0
                exp_total_reads_losub = 0
                for winIndices in self.site_2_window[site_0based]:
                    if isinstance(winIndices, int ):
                        winIndices = [winIndices] # hack for when there is only 1 window covering a site

                    for windowIdx in winIndices:
                        window = self.windows[windowIdx]
                        if window["nonsyn_subs"] >= 1 and window["syn_subs"] >= 1:
                            exp_total_subs_hisub += window["nonsyn_subs"] + window["syn_subs"]
                            exp_total_reads_hisub += window["reads"]
                        else:
                            exp_total_subs_losub += window["nonsyn_subs"] + window["syn_subs"]
                            exp_total_reads_losub += window["reads"]

                expected_ave_dnds_weightByReads = 0
                expected_ave_dnds_weightByReads_nolowsub = 0
                expected_ave_dnds_weightBySubs = 0
                expected_ave_dnds_weightBySubs_nolowsub = 0

                expected_ave_dnminusds_weightByReads = 0
                expected_ave_dnminusds_weightByReads_nolowsub = 0
                expected_ave_dnminusds_weightBySubs = 0
                expected_ave_dnminusds_weightBySubs_nolowsub = 0
                for winIndices in self.site_2_window[site_0based]:
                    if isinstance(winIndices, int ):
                        winIndices = [winIndices] # hack for when there is only 1 window covering a site

                    for windowIdx in winIndices:
                        window = self.windows[windowIdx]

                        expected_ave_dnds_weightBySubs += window["nonsyn_subs"]*window["exp_syn_subs"]*(window["nonsyn_subs"]+window["syn_subs"])/(window["syn_subs"]*window["exp_nonsyn_subs"]*(exp_total_subs_hisub+exp_total_subs_losub))
                        expected_ave_dnds_weightByReads += window["nonsyn_subs"]*window["exp_syn_subs"]*(window["reads"])/(window["syn_subs"]*window["exp_nonsyn_subs"]*(exp_total_reads_hisub+exp_total_reads_losub))
                        expected_ave_dnminusds_weightByReads += ((window["nonsyn_subs"]/window["exp_nonsyn_subs"])-(window["syn_subs"]/window["exp_syn_subs"]))*window["reads"]/(window["treelen"]*(exp_total_reads_hisub+exp_total_reads_losub))
                        expected_ave_dnminusds_weightBySubs += ((window["nonsyn_subs"]/window["exp_nonsyn_subs"])-(window["syn_subs"]/window["exp_syn_subs"]))*(window["nonsyn_subs"]+window["syn_subs"])/(window["treelen"]*(exp_total_subs_hisub+exp_total_subs_losub))

                        if window["nonsyn_subs"] >= 1 and window["syn_subs"] >= 1:
                            expected_ave_dnds_weightBySubs_nolowsub += window["nonsyn_subs"]*window["exp_syn_subs"]*(window["nonsyn_subs"]+window["syn_subs"])/(window["syn_subs"]*window["exp_nonsyn_subs"]*exp_total_subs_hisub)
                            expected_ave_dnds_weightByReads_nolowsub += window["nonsyn_subs"]*window["exp_syn_subs"]*(window["reads"])/(window["syn_subs"]*window["exp_nonsyn_subs"]*exp_total_reads_hisub)
                            expected_ave_dnminusds_weightByReads_nolowsub += ((window["nonsyn_subs"]/window["exp_nonsyn_subs"])-(window["syn_subs"]/window["exp_syn_subs"]))*window["reads"]/(window["treelen"]*exp_total_reads_hisub)
                            expected_ave_dnminusds_weightBySubs_nolowsub += ((window["nonsyn_subs"]/window["exp_nonsyn_subs"])-(window["syn_subs"]/window["exp_syn_subs"]))*(window["nonsyn_subs"]+window["syn_subs"])/(window["treelen"]*exp_total_subs_hisub)

                self.assertAlmostEqual(expected_ave_dnds_weightByReads, float(row["dndsWeightByReads"]), places=10,
                                       msg="Expected dn/ds weighted by reads=" + str(expected_ave_dnds_weightByReads) +
                                       " but got " + row["dndsWeightByReads"] + " at site " + str(site_0based+1))
                self.assertAlmostEqual(expected_ave_dnds_weightBySubs, float(row["dNdSWeightBySubs"]), places=10,
                                       msg="Expected dn/ds weighted by subs=" + str(expected_ave_dnds_weightBySubs) +
                                       " but got " + row["dnMinusDsWeightBySubs"] + " at site " + str(site_0based+1))
                self.assertAlmostEqual(expected_ave_dnminusds_weightByReads, float(row["dnMinusDsWeightByReads"]), places=10,
                                       msg="Expected dn-ds weighted by reads=" + str(expected_ave_dnminusds_weightByReads) +
                                       " but got " + row["dnMinusDsWeightByReads"] + " at site " + str(site_0based+1))
                self.assertAlmostEqual(expected_ave_dnminusds_weightBySubs, float(row["dnMinusDsWeightBySubs"]), places=10,
                                       msg="Expected dn-ds weighted by subs=" + str(expected_ave_dnminusds_weightBySubs) +
                                       " but got " + row["dnMinusDsWeightBySubs"] + " at site " + str(site_0based+1))

                if expected_ave_dnds_weightByReads_nolowsub:
                    self.assertAlmostEqual(expected_ave_dnds_weightByReads_nolowsub, float(row["dNdSWeightByReadsNoLowSub"]), places=10,
                                           msg="Expected dn/ds weighted by reads, excluding low sub sites=" + str(expected_ave_dnds_weightByReads_nolowsub) +
                                           " but got " + row["dNdSWeightByReadsNoLowSub"] + " at site " + str(site_0based+1))
                else:
                    self.assertEqual("", row["dNdSWeightByReadsNoLowSub"],
                                           msg="Expected dn/ds weighted by reads, excluding low sub sites=None"
                                           " but got " + row["dNdSWeightByReadsNoLowSub"] + " at site " + str(site_0based+1))
                if expected_ave_dnds_weightBySubs_nolowsub:
                    self.assertAlmostEqual(expected_ave_dnds_weightBySubs_nolowsub, float(row["dNdSWeightBySubsNoLowSub"]), places=10,
                                       msg="Expected dn/ds weighted by reads, excluding low sub sites=None" + str(expected_ave_dnds_weightBySubs_nolowsub) +
                                       " but got " + row["dNdSWeightBySubsNoLowSub"] + " at site " + str(site_0based+1))
                else:
                    self.assertEqual("", row["dNdSWeightBySubsNoLowSub"],
                                           msg="Expected dn/ds weighted by subs, excluding low sub sites=None"
                                           " but got " + row["dNdSWeightBySubsNoLowSub"] + " at site " + str(site_0based+1))

                if expected_ave_dnminusds_weightByReads_nolowsub:
                    self.assertAlmostEqual(expected_ave_dnminusds_weightByReads_nolowsub, float(row["dnMinusDsWeightByReadsNoLowSubs"]), places=10,
                                           msg="Expected dn-ds weighted by reads, excluding low sub sites=" + str(expected_ave_dnminusds_weightByReads_nolowsub) +
                                           " but got " + row["dnMinusDsWeightByReadsNoLowSubs"] + " at site " + str(site_0based+1))
                else:
                    self.assertEqual("", row["dnMinusDsWeightByReadsNoLowSubs"],
                                           msg="Expected dn-ds weighted by reads, excluding low sub sites=None"
                                           " but got " + row["dnMinusDsWeightByReadsNoLowSubs"] + " at site " + str(site_0based+1))
                if expected_ave_dnminusds_weightBySubs_nolowsub:
                    self.assertAlmostEqual(expected_ave_dnminusds_weightBySubs_nolowsub, float(row["dnMinusDsWeightBySubsNoLowSubs"]), places=10,
                                       msg="Expected dn-ds weighted by reads, excluding low sub sites=None" + str(expected_ave_dnminusds_weightBySubs_nolowsub) +
                                       " but got " + row["dnMinusDsWeightBySubsNoLowSubs"] + " at site " + str(site_0based+1))
                else:
                    self.assertEqual("", row["dnMinusDsWeightBySubsNoLowSubs"],
                                           msg="Expected dn-ds weighted by subs, excluding low sub sites=None"
                                           " but got " + row["dnMinusDsWeightBySubsNoLowSubs"] + " at site " + str(site_0based+1))

        for tmpfilename in tmpfilenames:
            os.remove(tmpfilename)

if __name__ == '__main__':
    unittest.main()

redpajama_set_name: RedPajamaGithub


text:
@interface DPSetupWindow ()

@property (retain) NSImageView *imageView;
@property (retain) NSBox *contentBox;
@property (retain) NSButton *cancelButton;
@property (retain) NSButton *backButton;
@property (retain) NSButton *nextButton;

@property (copy) void(^completionHandler)(BOOL);
@property (assign) NSViewController *currentViewController;

@end

@implementation DPSetupWindow

- (id)initWithViewControllers:(NSArray *)viewControllers completionHandler:(void (^)(BOOL completed))completionHandler {

	NSRect contentRect = NSMakeRect(0, 0, 580, 420);

    self = [super initWithContentRect:contentRect styleMask:(NSTitledWindowMask|NSClosableWindowMask) backing:NSBackingStoreBuffered defer:YES];
    if (self == nil) return nil;

	if (!viewControllers || [viewControllers count] == 0) return nil;
	if (!completionHandler) return nil;

	currentStage = -1;
	_animates = YES;
	_funnelsRepresentedObjects = NO;
	[self setViewControllers:viewControllers];
	[self setCompletionHandler:completionHandler];

	[self setContentView:[self initialiseContentViewForRect:contentRect]];
	[self next:nil];
    [self addNotifications];

    return self;
}

- (void)dealloc{

    [self removeNotifications];
}

- (NSView *)initialiseContentViewForRect:(NSRect)contentRect {
	NSView *contentView = [[NSView alloc] initWithFrame:contentRect];

	_cancelButton = [[NSButton alloc] initWithFrame:NSMakeRect(145, 13, 97, 32)];
	[_cancelButton setBezelStyle:NSRoundedBezelStyle];
	[_cancelButton setTarget:self];
	[_cancelButton setAction:@selector(cancel:)];
	[_cancelButton setTitle:@"Cancel"];
	[_cancelButton setFont:[NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:NSRegularControlSize]]];
	[contentView addSubview:_cancelButton];

	_backButton = [[NSButton alloc] initWithFrame:NSMakeRect(372, 13, 97, 32)];
	[_backButton setBezelStyle:NSRoundedBezelStyle];
	[_backButton setTarget:self];
	[_backButton setAction:@selector(back:)];
	[_backButton setFont:[NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:NSRegularControlSize]]];
	[contentView addSubview:_backButton];

	_nextButton = [[NSButton alloc] initWithFrame:NSMakeRect(469, 13, 97, 32)];
	[_nextButton setBezelStyle:NSRoundedBezelStyle];
	[_nextButton setTarget:self];
	[_nextButton setAction:@selector(next:)];
	[_nextButton setFont:[NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:NSRegularControlSize]]];
	[contentView addSubview:_nextButton];

	_imageView = [[NSImageView alloc] initWithFrame:NSMakeRect(-40, 60, 320, 320)];
	[_imageView setAlphaValue:0.3];
	[_imageView setImageScaling:NSImageScaleProportionallyUpOrDown];
	[_imageView setImage:[[NSApplication sharedApplication] applicationIconImage]];
	[contentView addSubview:_imageView];

	_contentBox = [[NSBox alloc] initWithFrame:NSMakeRect(148, 57, 415, 345)];
	[_contentBox setTitlePosition:(NSNoTitle)];
	[contentView addSubview:_contentBox];

	return contentView;
}

- (void) addNotifications{

    [[NSNotificationCenter defaultCenter] addObserverForName:kDPNotification_addNextViewController
                                                      object:nil
                                                       queue:[NSOperationQueue currentQueue]
                                                  usingBlock:^(NSNotification *note) {

                                                      NSDictionary *userInfo = [note userInfo];

                                                      NSViewController<DPSetupWindowStageViewController> *viewController = nil;

                                                      viewController = [userInfo objectForKey:kDPNotification_key_viewController];

                                                      if (viewController) {

                                                          NSMutableArray *newViewControllers = [[self viewControllers] mutableCopy];
                                                          [newViewControllers insertObject:viewController atIndex:(currentStage + 1)];
                                                          [self setViewControllers:[NSArray arrayWithArray:newViewControllers]];
                                                      }
                                                  }];

    [[NSNotificationCenter defaultCenter] addObserverForName:kDPNotification_addFinalViewController
                                                      object:nil
                                                       queue:[NSOperationQueue currentQueue]
                                                  usingBlock:^(NSNotification *note) {

                                                      NSDictionary *userInfo = [note userInfo];

                                                      NSViewController<DPSetupWindowStageViewController> *viewController = nil;

                                                      viewController = [userInfo objectForKey:kDPNotification_key_viewController];

                                                      if (viewController) {

                                                          NSArray *newViewControllers = [[self viewControllers] arrayByAddingObject:viewController];
                                                          [self setViewControllers:newViewControllers];
                                                      }
                                                  }];

    [[NSNotificationCenter defaultCenter] addObserverForName:kDPNotification_deleteViewController
                                                      object:nil
                                                       queue:[NSOperationQueue currentQueue]
                                                  usingBlock:^(NSNotification *note) {

                                                      NSDictionary *userInfo = [note userInfo];

                                                      id mustDeleteController = nil;
                                                      Class mustDeleteClass = nil;
                                                      mustDeleteClass = [userInfo objectForKey:kDPNotification_key_viewControllerClass];

                                                      NSMutableArray *viewControllers = [[self viewControllers] mutableCopy];
                                                      for (id controller in viewControllers)
                                                          if ([controller class]==mustDeleteClass)
                                                              mustDeleteController = controller;

                                                      if (mustDeleteController &&
                                                          mustDeleteController != [viewControllers objectAtIndex:currentStage]) {

                                                          @try {
                                                              [self deregisterObserversForViewController:mustDeleteController];
                                                          }
                                                          @catch (NSException *exception) {}

                                                          [viewControllers removeObject:mustDeleteController];
                                                          [self setViewControllers:[NSArray arrayWithArray:viewControllers]];
                                                      }
                                                  }];
}

- (void) removeNotifications{

    [[NSNotificationCenter defaultCenter] removeObserver:self
                                                    name:kDPNotification_addNextViewController
                                                  object:nil];

    [[NSNotificationCenter defaultCenter] removeObserver:self
                                                    name:kDPNotification_addFinalViewController
                                                  object:nil];

    [[NSNotificationCenter defaultCenter] removeObserver:self
                                                    name:kDPNotification_deleteViewController
                                                  object:nil];
}

#pragma mark -
#pragma mark Customisation

- (void)setBackgroundImage:(NSImage *)backgroundImage {
	_backgroundImage = backgroundImage;
	[[self imageView] setImage:backgroundImage];
}

- (NSImage *)backgroundImage {
	return _backgroundImage;
}

#pragma mark -
#pragma mark Flow Control

typedef enum {
	DPSetupWindowNextDirection = 1,
	DPSetupWindowBackDirection = -1
} DPSetupWindowDirection;

- (void)progressToNextStage {
	[self shift:DPSetupWindowNextDirection];
}

- (void)revertToPreviousStage {
	[self shift:DPSetupWindowBackDirection];
}

- (void)resetToZeroStage{

    for (id viewController in [self viewControllers])
        if ([viewController respondsToSelector:@selector(resetToInitialState)])
            [viewController resetToInitialState];

    NSViewController<DPSetupWindowStageViewController> *previousViewController = nil;
    if(currentStage>0 &&
       currentStage<=[[self viewControllers] count])

        previousViewController = [[self viewControllers] objectAtIndex:currentStage];
    else
        return;

    //rewind
    currentStage = 0;
    NSViewController<DPSetupWindowStageViewController> *nextViewController = [[self viewControllers] objectAtIndex:currentStage];
	NSView *view = [nextViewController view];

    [nextViewController performSelectorIfExists:@selector(willProgressToStage)];

    void (^finished)() = ^{

        [previousViewController performSelectorIfExists:@selector(didProgressToNextStage)];
        [nextViewController performSelectorIfExists:@selector(didProgressToStage)];
	};

    [view setFrame:NSMakeRect(0, 0, 400, 330)];
    if (previousViewController)
        [[previousViewController view] removeFromSuperviewWithoutNeedingDisplay];

    [[self contentBox] addSubview:view];
    finished();

	[self registerObserversForPreviousViewController:previousViewController nextViewController:nextViewController];
	[self recalculateButtonEnabledStates];
	[self resetButtonTitles];
}

- (void)next:(id)sender {
	[self shift:DPSetupWindowNextDirection];
}

- (void)back:(id)sender {
	[self shift:DPSetupWindowBackDirection];
}

- (void)shift:(DPSetupWindowDirection)direction {

	if ((currentStage == [[self viewControllers] count] && direction == DPSetupWindowNextDirection) ||
		(currentStage == 0 && direction == DPSetupWindowBackDirection)) {
		return;
	}

	NSViewController<DPSetupWindowStageViewController> *previousViewController = nil;
	if (currentStage >= 0 && currentStage < [[self viewControllers] count]) {
		previousViewController = [[self viewControllers] objectAtIndex:currentStage];
	}

	if (direction == DPSetupWindowNextDirection) {
		[previousViewController performSelectorIfExists:@selector(willProgressToNextStage)];
	} else if (direction == DPSetupWindowBackDirection)	{
		[previousViewController performSelectorIfExists:@selector(willRevertToPreviousStage)];
	}

	NSInteger nextStage = currentStage + direction;
	if (nextStage == [[self viewControllers] count]) {
        	//[self deregisterObserversForViewController:previousViewController];
		[self completionHandler](YES);
		return;
	}

	NSViewController<DPSetupWindowStageViewController> *nextViewController = [[self viewControllers] objectAtIndex:nextStage];
	NSView *view = [nextViewController view];

	if (direction == DPSetupWindowNextDirection) {
		[nextViewController performSelectorIfExists:@selector(willProgressToStage)];
	} else if (direction == DPSetupWindowBackDirection)	{
		[nextViewController performSelectorIfExists:@selector(willRevertToStage)];
	}

	void (^finished)() = ^{
		if (direction == DPSetupWindowNextDirection) {
			[previousViewController performSelectorIfExists:@selector(didProgressToNextStage)];
			[nextViewController performSelectorIfExists:@selector(didProgressToStage)];
		} else if (direction == DPSetupWindowBackDirection)	{
			[previousViewController performSelectorIfExists:@selector(didRevertToPreviousStage)];
			[nextViewController performSelectorIfExists:@selector(didRevertToStage)];
		}
	};

	if ([self funnelsRepresentedObjects]) {
		[nextViewController setRepresentedObject:[previousViewController representedObject]];
	}

	if ([self animates] && previousViewController) {
		[NSAnimationContext beginGrouping];

		if ([[NSApp currentEvent] modifierFlags] & NSShiftKeyMask) {
			[[NSAnimationContext currentContext] setDuration:3.0];
		}
		[[NSAnimationContext currentContext] setCompletionHandler:^{
			[[previousViewController view] removeFromSuperviewWithoutNeedingDisplay];
			finished();
		}];

		[view setFrame:NSMakeRect((400 * direction), 0, 400, 330)];
		[[self contentBox] addSubview:view];
		[[view animator] setFrameOrigin:NSMakePoint(0, 0)];
		[[[previousViewController view] animator] setFrameOrigin:NSMakePoint((-400 * direction), 0)];

		[NSAnimationContext endGrouping];
	} else {
		[view setFrame:NSMakeRect(0, 0, 400, 330)];
		if (previousViewController) {
			[[previousViewController view] removeFromSuperviewWithoutNeedingDisplay];
		}
		[[self contentBox] addSubview:view];
		finished();
	}

	currentStage = nextStage;
	[self registerObserversForPreviousViewController:previousViewController nextViewController:nextViewController];
	[self recalculateButtonEnabledStates];
	[self resetButtonTitles];
}

- (void)cancelOperation:(id)sender {
	[self cancel:sender];
}

- (void)cancel:(id)sender {
	[[NSApplication sharedApplication] endSheet:self returnCode:0];
	[self completionHandler](NO);
}

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
	[self recalculateButtonEnabledStates];
}

- (void)recalculateButtonEnabledStates {
	NSViewController<DPSetupWindowStageViewController> *currentViewController = [[self viewControllers] objectAtIndex:currentStage];
	if ([currentViewController respondsToSelector:@selector(canContinue)]) {
		[[self nextButton] setEnabled:[currentViewController canContinue]];
	} else {
		[[self nextButton] setEnabled:YES];
	}

	if ([currentViewController respondsToSelector:@selector(canGoBack)]) {
		[[self backButton] setEnabled:[currentViewController canGoBack]];
	} else {
		[[self backButton] setEnabled:YES];
	}

	if (currentStage == 0) {
		[[self backButton] setEnabled:NO];
	}
}

- (void)registerObserversForPreviousViewController:(NSViewController *)previousViewController nextViewController:(NSViewController *)nextViewController {

	[previousViewController removeObserver:self forKeyPath:@"canContinue"];
	[previousViewController removeObserver:self forKeyPath:@"canGoBack"];
	[nextViewController addObserver:self forKeyPath:@"canContinue" options:(NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld) context:NULL];
	[nextViewController addObserver:self forKeyPath:@"canGoBack" options:(NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld) context:NULL];
}

- (void)deregisterObserversForViewController:(NSViewController *)viewController {
    	[viewController removeObserver:self forKeyPath:@"canContinue"];
    	[viewController removeObserver:self forKeyPath:@"canGoBack"];
}

- (void)resetButtonTitles {
	NSViewController<DPSetupWindowStageViewController> *currentViewController = [[self viewControllers] objectAtIndex:currentStage];
	if ([currentViewController respondsToSelector:@selector(continueButtonTitle)]) {
		[[self nextButton] setTitle:[currentViewController continueButtonTitle]];
	} else {
		[[self nextButton] setTitle:@"Continue"];
	}

	if ([currentViewController respondsToSelector:@selector(backButtonTitle)]) {
		[[self backButton] setTitle:[currentViewController backButtonTitle]];
	} else {
		[[self backButton] setTitle:@"Back"];
	}
}

@end


text:
<?php

class BaseaButtonSlotActions extends BaseaSlotActions
{
  // Image association is handled by a separate action
  public function executeImage(sfRequest $request)
  {
    if ($request->getParameter('aMediaCancel'))
    {
      return $this->redirectToPage();
    }

    $this->logMessage("====== in aImageSlotActions::executeImage", "info");
    $this->editSetup();
    $item = Doctrine::getTable('aMediaItem')->find($request->getParameter('aMediaId'));
    if ((!$item) || ($item->type !== 'image'))
    {
      return $this->redirectToPage();
    }
    $this->slot->unlink('MediaItems');
    $this->slot->link('MediaItems', array($item->id));
    $this->editSave();
  }

  // Use the edit view for the URL (and any other well-behaved fields that may arise)
  public function executeEdit(sfRequest $request)
  {
    $this->logMessage("====== in aButtonSlotActions::executeEdit", "info");
    $this->editSetup();
    $value = $this->getRequestParameter('slotform-' . $this->id);
    $this->form = new aButtonForm($this->id);
    $this->form->bind($value);
    if ($this->form->isValid())
    {
      $url = $this->form->getValue('url');
      $value = $this->slot->getArrayValue();
      $value['url'] = $url;
      $value['title'] = $this->form->getValue('title');
      $this->slot->setArrayValue($value);
      $result = $this->editSave();
      return $result;
    }
    else
    {
      // Makes $this->form available to the next iteration of the
      // edit view so that validation errors can be seen
      return $this->editRetry();
    }
  }
}


text:
/**
 * Module dependencies.
 */

var mongoose = require('mongoose')
  , async = require('async')
  , Device = mongoose.model('Device')
  , User = mongoose.model('User')

/**
 * Clear database
 *
 * @param {Function} done
 * @api public
 */

exports.clearDb = function (done) {
  async.parallel([
    function (cb) {
      User.collection.remove(cb)
    },
    function (cb) {
      Device.collection.remove(cb)
    }
  ], done)
}


text:
Smoke
=====

This automated betting framework is intended to allow you to add:

1. betting odds providers (e.g. Betfair)
2. betting data providers (e.g. ScoresPro)
3. automated betting strategies

This contains two sample betting strategies named Genghis (and its improved version Genghis II) and Tamerlane.

The solution builds successfully in Visual Studio 2012 using .NET 4.5. To run it set any of the sample strategies project as startup. That will require a valid Betfair username and password.

Do play around, hope it helps you. If you have any questions or you are interested in contributing, do let me know.


text:
const R = require('ramda');

const constants = require('./constants');
const blueToRedProjectPrefixes = require('../db/blue-to-red-project.json');
const projectNameToTaskCodeId = require('../db/red-task-code-name-to-id.json');
const blueProjectPrefixes = require('../db/blue-project-name-to-prefix.json');
const redPrefixToProjectName = require('../db/red-prefix-to-project-name.json');

function getBlueProject(ticket, specialTickets = []) {
  if (specialTickets.includes(ticket[constants.blue.ID])) {
    return constants.converter.SPECIAL;
  }

  return getBlueProjectPrefix(ticket) || constants.converter.NO_PROJECT;
}

function getBlueProjectPrefix(ticket) {
  const projectName = R.prop(constants.blue.BILLING_PROJECT, ticket) ||
    R.prop(constants.blue.PROJECT, ticket);

  return blueProjectPrefixes[projectName];
}

function split(tickets, options = {}) {
  if (R.isNil(tickets) || R.isEmpty(tickets)) {
    return {};
  }

  return R.pipe(
    R.groupBy((ticket) => (getBlueProject(ticket, options.special))),
    R.map(
      R.sort(
        (first, second) => (
        new Date(first[constants.blue.WHEN]) - new Date(second[constants.blue.WHEN]))
      )
    )
  )(tickets);
}

function convert(blueTicket, userType) {
  const redTicket = {};

  const commonConstantNames = [
    'WHEN',
    'TIME_SPENT',
    'TITLE',
    'ID',
  ];
  const blueColumnNames = R.pick(commonConstantNames, constants.blue);
  const redColumnNames = constants.red;
  R.toPairs(blueColumnNames).forEach(([k, v]) => {
    redTicket[redColumnNames[k]] = blueTicket[v];
  });

  redTicket[redColumnNames.WHEN] = convertDateToRedFormat(redTicket[redColumnNames.WHEN]);
  redTicket[redColumnNames.TASK_CODE] = getRedTaskCode(blueTicket, userType);
  return redTicket;
}

function convertDateToRedFormat(someDateString) {
  // e.g. from 2016-12-19 14:18:00 to 12-19-2016
  const d = (new Date(someDateString));
  return `${d.getMonth() + 1}-${d.getDate()}-${d.getFullYear()}`;
}

function getRedTaskCode(blueTicket, userType) {
  const blueProjectPrefix = getBlueProjectPrefix(blueTicket);
  const redProjectPrefix = blueToRedProjectPrefixes[blueProjectPrefix];

  return projectNameToTaskCodeId[`${redProjectPrefix}-${userType || 'WEB'}`];
}

function toRedProjectTypes(ticketsGroupedByBlueProjectTypes) {
  const specialGroups = [constants.converter.SPECIAL, constants.converter.NO_PROJECT];
  const newMapping = {};

  R.toPairs(ticketsGroupedByBlueProjectTypes).forEach(([k, v]) => {
    if (specialGroups.includes(k)) {
      newMapping[k] = v;
    } else {
      newMapping[blueToRedProjectPrefixes[k]] = v;
    }
  });

  return newMapping;
}

function generateRedTicketsWithTimesheetInfo(redTicketsByRedProjectTypes, redProjectToTimesheet) {
  const tickets = [];
  R.toPairs(redTicketsByRedProjectTypes)
    .forEach(([project, ticketsInProject]) => {
      const timesheet = redProjectToTimesheet[redPrefixToProjectName[project]];
      const ticketsWithTimesheet = ticketsInProject.map(R.assoc(constants.red.TIMESHEET, timesheet));
      tickets.push(...ticketsWithTimesheet);
    });
  return tickets;
}

module.exports = {
  split,
  convert,
  toRedProjectTypes,
  generateRedTicketsWithTimesheetInfo,
};


text:
import main,dataset
import re,pdb

'''
need to handle some specific patterns:

    sentence without a VP indicates some mistagging
        can a corrective retagging occur when ambiguity arises?

    a VP without a preceding NP likely corresponds to the following NP?

    sequences of NPs joined by commas and CCs (either an "AND" or "OR" CC)
    "AND" -> a set of distinct statements all of which are true
    "OR" -> a set of somewhat dependent statements at least one of which is true

    sequences of (NP+VP)s separated by commas and CCs may produce
    sets of distinct statements
    "AND" -> a set of distinct statements all of which are true
    "OR" -> a set of somewhat dependent statements at least one of which is true

    a NP following a PP modifies the preceding statement

    a VP followed or preceded by an ADJP modifieds a statement

    would be very useful to tag the tense of VPs

    would be very useful perform anaphorism resolution between sentences

    ultimately would like a set of concise, independent statements to analyze
    each such statement should have a specific set of components:
        a primary VP corresponding to a primary NP
        a set of modifying phrases (NPs, ADJPs, PPs, ADVPs)
            describing the primary NP or VP
        ADJPs modify NPs, ADVPs modify VPs, (PP+NP)s modifying (NP+VP)s

    variants of sentences derived by changing the order of reduction operations
    should not yield contradictory statements
        (or statements should universally entail one another?)

    breaking of sentences yields a tree of break operations
'''

def printo(o,ks):
    '''Given the output of the tagger on a sentence (o),
    print in a readable fashion the part of speech tagging and chunking.'''
    print('::'.join([k.center(16) for k in ks]))
    print('::'.join(['-'*16]*3))
    for j in range(len(o[ks[0]])):
        l = [o[k][j].center(16) for k in ks]
        print('::'.join(l))
    for phrase in dataset.POSTags.chunk([o[k] for k in ks]):
        l = [' '.join(phrase[0]).ljust(32),','.join(phrase[2]).rjust(16)]
        print('::'.join(l))

def resolvechunks(o,ks):
    '''Given the output of the tagger on a sentence (o),
    produce chunk tuples (phrase type, phrase words, phrase parts of speech).'''
    chunks = []
    for phrase in dataset.POSTags.chunk([o[k] for k in ks]):
        phrasetags = set([x if x == 'O' else x[2:] for x in phrase[2]])
        if len(phrasetags) == 1:phrasetag = phrasetags.pop()
        else:
            print('phrasetag ambiguity %s' % str(phrasetags))
            pdb.set_trace()
        chunks.append((phrasetag,tuple(zip(phrase[0],phrase[1]))))
    return chunks

def scanVP(chunks,d = -1):
    #printc(chunks)
    clen = len(chunks)
    if d < 0:
        j = clen
        while j > 0:
            j -= 1
            if chunks[j][0] == 'VP':
                return j
        return 0
    elif d > 0:
        j = 0
        while j < clen:
            if chunks[j][0] == 'VP':
                return j
            j += 1
        return clen-1

def findbreaks(chunks):
    '''Return, if possible, an alternative set of sentences based on tagging.'''

    '''Identify each acceptable break operation on a subvertex (chunked sentence).
    chunks likely fits a known template about which a breakable can be predicted.
    '''
    chunkf = lambda c : (c[0],)+tuple(' '.join(x) for x in tuple(zip(*c[1])))
    printf = lambda c : ('[ %s | %s | %s ]' % chunkf(c))
    printc = lambda c : print(' -> '.join([printf(p) for p in c]))

    prints = lambda c : print(' '.join([chunkf(x)[1] for x in c]))

    printc(chunks)

    CC_and = ('O',(('and','CC'),))
    if CC_and in chunks:
        bp = chunks.index(CC_and)
        l,r = chunks[:bp],chunks[bp+1:]
        bpl = scanVP(l,-1)
        bpr = scanVP(r,+1)
        aset = [x for x in l[bpl:]+r[:bpr] if not x == ('O',((',',','),))]
        '''each member of aset presents a candidate sentence...'''
        cands = [l[:bpl]+[aseti]+r[bpr:] for aseti in aset]
        for c in cands:prints(c)
        '''some number of comma separated NPs (VP should adjust for tense)'''
        '''a pair of (NP+VP)s'''

        pdb.set_trace()

def breaksentence(o,ks):
    '''Break a sentence into a set of sentences, providing a resolution tree.
      - Each vertex in the tree represents a set of sentences.
      - Each sentence at a vertex represents a subvertex.
      - Each edge in the tree represents a potential break operation
          from a subvertex at a single vertex to another vertex.
      - The set of terminal vertices once break options are exhausted
          represents the possible set of sentences (subvertices) to return.

    NOTE: Require a function that returns break options (edges) given a sentence.
    '''

    chunks = resolvechunks(o,ks)

    '''
    graph ([list of vertices],[list of edges])
    each vertex is a list of subvertices [list of chunk variants]
    each edge indicates a starting vertex, subvertex, and ending vertex
    '''
    graph = ([[chunks]],[])
    unfinished = [(0,[0])]
    while True:
        unfin = unfinished.pop()
        vertex = unfin[0]
        for subvertex in unfin[1]:
            breakable = findbreaks(graph[0][vertex][subvertex])
            if breakable:

                pdb.set_trace()

            else:
                pdb.set_trace()

        if not unfinished:break

    pdb.set_trace()

def resolvecorpus(o,ks):
    '''Given a list of tagger outputs for a list of sentences,
    produce a list of independent and more concise sentences
    representing the same global information.'''

    '''Order of resolution operations:
    1: Anaphorism resolution (removal of pronouns and the like as possible).
    2: Breaking sentences based on CC usage.
    '''

    printo(o[0],ks)

    o = [breaksentence(s,ks) for s in o]

    #chunks = [resolvechunks(s,ks) for s in o]
    #for chunked in chunks:
    #    chunkstring = ' -> '.join([('[%s | %s | %s]' % chunk) for chunk in chunked])
    #    print(chunkstring+'\n\n')

    pdb.set_trace()

if __name__ == '__main__':
    d = [
        'An elephant, a donkey, and a penguin walk into a bar.',
        'One of them spoke to the bartender, and the others remained silent.',
            ]

    tagger = main.main()
    ks = (tagger.config.target_field,)+tagger.config.output_fields

    o = [tagger.work(s) for s in d]
    resolvecorpus(o,ks)

    pdb.set_trace()


text:
We'll begin by setting up the master node.  For the purposes of illustration, we'll assume that the IP of this machine
is `${MASTER_IP}`.  We'll need to run several versioned Kubernetes components, so we'll assume that the version we want
to run is `${K8S_VERSION}`, which should hold a released version of Kubernetes >= "1.2.0-alpha.7"

Enviroinment variables used:

```shell
export MASTER_IP=<the_master_ip_here>
export K8S_VERSION=<your_k8s_version (e.g. 1.2.0-alpha.7)>
export ETCD_VERSION=<your_etcd_version (e.g. 2.2.1)>
export FLANNEL_VERSION=<your_flannel_version (e.g. 0.5.5)>
export FLANNEL_IFACE=<flannel_interface (defaults to eth0)>
export FLANNEL_IPMASQ=<flannel_ipmasq_flag (defaults to true)>
```

There are two main phases to installing the master:

   * [Setting up `flanneld` and `etcd`](#setting-up-flanneld-and-etcd)
   * [Starting the Kubernetes master components](#starting-the-kubernetes-master)

## Setting up flanneld and etcd

_Note_:
This guide expects **Docker 1.7.1 or higher**.

### Setup Docker Bootstrap

We're going to use `flannel` to set up networking between Docker daemons.  Flannel itself (and etcd on which it relies) will run inside of
Docker containers themselves.  To achieve this, we need a separate "bootstrap" instance of the Docker daemon.  This daemon will be started with
`--iptables=false` so that it can only run containers with `--net=host`.  That's sufficient to bootstrap our system.

Run:

```shell
sudo sh -c 'docker -d -H unix:///var/run/docker-bootstrap.sock -p /var/run/docker-bootstrap.pid --iptables=false --ip-masq=false --bridge=none --graph=/var/lib/docker-bootstrap 2> /var/log/docker-bootstrap.log 1> /dev/null &'
```

_If you have Docker 1.8.0 or higher run this instead_

```shell
sudo sh -c 'docker daemon -H unix:///var/run/docker-bootstrap.sock -p /var/run/docker-bootstrap.pid --iptables=false --ip-masq=false --bridge=none --graph=/var/lib/docker-bootstrap 2> /var/log/docker-bootstrap.log 1> /dev/null &'
```

_Important Note_:
If you are running this on a long running system, rather than experimenting, you should run the bootstrap Docker instance under something like SysV init, upstart or systemd so that it is restarted
across reboots and failures.

### Startup etcd for flannel and the API server to use

Run:

```shell
sudo docker -H unix:///var/run/docker-bootstrap.sock run -d \
    --net=host \
    gcr.io/google_containers/etcd-amd64:${ETCD_VERSION} \
    /usr/local/bin/etcd \
        --listen-client-urls=http://127.0.0.1:4001,http://${MASTER_IP}:4001 \
        --advertise-client-urls=http://${MASTER_IP}:4001 \
        --data-dir=/var/etcd/data
```

Next, you need to set a CIDR range for flannel.  This CIDR should be chosen to be non-overlapping with any existing network you are using:

```shell
sudo docker -H unix:///var/run/docker-bootstrap.sock run \
    --net=host \
    gcr.io/google_containers/etcd-amd64:${ETCD_VERSION} \
    etcdctl set /coreos.com/network/config '{ "Network": "10.1.0.0/16" }'
```

### Set up Flannel on the master node

Flannel is a network abstraction layer build by CoreOS, we will use it to provide simplified networking between our Pods of containers.

Flannel re-configures the bridge that Docker uses for networking.  As a result we need to stop Docker, reconfigure its networking, and then restart Docker.

#### Bring down Docker

To re-configure Docker to use flannel, we need to take docker down, run flannel and then restart Docker.

Turning down Docker is system dependent, it may be:

```shell
sudo /etc/init.d/docker stop
```

or

```shell
sudo systemctl stop docker
```

or

```shell
sudo service docker stop
```

or it may be something else.

#### Run flannel

Now run flanneld itself:

```shell
sudo docker -H unix:///var/run/docker-bootstrap.sock run -d \
    --net=host \
    --privileged \
    -v /dev/net:/dev/net \
    quay.io/coreos/flannel:${FLANNEL_VERSION} \
        --ip-masq=${FLANNEL_IPMASQ} \
        --iface=${FLANNEL_IFACE}
```

The previous command should have printed a really long hash, the container id, copy this hash.

Now get the subnet settings from flannel:

```shell
sudo docker -H unix:///var/run/docker-bootstrap.sock exec <really-long-hash-from-above-here> cat /run/flannel/subnet.env
```

#### Edit the docker configuration

You now need to edit the docker configuration to activate new flags.  Again, this is system specific.

This may be in `/etc/default/docker` or `/etc/systemd/service/docker.service` or it may be elsewhere.

Regardless, you need to add the following to the docker command line:

```shell
--bip=${FLANNEL_SUBNET} --mtu=${FLANNEL_MTU}
```

#### Remove the existing Docker bridge

Docker creates a bridge named `docker0` by default.  You need to remove this:

```shell
sudo /sbin/ifconfig docker0 down
sudo brctl delbr docker0
```

You may need to install the `bridge-utils` package for the `brctl` binary.

#### Restart Docker

Again this is system dependent, it may be:

```shell
sudo /etc/init.d/docker start
```

it may be:

```shell
systemctl start docker
```

## Starting the Kubernetes Master

Ok, now that your networking is set up, you can startup Kubernetes, this is the same as the single-node case, we will use the "main" instance of the Docker daemon for the Kubernetes components.

```shell
sudo docker run \
    --volume=/:/rootfs:ro \
    --volume=/sys:/sys:ro \
    --volume=/var/lib/docker/:/var/lib/docker:rw \
    --volume=/var/lib/kubelet/:/var/lib/kubelet:rw \
    --volume=/var/run:/var/run:rw \
    --net=host \
    --privileged=true \
    --pid=host \
    -d \
    gcr.io/google_containers/hyperkube-amd64:v${K8S_VERSION} \
    /hyperkube kubelet \
        --allow-privileged=true \
        --api-servers=http://localhost:8080 \
        --v=2 \
        --address=0.0.0.0 \
        --enable-server \
        --hostname-override=127.0.0.1 \
        --config=/etc/kubernetes/manifests-multi \
        --containerized \
        --cluster-dns=10.0.0.10 \
        --cluster-domain=cluster.local
```

> Note that `--cluster-dns` and `--cluster-domain` is used to deploy dns, feel free to discard them if dns is not needed.

### Test it out

At this point, you should have a functioning 1-node cluster.  Let's test it out!

Download the kubectl binary for `${K8S_VERSION}` ({{page.version}}) and make it available by editing your PATH environment variable.
([OS X/amd64](http://storage.googleapis.com/kubernetes-release/release/{{page.version}}.0-alpha.7/bin/darwin/amd64/kubectl))
([OS X/386](http://storage.googleapis.com/kubernetes-release/release/{{page.version}}.0-alpha.7/bin/darwin/386/kubectl))
([linux/amd64](http://storage.googleapis.com/kubernetes-release/release/{{page.version}}.0-alpha.7/bin/linux/amd64/kubectl))
([linux/386](http://storage.googleapis.com/kubernetes-release/release/{{page.version}}.0-alpha.7/bin/linux/386/kubectl))
([linux/arm](http://storage.googleapis.com/kubernetes-release/release/{{page.version}}.0-alpha.7/bin/linux/arm/kubectl))

For example, OS X:

```shell
$ wget http://storage.googleapis.com/kubernetes-release/release/v${K8S_VERSION}/bin/darwin/amd64/kubectl
$ chmod 755 kubectl
$ PATH=$PATH:`pwd`
```

Linux:

```shell
$ wget http://storage.googleapis.com/kubernetes-release/release/v${K8S_VERSION}/bin/linux/amd64/kubectl
$ chmod 755 kubectl
$ PATH=$PATH:`pwd`
```

Now you can list the nodes:

```shell
kubectl get nodes
```

This should print something like:

```shell
NAME        LABELS                             STATUS
127.0.0.1   kubernetes.io/hostname=127.0.0.1   Ready
```

If the status of the node is `NotReady` or `Unknown` please check that all of the containers you created are successfully running.
If all else fails, ask questions on [Slack](/docs/troubleshooting/#slack).

### Next steps

Move on to [adding one or more workers](/docs/getting-started-guides/docker-multinode/worker/) or [deploy a dns](/docs/getting-started-guides/docker-multinode/deployDNS/)


text:
from imports import *

def get_user_id(nick):
    """Get userid by nickname

    Args:
        nick: the nickname of the user

    Returns:
        the user id of the nickname
    """

    user_id = db_session.query(User.user_id).filter_by(nick=nick).first()
    return user_id[0]

def getNick():
    """Get nickname

    Returns:
        The nickname of current User
    """

    nick = None
    if 'user_id' in session:
        result = db_session.query(User.nick).filter_by(
            user_id=int(session['user_id'])).first()
        nick = result[0]
    return nick

def get_avatar():
    """Get avatar

    Returns:
        THe avatar of current user
    """

    nick = getNick()
    return db_session.query(User.photo).filter_by(nick=nick).first()[0] if nick is not None else None
    # if nick is None:
    #     return None
    # avatar = db_session.query(User.photo).filter_by(nick=nick).first()
    # return avatar[0]

def get_role(user_id):
    """Get role by id

    Args:
        user_id: the id of the user

    Returns:
        The role of the user
    """

    result = db_session.query(User.role).filter_by(user_id=user_id).first()
    return result[0]

def get_user_by_nick(nick):
    """Get user by nickname

    Args:
        nick: the nickname of the user

    Returns:
        The user object
    """

    result = db_session.query(User).filter_by(nick=nick).first()
    return result

def examine_user_id(user_id):
    """Examine if user of user_id exists

    Args:
        user_id: the id of the user

    Returns:
        Whether user exists
    """

    result = db_session.query(User).filter_by(user_id=user_id).all()
    if len(result) > 0:
        return True
    else:
        return False


text:
var User = require("./models/User.js");

const mongoose = require("mongoose");
const configDB = require ("./dbConfig.js");
mongoose.connect(configDB.url);

function createUser(email, password){
    User.findOne({ "local.email": email}, (err, user) => {
        if(err) return done(err);

        if(user){
            console.log("The email is already taken.")
            return false;
        }else{
            var newUser = new User();

            newUser.local.email = email;
            newUser.local.password = newUser.generateHash(password);

            newUser.save( (err) => {
                if(err) throw err;

                return false;
            });
        }
    });
}

createUser(process.argv[2], process.argv[3]);