<commit_before>const simple = ['AB', 'AW', 'AE', 'B', 'CR', 'DD', 'MA', 'SL', 'SQ', 'TB', 'TR', 'TW', 'VW', 'W']
const pointWithText = ['LB']
const arrowish = ['AR', 'LN']

const alpha = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
const alphaRev = [...alpha].reverse()

const colorSwapMap = {
	'AB': 'AW',
	'AW': 'AB',
	'B': 'W',
	'W': 'B',
}

// Special functions that return the "min" and "max"
// for the SGF coordinate system...
//
// a-z : 0-25
// A-Z : 26-51
//
// Note that lowercase has higher ASCII value,
// but is considered lower in the SGF system.

function min(one, two) {
    // In case exactly one is lowercase, return it...

    if (one >= 'a' && two <= 'Z') return one
    if (one <= 'Z' && two >= 'a') return two

    // Same case...

    if (one < two) return one
    return two
}

function max(one, two) {
    if (one >= 'a' && two <= 'Z') return two
    if (one <= 'Z' && two >= 'a') return one
    if (one < two) return two
    return one
}

function pointIntegers(point, width, height) {
    // point is something like 'ae'
    // Returns [null, null] on failure; otherwise returns something like [0,4]

    if (typeof point !== 'string' || point.length !== 2) return [null, null]
    let index0 = alpha.indexOf(point[0])
    let index1 = alpha.indexOf(point[1])
    if (index0 === -1 || index1 === -1 || index0 >= width || index1 >= height) return [null, null]
    return [index0, index1]
}

function extractTwoPoints(s) {
    // s is something like 'aa:cc'
    // Returns [null, null] on failure; otherwise returns something like ['aa','cc']

    if (typeof s !== 'string' || s.length !== 5 || s[2] !== ':') return [null, null]
    return [s.slice(0, 2), s.slice(3, 5)]
}

function fixedRectangle(first, second) {
    // Given two SGF formatted corners of a rectangle, e.g. 'ch' and 'fc',
    // return a string using top-left : bottom-right format, e.g. 'cc:fh'

    return min(first[0], second[0]) + min(first[1], second[1])
    + ':' + max(first[0], second[0]) + max(first[1], second[1])
}

exports.rotatePoint = function(point, width, height, anticlockwise) {
    // Returns null on failure; point is something like 'ae'

    let [x, y] = pointIntegers(point, width, height)
    if (x === null || y === null) return null

    if (anticlockwise) {
        let rev = alphaRev.slice(52 - width)
        return point[1] + rev[x]
    } else {
        let rev = alphaRev.slice(52 - height)
        return rev[y] + point[0]
    }
}

exports.rotateTwoPoints = function(twopoints, width, height, anticlockwise, isRect) {
    // Returns null on failure; twopoints is something like 'aa:cc'

    let [first, second] = extractTwoPoints(twopoints)
    first = exports.rotatePoint(first, width, height, anticlockwise)
    second = exports.rotatePoint(second, width, height, anticlockwise)
    if (first === null || second === null) return null

    // For a rectangle (e.g. anything except line / arrow) we
    // need to make the format topleft : bottomright

    if (isRect) {
        return fixedRectangle(first, second)
    } else {
        return first + ':' + second
    }
}

exports.rotateRect = function(twopoints, width, height, anticlockwise) {
    return exports.rotateTwoPoints(twopoints, width, height, anticlockwise, true)
}

exports.rotateArrow = function(twopoints, width, height, anticlockwise) {
    return exports.rotateTwoPoints(twopoints, width, height, anticlockwise, false)
}

exports.rotateTree = function(tree, width, height, anticlockwise) {
    return tree.mutate(draft => {
        for (let node of tree.listNodes()) {

            // 'simple' cases are either a single point (e.g. 'aa') or a rect (e.g. 'aa:cc')

            for (let key of simple) {
                if (node.data[key] == null) continue

                draft.updateProperty(node.id, key, node.data[key].map(value => {
                    if (value.length === 2) {
                        let result = exports.rotatePoint(value, width, height, anticlockwise)
                        if (result) return result
                    } else if (value.length === 5 && value[2] === ':') {
                        let result = exports.rotateRect(value, width, height, anticlockwise)
                        if (result) return result
                    }

                    return value
                }))
            }

            // 'pointWithText' means something like 'aa:hi there'

            for (let key of pointWithText) {
                if (node.data[key] == null) continue

                draft.updateProperty(node.id, key, node.data[key].map(value => {
                    if (value[2] === ':') {
                        let point = value.slice(0, 2)

                        point = exports.rotatePoint(point, width, height, anticlockwise)
                        if (point) return point + value.slice(2)
                    }

                    return value
                }))
            }

            // 'arrowish' things are formatted like rects, but with no requirement of topleft:bottomright

            for (let key of arrowish) {
                if (node.data[key] == null) continue

                draft.updateProperty(node.id, key, node.data[key].map(value => {
                    if (value[2] === ':') {
                        let result = exports.rotateArrow(value, width, height, anticlockwise)
                        if (result) return result
                    }

                    return value
                }))
            }
        }

        if (draft.root.data.SZ != null && draft.root.data.SZ[0].includes(':')) {
            draft.updateProperty(draft.root.id, 'SZ', [draft.root.data.SZ[0].split(':').reverse().join(':')])
        }
    })
}

exports.flipPoint = function(point, width, height, horizontal) {
    // Returns null on failure; point is something like 'ae'

    let [x, y] = pointIntegers(point, width, height)
    if (x === null || y === null) return null

    if (horizontal) {
        let rev = alphaRev.slice(52 - width)
        return rev[x] + point[1]
    } else {
        let rev = alphaRev.slice(52 - height)
        return point[0] + rev[y]
    }
}

exports.flipTwoPoints = function(twopoints, width, height, horizontal, isRect) {
    // Returns null on failure; twopoints is something like 'aa:cc'

    let [first, second] = extractTwoPoints(twopoints)
    first = exports.flipPoint(first, width, height, horizontal)
    second = exports.flipPoint(second, width, height, horizontal)
    if (first === null || second === null) return null

    // For a rectangle (e.g. anything except line / arrow) we
    // need to make the format topleft : bottomright

    if (isRect) {
        return fixedRectangle(first, second)
    } else {
        return first + ':' + second
    }
}

exports.flipRect = function(twopoints, width, height, horizontal) {
    return exports.flipTwoPoints(twopoints, width, height, horizontal, true)
}

exports.flipArrow = function(twopoints, width, height, horizontal) {
    return exports.flipTwoPoints(twopoints, width, height, horizontal, false)
}

exports.flipTree = function(tree, width, height, horizontal) {
    return tree.mutate(draft => {
        for (let node of tree.listNodes()) {

            for (let key of simple) {
                if (node.data[key] == null) continue

                draft.updateProperty(node.id, key, node.data[key].map(value => {
                    if (value.length === 2) {
                        let result = exports.flipPoint(value, width, height, horizontal)
                        if (result) return result
                    } else if (value.length === 5 && value[2] === ':') {
                        let result = exports.flipRect(value, width, height, horizontal)
                        if (result) return result
                    }

                    return value
                }))
            }

            // 'pointWithText' means something like 'aa:hi there'

            for (let key of pointWithText) {
                if (node.data[key] == null) continue

                draft.updateProperty(node.id, key, node.data[key].map(value => {
                    if (value[2] === ':') {
                        let point = value.slice(0, 2)

                        point = exports.flipPoint(point, width, height, horizontal)
                        if (point) return point + value.slice(2)
                    }

                    return value
                }))
            }

            // 'arrowish' things are formatted like rects, but with no requirement of topleft:bottomright

            for (let key of arrowish) {
                if (node.data[key] == null) continue

                draft.updateProperty(node.id, key, node.data[key].map(value => {
                    if (value[2] === ':') {
                        let result = exports.flipArrow(value, width, height, horizontal)
                        if (result) return result
                    }

                    return value
                }))
            }
        }
    })
}

exports.swapTreeColors = function(tree) {
    return tree.mutate(draft => {
        for (let node of tree.listNodes()) {

        	let newProperties = Object.create(null)

        	for (let key of Object.keys(colorSwapMap)) {
        		let data = node.data[key]
        		if (data == null) {
        			continue
        		}
        		let newKey = colorSwapMap[key]
        		newProperties[newKey] = data
        		draft.removeProperty(node.id, key)		// Get rid of the old property
        	}

        	for (let key of Object.keys(newProperties)) {
        		draft.updateProperty(node.id, key, newProperties[key])
        	}
        }
    })
}
<commit_msg>Convert indentation to spaces<commit_after>const simple = ['AB', 'AW', 'AE', 'B', 'CR', 'DD', 'MA', 'SL', 'SQ', 'TB', 'TR', 'TW', 'VW', 'W']
const pointWithText = ['LB']
const arrowish = ['AR', 'LN']

const alpha = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
const alphaRev = [...alpha].reverse()

const colorSwapMap = {
    'AB': 'AW',
    'AW': 'AB',
    'B': 'W',
    'W': 'B',
}

// Special functions that return the "min" and "max"
// for the SGF coordinate system...
//
// a-z : 0-25
// A-Z : 26-51
//
// Note that lowercase has higher ASCII value,
// but is considered lower in the SGF system.

function min(one, two) {
    // In case exactly one is lowercase, return it...

    if (one >= 'a' && two <= 'Z') return one
    if (one <= 'Z' && two >= 'a') return two

    // Same case...

    if (one < two) return one
    return two
}

function max(one, two) {
    if (one >= 'a' && two <= 'Z') return two
    if (one <= 'Z' && two >= 'a') return one
    if (one < two) return two
    return one
}

function pointIntegers(point, width, height) {
    // point is something like 'ae'
    // Returns [null, null] on failure; otherwise returns something like [0,4]

    if (typeof point !== 'string' || point.length !== 2) return [null, null]
    let index0 = alpha.indexOf(point[0])
    let index1 = alpha.indexOf(point[1])
    if (index0 === -1 || index1 === -1 || index0 >= width || index1 >= height) return [null, null]
    return [index0, index1]
}

function extractTwoPoints(s) {
    // s is something like 'aa:cc'
    // Returns [null, null] on failure; otherwise returns something like ['aa','cc']

    if (typeof s !== 'string' || s.length !== 5 || s[2] !== ':') return [null, null]
    return [s.slice(0, 2), s.slice(3, 5)]
}

function fixedRectangle(first, second) {
    // Given two SGF formatted corners of a rectangle, e.g. 'ch' and 'fc',
    // return a string using top-left : bottom-right format, e.g. 'cc:fh'

    return min(first[0], second[0]) + min(first[1], second[1])
    + ':' + max(first[0], second[0]) + max(first[1], second[1])
}

exports.rotatePoint = function(point, width, height, anticlockwise) {
    // Returns null on failure; point is something like 'ae'

    let [x, y] = pointIntegers(point, width, height)
    if (x === null || y === null) return null

    if (anticlockwise) {
        let rev = alphaRev.slice(52 - width)
        return point[1] + rev[x]
    } else {
        let rev = alphaRev.slice(52 - height)
        return rev[y] + point[0]
    }
}

exports.rotateTwoPoints = function(twopoints, width, height, anticlockwise, isRect) {
    // Returns null on failure; twopoints is something like 'aa:cc'

    let [first, second] = extractTwoPoints(twopoints)
    first = exports.rotatePoint(first, width, height, anticlockwise)
    second = exports.rotatePoint(second, width, height, anticlockwise)
    if (first === null || second === null) return null

    // For a rectangle (e.g. anything except line / arrow) we
    // need to make the format topleft : bottomright

    if (isRect) {
        return fixedRectangle(first, second)
    } else {
        return first + ':' + second
    }
}

exports.rotateRect = function(twopoints, width, height, anticlockwise) {
    return exports.rotateTwoPoints(twopoints, width, height, anticlockwise, true)
}

exports.rotateArrow = function(twopoints, width, height, anticlockwise) {
    return exports.rotateTwoPoints(twopoints, width, height, anticlockwise, false)
}

exports.rotateTree = function(tree, width, height, anticlockwise) {
    return tree.mutate(draft => {
        for (let node of tree.listNodes()) {

            // 'simple' cases are either a single point (e.g. 'aa') or a rect (e.g. 'aa:cc')

            for (let key of simple) {
                if (node.data[key] == null) continue

                draft.updateProperty(node.id, key, node.data[key].map(value => {
                    if (value.length === 2) {
                        let result = exports.rotatePoint(value, width, height, anticlockwise)
                        if (result) return result
                    } else if (value.length === 5 && value[2] === ':') {
                        let result = exports.rotateRect(value, width, height, anticlockwise)
                        if (result) return result
                    }

                    return value
                }))
            }

            // 'pointWithText' means something like 'aa:hi there'

            for (let key of pointWithText) {
                if (node.data[key] == null) continue

                draft.updateProperty(node.id, key, node.data[key].map(value => {
                    if (value[2] === ':') {
                        let point = value.slice(0, 2)

                        point = exports.rotatePoint(point, width, height, anticlockwise)
                        if (point) return point + value.slice(2)
                    }

                    return value
                }))
            }

            // 'arrowish' things are formatted like rects, but with no requirement of topleft:bottomright

            for (let key of arrowish) {
                if (node.data[key] == null) continue

                draft.updateProperty(node.id, key, node.data[key].map(value => {
                    if (value[2] === ':') {
                        let result = exports.rotateArrow(value, width, height, anticlockwise)
                        if (result) return result
                    }

                    return value
                }))
            }
        }

        if (draft.root.data.SZ != null && draft.root.data.SZ[0].includes(':')) {
            draft.updateProperty(draft.root.id, 'SZ', [draft.root.data.SZ[0].split(':').reverse().join(':')])
        }
    })
}

exports.flipPoint = function(point, width, height, horizontal) {
    // Returns null on failure; point is something like 'ae'

    let [x, y] = pointIntegers(point, width, height)
    if (x === null || y === null) return null

    if (horizontal) {
        let rev = alphaRev.slice(52 - width)
        return rev[x] + point[1]
    } else {
        let rev = alphaRev.slice(52 - height)
        return point[0] + rev[y]
    }
}

exports.flipTwoPoints = function(twopoints, width, height, horizontal, isRect) {
    // Returns null on failure; twopoints is something like 'aa:cc'

    let [first, second] = extractTwoPoints(twopoints)
    first = exports.flipPoint(first, width, height, horizontal)
    second = exports.flipPoint(second, width, height, horizontal)
    if (first === null || second === null) return null

    // For a rectangle (e.g. anything except line / arrow) we
    // need to make the format topleft : bottomright

    if (isRect) {
        return fixedRectangle(first, second)
    } else {
        return first + ':' + second
    }
}

exports.flipRect = function(twopoints, width, height, horizontal) {
    return exports.flipTwoPoints(twopoints, width, height, horizontal, true)
}

exports.flipArrow = function(twopoints, width, height, horizontal) {
    return exports.flipTwoPoints(twopoints, width, height, horizontal, false)
}

exports.flipTree = function(tree, width, height, horizontal) {
    return tree.mutate(draft => {
        for (let node of tree.listNodes()) {

            for (let key of simple) {
                if (node.data[key] == null) continue

                draft.updateProperty(node.id, key, node.data[key].map(value => {
                    if (value.length === 2) {
                        let result = exports.flipPoint(value, width, height, horizontal)
                        if (result) return result
                    } else if (value.length === 5 && value[2] === ':') {
                        let result = exports.flipRect(value, width, height, horizontal)
                        if (result) return result
                    }

                    return value
                }))
            }

            // 'pointWithText' means something like 'aa:hi there'

            for (let key of pointWithText) {
                if (node.data[key] == null) continue

                draft.updateProperty(node.id, key, node.data[key].map(value => {
                    if (value[2] === ':') {
                        let point = value.slice(0, 2)

                        point = exports.flipPoint(point, width, height, horizontal)
                        if (point) return point + value.slice(2)
                    }

                    return value
                }))
            }

            // 'arrowish' things are formatted like rects, but with no requirement of topleft:bottomright

            for (let key of arrowish) {
                if (node.data[key] == null) continue

                draft.updateProperty(node.id, key, node.data[key].map(value => {
                    if (value[2] === ':') {
                        let result = exports.flipArrow(value, width, height, horizontal)
                        if (result) return result
                    }

                    return value
                }))
            }
        }
    })
}

exports.swapTreeColors = function(tree) {
    return tree.mutate(draft => {
        for (let node of tree.listNodes()) {

            let newProperties = Object.create(null)

            for (let key of Object.keys(colorSwapMap)) {
                let data = node.data[key]
                if (data == null) {
                    continue
                }
                let newKey = colorSwapMap[key]
                newProperties[newKey] = data
                draft.removeProperty(node.id, key)      // Get rid of the old property
            }

            for (let key of Object.keys(newProperties)) {
                draft.updateProperty(node.id, key, newProperties[key])
            }
        }
    })
}
<|endoftext|>


<commit_before>/* eslint-disable react/prefer-stateless-function */
import React from 'react';
import { Actions, Scene } from 'react-native-router-flux';
import Home from '../containers/home/Home';
import AppConfig from '../constants/config';
import AppSizes from '../theme/sizes';
import AppStyles from '../theme/styles';
import Community from '../containers/community/Community';
import UserCenter from '../containers/user-center/UserCenter';
import AboutUs from '../containers/user-center/about-us/AboutUs';
import ContributorProfile from '../containers/user-center/about-us/ContributorProfile';
import Discover from '../containers/discover/Discover';
import RoadmapList from '../containers/discover/roadmap-list/RoadmapList';
import RoadmapDetail from '../containers/discover/roadmap-detail/RoadmapDetail';
import ProjectList from '../containers/discover/project-list/ProjectList';
import ProjectDetail from '../containers/discover/project-detail/ProjectDetail';
import ToolBoxList from '../containers/discover/toolbox-list/ToolBoxList';
import ToolBoxDetail from '../containers/discover/toolbox-detail/ToolBoxDetail';
import ArticleList from '../containers/discover/article-list/ArticleList';
import ArticleDetail from '../containers/discover/article-detail/ArticleDetail';
import ExamList from '../containers/discover/exam-list/ExamList';
import ExamDetail from '../containers/discover/exam-detail/ExamDetail';
import Solution from '../containers/discover/solution/Solution';
import SolutionDetail from '../containers/discover/solution-detail/SolutionDetail';
import ThoughtworksBooks from '../containers/discover/thoughtworks-books/ThoughtworksBooks';
import RecommendBooks from '../containers/discover/recommend-books/RecommendBooks';
import RecommendArticles from '../containers/discover/recommend-articles/RecommendArticles';
import TodoLists from '../containers/discover/todo-lists/TodoLists';
import ChapterList from '../containers/discover/chapter-list/ChapterList';
import SkillTree from '../containers/skill-tree/SkillTree';
import SkillDetailView from '../containers/skill-tree/SkillDetailView';
import ComingSoonView from '../containers/ComingSoonView';
import Helper from '../utils/helper';
import TabIcon from '../components/TabIcon';
import Practises from '../containers/practises/Practises';
import GrEditor from '../components/GrEditor';

const navbarPropsTabs = {
  ...AppConfig.navbarProps,
  sceneStyle: {
    ...AppConfig.navbarProps.sceneStyle,
    paddingBottom: AppSizes.tabbarHeight,
  },
};

export default Actions.create(
  <Scene key="root" {...AppConfig.navbarProps}>
    <Scene key="tabs" initial={'tabBar'} tabs tabBarIconContainerStyle={AppStyles.tabbar} pressOpacity={0.95}>
      <Scene
        {...navbarPropsTabs}
        key={'home'}
        title={'Growth'}
        iconName={'md-home'}
        iconType={'ionicon'}
        leftTitle={'用户中心'}
        renderLeftButton={() => Helper.gotoUserCenter()}
        rightTitle={'购买纸质版'}
        onRight={() => Actions.comingSoon()}
        rightButtonTextStyle={AppStyles.navbarTitle}
        icon={TabIcon}
        component={Home}
      />
      <Scene
        {...navbarPropsTabs}
        key={'discover'}
        title={'探索'}
        iconName={'md-compass'}
        iconType={'ionicon'}
        icon={TabIcon}
        component={Discover}
      />
      <Scene
        {...navbarPropsTabs}
        key={'skillTree'}
        title={'技能树'}
        rightTitle={'获取专业版'}
        onRight={() => Helper.getProfessionalSkilltree()}
        rightButtonTextStyle={AppStyles.navbarTitle}
        iconName={'md-egg'}
        iconType={'ionicon'}
        icon={TabIcon}
        component={SkillTree}
      />
      <Scene
        {...navbarPropsTabs}
        key={'community'}
        title={'社区'}
        iconName={'md-people'}
        iconType={'ionicon'}
        icon={TabIcon}
        component={Community}
      />
      <Scene
        {...navbarPropsTabs}
        key={'practises'}
        title={'练习'}
        iconName={'md-bonfire'}
        iconType={'ionicon'}
        icon={TabIcon}
        rightTitle={'编辑器'}
        onRight={() => Actions.grEditor()}
        rightButtonTextStyle={AppStyles.navbarTitle}
        component={Practises}
      />
    </Scene>

    <Scene
      {...AppConfig.navbarProps}
      key={'userCenter'}
      title={'用户中心'}
      component={UserCenter}
    />

    <Scene
      {...AppConfig.navbarProps}
      key={'skillDetail'}
      title={'技能'}
      component={SkillDetailView}
    />

    <Scene
      key={'comingSoon'}
      title={'Coming Soon'}
      component={ComingSoonView}
    />

    <Scene
      key={'roadmapList'}
      title={'学习路线'}
      duration={0}
      component={RoadmapList}
    />

    <Scene
      key={'roadmapDetail'}
      duration={0}
      component={RoadmapDetail}
    />

    <Scene
      key={'projectList'}
      duration={0}
      title={'练手项目'}
      component={ProjectList}
    />

    <Scene
      key={'projectDetail'}
      duration={0}
      component={ProjectDetail}
    />

    <Scene
      key={'toolBoxList'}
      duration={0}
      title={'工具箱'}
      component={ToolBoxList}
    />

    <Scene
      key={'toolBoxDetail'}
      duration={0}
      title={'工具箱'}
      component={ToolBoxDetail}
    />

    <Scene
      key={'articleList'}
      duration={0}
      title={'文章推荐'}
      component={ArticleList}
    />

    <Scene
      key={'articleDetail'}
      duration={0}
      title={'文章详情'}
      component={ArticleDetail}
    />

    <Scene
      key={'examList'}
      duration={0}
      title={'技能测验'}
      component={ExamList}
    />

    <Scene
      key={'examDetail'}
      duration={0}
      hideNavBar
      component={ExamDetail}
    />

    <Scene
      key={'solution'}
      duration={0}
      title={'解决方案'}
      component={Solution}
    />

    <Scene
      key={'solutionDetail'}
      duration={0}
      title={'解决方案'}
      component={SolutionDetail}
    />

    <Scene
      key={'thoughtworksBooks'}
      duration={0}
      title={'ThoughtWorks读书路线'}
      component={ThoughtworksBooks}
    />

    <Scene
      key={'recommendBooks'}
      duration={0}
      title={'推荐书籍'}
      component={RecommendBooks}
    />

    <Scene
      key={'recommendArticles'}
      duration={0}
      title={'推荐文章'}
      component={RecommendArticles}
    />

    <Scene
      key={'todoLists'}
      duration={0}
      title={'待办事项'}
      component={TodoLists}
    />

    <Scene
      key={'chapterList'}
      duration={0}
      title={'ChapterList'}
      component={ChapterList}
    />

    <Scene
      key={'aboutUs'}
      title={'关于'}
      component={AboutUs}
    />

    <Scene
      key={'contributorProfile'}
      title={'Contributor Profile'}
      component={ContributorProfile}
    />

    <Scene
      {...navbarPropsTabs}
      key={'grEditor'}
      duration={500}
      title={'编辑器'}
      rightTitle={'Run'}
      rightButtonTextStyle={AppStyles.navbarTitle}
      onRight={() => GrEditor.runCode()}
      component={GrEditor}
    />

  </Scene>,
);
<commit_msg>[T] navigation: add domain detial page action<commit_after>/* eslint-disable react/prefer-stateless-function */
import React from 'react';
import { Actions, Scene } from 'react-native-router-flux';
import Home from '../containers/home/Home';
import AppConfig from '../constants/config';
import AppSizes from '../theme/sizes';
import AppStyles from '../theme/styles';
import Community from '../containers/community/Community';
import UserCenter from '../containers/user-center/UserCenter';
import AboutUs from '../containers/user-center/about-us/AboutUs';
import ContributorProfile from '../containers/user-center/about-us/ContributorProfile';
import Discover from '../containers/discover/Discover';
import RoadmapList from '../containers/discover/roadmap-list/RoadmapList';
import RoadmapDetail from '../containers/discover/roadmap-detail/RoadmapDetail';
import ProjectList from '../containers/discover/project-list/ProjectList';
import ProjectDetail from '../containers/discover/project-detail/ProjectDetail';
import ToolBoxList from '../containers/discover/toolbox-list/ToolBoxList';
import ToolBoxDetail from '../containers/discover/toolbox-detail/ToolBoxDetail';
import ArticleList from '../containers/discover/article-list/ArticleList';
import ArticleDetail from '../containers/discover/article-detail/ArticleDetail';
import ExamList from '../containers/discover/exam-list/ExamList';
import ExamDetail from '../containers/discover/exam-detail/ExamDetail';
import Solution from '../containers/discover/solution/Solution';
import SolutionDetail from '../containers/discover/solution-detail/SolutionDetail';
import ThoughtworksBooks from '../containers/discover/thoughtworks-books/ThoughtworksBooks';
import DomainDetailPage from '../containers/discover/thoughtworks-books/domain-detail-page/DomainDetailPage';
import RecommendBooks from '../containers/discover/recommend-books/RecommendBooks';
import RecommendArticles from '../containers/discover/recommend-articles/RecommendArticles';
import TodoLists from '../containers/discover/todo-lists/TodoLists';
import ChapterList from '../containers/discover/chapter-list/ChapterList';
import SkillTree from '../containers/skill-tree/SkillTree';
import SkillDetailView from '../containers/skill-tree/SkillDetailView';
import ComingSoonView from '../containers/ComingSoonView';
import Helper from '../utils/helper';
import TabIcon from '../components/TabIcon';
import Practises from '../containers/practises/Practises';
import GrEditor from '../components/GrEditor';

const navbarPropsTabs = {
  ...AppConfig.navbarProps,
  sceneStyle: {
    ...AppConfig.navbarProps.sceneStyle,
    paddingBottom: AppSizes.tabbarHeight,
  },
};

export default Actions.create(
  <Scene key="root" {...AppConfig.navbarProps}>
    <Scene key="tabs" initial={'tabBar'} tabs tabBarIconContainerStyle={AppStyles.tabbar} pressOpacity={0.95}>
      <Scene
        {...navbarPropsTabs}
        key={'home'}
        title={'Growth'}
        iconName={'md-home'}
        iconType={'ionicon'}
        leftTitle={'用户中心'}
        renderLeftButton={() => Helper.gotoUserCenter()}
        rightTitle={'购买纸质版'}
        onRight={() => Actions.comingSoon()}
        rightButtonTextStyle={AppStyles.navbarTitle}
        icon={TabIcon}
        component={Home}
      />
      <Scene
        {...navbarPropsTabs}
        key={'discover'}
        title={'探索'}
        iconName={'md-compass'}
        iconType={'ionicon'}
        icon={TabIcon}
        component={Discover}
      />
      <Scene
        {...navbarPropsTabs}
        key={'skillTree'}
        title={'技能树'}
        rightTitle={'获取专业版'}
        onRight={() => Helper.getProfessionalSkilltree()}
        rightButtonTextStyle={AppStyles.navbarTitle}
        iconName={'md-egg'}
        iconType={'ionicon'}
        icon={TabIcon}
        component={SkillTree}
      />
      <Scene
        {...navbarPropsTabs}
        key={'community'}
        title={'社区'}
        iconName={'md-people'}
        iconType={'ionicon'}
        icon={TabIcon}
        component={Community}
      />
      <Scene
        {...navbarPropsTabs}
        key={'practises'}
        title={'练习'}
        iconName={'md-bonfire'}
        iconType={'ionicon'}
        icon={TabIcon}
        rightTitle={'编辑器'}
        onRight={() => Actions.grEditor()}
        rightButtonTextStyle={AppStyles.navbarTitle}
        component={Practises}
      />
    </Scene>

    <Scene
      {...AppConfig.navbarProps}
      key={'userCenter'}
      title={'用户中心'}
      component={UserCenter}
    />

    <Scene
      {...AppConfig.navbarProps}
      key={'skillDetail'}
      title={'技能'}
      component={SkillDetailView}
    />

    <Scene
      key={'comingSoon'}
      title={'Coming Soon'}
      component={ComingSoonView}
    />

    <Scene
      key={'roadmapList'}
      title={'学习路线'}
      duration={0}
      component={RoadmapList}
    />

    <Scene
      key={'roadmapDetail'}
      duration={0}
      component={RoadmapDetail}
    />

    <Scene
      key={'projectList'}
      duration={0}
      title={'练手项目'}
      component={ProjectList}
    />

    <Scene
      key={'projectDetail'}
      duration={0}
      component={ProjectDetail}
    />

    <Scene
      key={'toolBoxList'}
      duration={0}
      title={'工具箱'}
      component={ToolBoxList}
    />

    <Scene
      key={'toolBoxDetail'}
      duration={0}
      title={'工具箱'}
      component={ToolBoxDetail}
    />

    <Scene
      key={'articleList'}
      duration={0}
      title={'文章推荐'}
      component={ArticleList}
    />

    <Scene
      key={'articleDetail'}
      duration={0}
      title={'文章详情'}
      component={ArticleDetail}
    />

    <Scene
      key={'examList'}
      duration={0}
      title={'技能测验'}
      component={ExamList}
    />

    <Scene
      key={'examDetail'}
      duration={0}
      hideNavBar
      component={ExamDetail}
    />

    <Scene
      key={'solution'}
      duration={0}
      title={'解决方案'}
      component={Solution}
    />

    <Scene
      key={'solutionDetail'}
      duration={0}
      title={'解决方案'}
      component={SolutionDetail}
    />

    <Scene
      key={'thoughtworksBooks'}
      duration={0}
      title={'ThoughtWorks读书路线'}
      component={ThoughtworksBooks}
    />

    <Scene
      key={'domainDetailPage'}
      duration={0}
      component={DomainDetailPage}
    />

    <Scene
      key={'recommendBooks'}
      duration={0}
      title={'推荐书籍'}
      component={RecommendBooks}
    />

    <Scene
      key={'recommendArticles'}
      duration={0}
      title={'推荐文章'}
      component={RecommendArticles}
    />

    <Scene
      key={'todoLists'}
      duration={0}
      title={'待办事项'}
      component={TodoLists}
    />

    <Scene
      key={'chapterList'}
      duration={0}
      title={'ChapterList'}
      component={ChapterList}
    />

    <Scene
      key={'aboutUs'}
      title={'关于'}
      component={AboutUs}
    />

    <Scene
      key={'contributorProfile'}
      title={'Contributor Profile'}
      component={ContributorProfile}
    />

    <Scene
      {...navbarPropsTabs}
      key={'grEditor'}
      duration={500}
      title={'编辑器'}
      rightTitle={'Run'}
      rightButtonTextStyle={AppStyles.navbarTitle}
      onRight={() => GrEditor.runCode()}
      component={GrEditor}
    />

  </Scene>,
);
<|endoftext|>


<commit_before>/* eslint-disable react/prefer-stateless-function */
import React from 'react';
import { Actions, Scene } from 'react-native-router-flux';
import Home from '../containers/home/Home';
import AppConfig from '../constants/config';
import AppSizes from '../theme/sizes';
import AppStyles from '../theme/styles';
import Community from '../containers/community/Community';
import UserCenter from '../containers/user-center/UserCenter';
import AboutUs from '../containers/user-center/AboutUs';
import Discover from '../containers/discover/Discover';
import RoadmapList from '../containers/discover/roadmap-list/RoadmapList';
import RoadmapDetail from '../containers/discover/roadmap-detail/RoadmapDetail';
import ProjectList from '../containers/discover/project-list/ProjectList';
import ProjectDetail from '../containers/discover/project-detail/ProjectDetail';
import ToolBoxList from '../containers/discover/toolbox-list/ToolBoxList';
import ToolBoxDetail from '../containers/discover/toolbox-detail/ToolBoxDetail';
import ArticleList from '../containers/discover/article-list/ArticleList';
import ArticleDetail from '../containers/discover/article-detail/ArticleDetail';
import ExamList from '../containers/discover/exam-list/ExamList';
import Solution from '../containers/discover/solution/Solution';
import ThoughtworksBooks from '../containers/discover/thoughtworks-books/ThoughtworksBooks';
import RecommendBooks from '../containers/discover/recommend-books/RecommendBooks';
import RecommendArticles from '../containers/discover/recommend-articles/RecommendArticles';
import TodoLists from '../containers/discover/todo-lists/TodoLists';
import ChapterList from '../containers/discover/chapter-list/ChapterList';
import SkillTree from '../containers/skill-tree/SkillTree';
import SkillDetailView from '../containers/skill-tree/SkillDetailView';
import ComingSoonView from '../containers/ComingSoonView';
import Helper from '../utils/helper';
import TabIcon from '../components/TabIcon';
import Practises from '../containers/practises/Practises';
import GrEditor from '../components/GrEditor';

const navbarPropsTabs = {
  ...AppConfig.navbarProps,
  sceneStyle: {
    ...AppConfig.navbarProps.sceneStyle,
    paddingBottom: AppSizes.tabbarHeight,
  },
};

export default Actions.create(
  <Scene key="root" {...AppConfig.navbarProps}>
    <Scene key="tabs" initial={'tabBar'} tabs tabBarIconContainerStyle={AppStyles.tabbar} pressOpacity={0.95}>
      <Scene
        {...navbarPropsTabs}
        key={'home'}
        title={'Growth'}
        iconName={'md-home'}
        iconType={'ionicon'}
        leftTitle={'用户中心'}
        renderLeftButton={() => Helper.gotoUserCenter()}
        rightTitle={'购买纸质版'}
        onRight={() => Actions.comingSoon()}
        rightButtonTextStyle={AppStyles.navbarTitle}
        icon={TabIcon}
        component={Home}
      />
      <Scene
        {...navbarPropsTabs}
        key={'discover'}
        title={'探索'}
        iconName={'md-compass'}
        iconType={'ionicon'}
        icon={TabIcon}
        component={Discover}
      />
      <Scene
        {...navbarPropsTabs}
        key={'skillTree'}
        title={'技能树'}
        rightTitle={'获取专业版'}
        onRight={() => Helper.getProfessionalSkilltree()}
        rightButtonTextStyle={AppStyles.navbarTitle}
        iconName={'md-egg'}
        iconType={'ionicon'}
        icon={TabIcon}
        component={SkillTree}
      />
      <Scene
        {...navbarPropsTabs}
        key={'community'}
        title={'社区'}
        iconName={'md-people'}
        iconType={'ionicon'}
        icon={TabIcon}
        component={Community}
      />
      <Scene
        {...navbarPropsTabs}
        key={'practises'}
        title={'练习'}
        iconName={'md-bonfire'}
        iconType={'ionicon'}
        icon={TabIcon}
        rightTitle={'编辑器'}
        onRight={() => Actions.grEditor()}
        rightButtonTextStyle={AppStyles.navbarTitle}
        component={Practises}
      />
    </Scene>

    <Scene
      {...navbarPropsTabs}
      key={'userCenter'}
      title={'用户中心'}
      component={UserCenter}
    />

    <Scene
      {...navbarPropsTabs}
      key={'skillDetail'}
      title={'技能'}
      component={SkillDetailView}
    />

    <Scene
      key={'comingSoon'}
      title={'Coming Soon'}
      component={ComingSoonView}
    />

    <Scene
      key={'roadmapList'}
      title={'学习路线'}
      duration={0}
      component={RoadmapList}
    />

    <Scene
      key={'roadmapDetail'}
      duration={0}
      component={RoadmapDetail}
    />

    <Scene
      key={'projectList'}
      duration={0}
      title={'练手项目'}
      component={ProjectList}
    />

    <Scene
      key={'projectDetail'}
      duration={0}
      component={ProjectDetail}
    />

    <Scene
      key={'toolBoxList'}
      duration={0}
      title={'工具箱'}
      component={ToolBoxList}
    />

    <Scene
      key={'toolBoxDetail'}
      duration={0}
      title={'工具箱'}
      component={ToolBoxDetail}
    />

    <Scene
      key={'articleList'}
      duration={0}
      title={'文章推荐'}
      component={ArticleList}
    />

    <Scene
      key={'articleDetail'}
      duration={0}
      title={'文章详情'}
      component={ArticleDetail}
    />

    <Scene
      key={'examList'}
      duration={0}
      title={'技能测验'}
      component={ExamList}
    />
    <Scene
      key={'solution'}
      duration={0}
      title={'解决方案'}
      component={Solution}
    />

    <Scene
      key={'thoughtworksBooks'}
      duration={0}
      title={'ThoughtWorks读书路线'}
      component={ThoughtworksBooks}
    />

    <Scene
      key={'recommendBooks'}
      duration={0}
      title={'推荐书籍'}
      component={RecommendBooks}
    />

    <Scene
      key={'recommendArticles'}
      duration={0}
      title={'推荐文章'}
      component={RecommendArticles}
    />

    <Scene
      key={'todoLists'}
      duration={0}
      title={'待办事项'}
      component={TodoLists}
    />

    <Scene
      key={'chapterList'}
      duration={0}
      title={'ChapterList'}
      component={ChapterList}
    />

    <Scene
      key={'aboutUs'}
      duration={0}
      title={'关于'}
      component={AboutUs}
    />

    <Scene
      {...navbarPropsTabs}
      key={'grEditor'}
      duration={500}
      title={'编辑器'}
      rightTitle={'Run'}
      rightButtonTextStyle={AppStyles.navbarTitle}
      onRight={() => GrEditor.runCode()}
      component={GrEditor}
    />

  </Scene>,
);
<commit_msg>[T] navigation: add exam detail action<commit_after>/* eslint-disable react/prefer-stateless-function */
import React from 'react';
import { Actions, Scene } from 'react-native-router-flux';
import Home from '../containers/home/Home';
import AppConfig from '../constants/config';
import AppSizes from '../theme/sizes';
import AppStyles from '../theme/styles';
import Community from '../containers/community/Community';
import UserCenter from '../containers/user-center/UserCenter';
import AboutUs from '../containers/user-center/AboutUs';
import Discover from '../containers/discover/Discover';
import RoadmapList from '../containers/discover/roadmap-list/RoadmapList';
import RoadmapDetail from '../containers/discover/roadmap-detail/RoadmapDetail';
import ProjectList from '../containers/discover/project-list/ProjectList';
import ProjectDetail from '../containers/discover/project-detail/ProjectDetail';
import ToolBoxList from '../containers/discover/toolbox-list/ToolBoxList';
import ToolBoxDetail from '../containers/discover/toolbox-detail/ToolBoxDetail';
import ArticleList from '../containers/discover/article-list/ArticleList';
import ArticleDetail from '../containers/discover/article-detail/ArticleDetail';
import ExamList from '../containers/discover/exam-list/ExamList';
import ExamDetail from '../containers/discover/exam-detail/ExamDetail';
import Solution from '../containers/discover/solution/Solution';
import ThoughtworksBooks from '../containers/discover/thoughtworks-books/ThoughtworksBooks';
import RecommendBooks from '../containers/discover/recommend-books/RecommendBooks';
import RecommendArticles from '../containers/discover/recommend-articles/RecommendArticles';
import TodoLists from '../containers/discover/todo-lists/TodoLists';
import ChapterList from '../containers/discover/chapter-list/ChapterList';
import SkillTree from '../containers/skill-tree/SkillTree';
import SkillDetailView from '../containers/skill-tree/SkillDetailView';
import ComingSoonView from '../containers/ComingSoonView';
import Helper from '../utils/helper';
import TabIcon from '../components/TabIcon';
import Practises from '../containers/practises/Practises';
import GrEditor from '../components/GrEditor';

const navbarPropsTabs = {
  ...AppConfig.navbarProps,
  sceneStyle: {
    ...AppConfig.navbarProps.sceneStyle,
    paddingBottom: AppSizes.tabbarHeight,
  },
};

export default Actions.create(
  <Scene key="root" {...AppConfig.navbarProps}>
    <Scene key="tabs" initial={'tabBar'} tabs tabBarIconContainerStyle={AppStyles.tabbar} pressOpacity={0.95}>
      <Scene
        {...navbarPropsTabs}
        key={'home'}
        title={'Growth'}
        iconName={'md-home'}
        iconType={'ionicon'}
        leftTitle={'用户中心'}
        renderLeftButton={() => Helper.gotoUserCenter()}
        rightTitle={'购买纸质版'}
        onRight={() => Actions.comingSoon()}
        rightButtonTextStyle={AppStyles.navbarTitle}
        icon={TabIcon}
        component={Home}
      />
      <Scene
        {...navbarPropsTabs}
        key={'discover'}
        title={'探索'}
        iconName={'md-compass'}
        iconType={'ionicon'}
        icon={TabIcon}
        component={Discover}
      />
      <Scene
        {...navbarPropsTabs}
        key={'skillTree'}
        title={'技能树'}
        rightTitle={'获取专业版'}
        onRight={() => Helper.getProfessionalSkilltree()}
        rightButtonTextStyle={AppStyles.navbarTitle}
        iconName={'md-egg'}
        iconType={'ionicon'}
        icon={TabIcon}
        component={SkillTree}
      />
      <Scene
        {...navbarPropsTabs}
        key={'community'}
        title={'社区'}
        iconName={'md-people'}
        iconType={'ionicon'}
        icon={TabIcon}
        component={Community}
      />
      <Scene
        {...navbarPropsTabs}
        key={'practises'}
        title={'练习'}
        iconName={'md-bonfire'}
        iconType={'ionicon'}
        icon={TabIcon}
        rightTitle={'编辑器'}
        onRight={() => Actions.grEditor()}
        rightButtonTextStyle={AppStyles.navbarTitle}
        component={Practises}
      />
    </Scene>

    <Scene
      {...navbarPropsTabs}
      key={'userCenter'}
      title={'用户中心'}
      component={UserCenter}
    />

    <Scene
      {...navbarPropsTabs}
      key={'skillDetail'}
      title={'技能'}
      component={SkillDetailView}
    />

    <Scene
      key={'comingSoon'}
      title={'Coming Soon'}
      component={ComingSoonView}
    />

    <Scene
      key={'roadmapList'}
      title={'学习路线'}
      duration={0}
      component={RoadmapList}
    />

    <Scene
      key={'roadmapDetail'}
      duration={0}
      component={RoadmapDetail}
    />

    <Scene
      key={'projectList'}
      duration={0}
      title={'练手项目'}
      component={ProjectList}
    />

    <Scene
      key={'projectDetail'}
      duration={0}
      component={ProjectDetail}
    />

    <Scene
      key={'toolBoxList'}
      duration={0}
      title={'工具箱'}
      component={ToolBoxList}
    />

    <Scene
      key={'toolBoxDetail'}
      duration={0}
      title={'工具箱'}
      component={ToolBoxDetail}
    />

    <Scene
      key={'articleList'}
      duration={0}
      title={'文章推荐'}
      component={ArticleList}
    />

    <Scene
      key={'articleDetail'}
      duration={0}
      title={'文章详情'}
      component={ArticleDetail}
    />

    <Scene
      key={'examList'}
      duration={0}
      title={'技能测验'}
      component={ExamList}
    />

    <Scene
      key={'examDetail'}
      duration={0}
      hideNavBar
      component={ExamDetail}
    />

    <Scene
      key={'solution'}
      duration={0}
      title={'解决方案'}
      component={Solution}
    />

    <Scene
      key={'thoughtworksBooks'}
      duration={0}
      title={'ThoughtWorks读书路线'}
      component={ThoughtworksBooks}
    />

    <Scene
      key={'recommendBooks'}
      duration={0}
      title={'推荐书籍'}
      component={RecommendBooks}
    />

    <Scene
      key={'recommendArticles'}
      duration={0}
      title={'推荐文章'}
      component={RecommendArticles}
    />

    <Scene
      key={'todoLists'}
      duration={0}
      title={'待办事项'}
      component={TodoLists}
    />

    <Scene
      key={'chapterList'}
      duration={0}
      title={'ChapterList'}
      component={ChapterList}
    />

    <Scene
      key={'aboutUs'}
      duration={0}
      title={'关于'}
      component={AboutUs}
    />

    <Scene
      {...navbarPropsTabs}
      key={'grEditor'}
      duration={500}
      title={'编辑器'}
      rightTitle={'Run'}
      rightButtonTextStyle={AppStyles.navbarTitle}
      onRight={() => GrEditor.runCode()}
      component={GrEditor}
    />

  </Scene>,
);
<|endoftext|>


<commit_before>goog.provide('ol.FeatureLoader');
goog.provide('ol.featureloader');

goog.require('goog.asserts');
goog.require('goog.events');
goog.require('goog.net.EventType');
goog.require('goog.net.XhrIo');
goog.require('goog.net.XhrIo.ResponseType');
goog.require('ol.format.FormatType');
goog.require('ol.xml');

/**
 * @api
 * @typedef {function(this:ol.source.Vector, ol.Extent, number,
 *                    ol.proj.Projection)}
 */
ol.FeatureLoader;

/**
 * @param {string} url Feature URL service.
 * @param {ol.format.Feature} format Feature format.
 * @param {function(this:ol.source.Vector, Array.<ol.Feature>)} success
 *     Function called with the loaded features. Called with the vector
 *     source as `this`.
 * @return {ol.FeatureLoader} The feature loader.
 */
ol.featureloader.loadFeaturesXhr = function(url, format, success) {
  return (
      /**
       * @param {ol.Extent} extent Extent.
       * @param {number} resolution Resolution.
       * @param {ol.proj.Projection} projection Projection.
       * @this {ol.source.Vector}
       */
      function(extent, resolution, projection) {
        var xhrIo = new goog.net.XhrIo();
        xhrIo.setResponseType(goog.net.XhrIo.ResponseType.TEXT);
        goog.events.listen(xhrIo, goog.net.EventType.COMPLETE,
            /**
             * @param {Event} event Event.
             * @private
             * @this {ol.source.Vector}
             */
            function(event) {
              var xhrIo = event.target;
              goog.asserts.assertInstanceof(xhrIo, goog.net.XhrIo,
                  'event.target/xhrIo is an instance of goog.net.XhrIo');
              if (xhrIo.isSuccess()) {
                var type = format.getType();
                /** @type {Document|Node|Object|string|undefined} */
                var source;
                if (type == ol.format.FormatType.JSON) {
                  source = xhrIo.getResponseText();
                } else if (type == ol.format.FormatType.TEXT) {
                  source = xhrIo.getResponseText();
                } else if (type == ol.format.FormatType.XML) {
                  if (!goog.userAgent.IE) {
                    source = xhrIo.getResponseXml();
                  }
                  if (!goog.isDefAndNotNull(source)) {
                    source = ol.xml.parse(xhrIo.getResponseText());
                  }
                } else {
                  goog.asserts.fail('unexpected format type');
                }
                if (goog.isDefAndNotNull(source)) {
                  var features = format.readFeatures(source,
                      {featureProjection: projection});
                  success.call(this, features);
                } else {
                  goog.asserts.fail('undefined or null source');
                }
              } else {
                // FIXME
              }
              goog.dispose(xhrIo);
            }, false, this);
        xhrIo.send(url);
      });
};

/**
 * Create an XHR feature loader for a `url` and `format`. The feature loader
 * loads features (with XHR), parses the features, and adds them to the
 * vector source.
 * @param {string} url Feature URL service.
 * @param {ol.format.Feature} format Feature format.
 * @return {ol.FeatureLoader} The feature loader.
 * @api
 */
ol.featureloader.xhr = function(url, format) {
  return ol.featureloader.loadFeaturesXhr(url, format,
      /**
       * @param {Array.<ol.Feature>} features The loaded features.
       * @this {ol.source.Vector}
       */
      function(features) {
        this.addFeatures(features);
      });
};
<commit_msg>Testing xhrIo POST method.<commit_after>goog.provide('ol.FeatureLoader');
goog.provide('ol.featureloader');

goog.require('goog.asserts');
goog.require('goog.events');
goog.require('goog.net.EventType');
goog.require('goog.net.XhrIo');
goog.require('goog.net.XhrIo.ResponseType');
goog.require('ol.format.FormatType');
goog.require('ol.xml');

/**
 * @api
 * @typedef {function(this:ol.source.Vector, ol.Extent, number,
 *                    ol.proj.Projection)}
 */
ol.FeatureLoader;

/**
 * @param {string} url Feature URL service.
 * @param {ol.format.Feature} format Feature format.
 * @param {function(this:ol.source.Vector, Array.<ol.Feature>)} success
 *     Function called with the loaded features. Called with the vector
 *     source as `this`.
 * @return {ol.FeatureLoader} The feature loader.
 */
ol.featureloader.loadFeaturesXhr = function(url, format, success) {
  return (
      /**
       * @param {ol.Extent} extent Extent.
       * @param {number} resolution Resolution.
       * @param {ol.proj.Projection} projection Projection.
       * @this {ol.source.Vector}
       */
      function(extent, resolution, projection) {
        var xhrIo = new goog.net.XhrIo();
        xhrIo.setResponseType(goog.net.XhrIo.ResponseType.TEXT);
        goog.events.listen(xhrIo, goog.net.EventType.COMPLETE,
            /**
             * @param {Event} event Event.
             * @private
             * @this {ol.source.Vector}
             */
            function(event) {
              var xhrIo = event.target;
              goog.asserts.assertInstanceof(xhrIo, goog.net.XhrIo,
                  'event.target/xhrIo is an instance of goog.net.XhrIo');
              if (xhrIo.isSuccess()) {
                var type = format.getType();
                /** @type {Document|Node|Object|string|undefined} */
                var source;
                if (type == ol.format.FormatType.JSON) {
                  source = xhrIo.getResponseText();
                } else if (type == ol.format.FormatType.TEXT) {
                  source = xhrIo.getResponseText();
                } else if (type == ol.format.FormatType.XML) {
                  if (!goog.userAgent.IE) {
                    source = xhrIo.getResponseXml();
                  }
                  if (!goog.isDefAndNotNull(source)) {
                    source = ol.xml.parse(xhrIo.getResponseText());
                  }
                } else {
                  goog.asserts.fail('unexpected format type');
                }
                if (goog.isDefAndNotNull(source)) {
                  var features = format.readFeatures(source,
                      {featureProjection: projection});
                  success.call(this, features);
                } else {
                  goog.asserts.fail('undefined or null source');
                }
              } else {
                // FIXME
              }
              goog.dispose(xhrIo);
            }, false, this);
// FIXME: Let caller specify GET or POST.
//        [lb] is just testing for now.
        //xhrIo.send(url);
        xhrIo.send(url, 'POST', '{"test": "blah"}');
      });
};

/**
 * Create an XHR feature loader for a `url` and `format`. The feature loader
 * loads features (with XHR), parses the features, and adds them to the
 * vector source.
 * @param {string} url Feature URL service.
 * @param {ol.format.Feature} format Feature format.
 * @return {ol.FeatureLoader} The feature loader.
 * @api
 */
ol.featureloader.xhr = function(url, format) {
  return ol.featureloader.loadFeaturesXhr(url, format,
      /**
       * @param {Array.<ol.Feature>} features The loaded features.
       * @this {ol.source.Vector}
       */
      function(features) {
        this.addFeatures(features);
      });
};
<|endoftext|>


<commit_before>import eq from 'orbit/lib/eq';
import clone from 'orbit/lib/clone';

/**
 * Prototype extensions
 */
if (!Array.prototype.forEach) {
  Array.prototype.forEach = function (fn, scope) {
    var i, len;
    for (i = 0, len = this.length; i < len; ++i) {
      if (i in this) {
        fn.call(scope, this[i], i, this);
      }
    }
  };
}

/**
 * Orbit
 */
var Orbit = {
  idField: '__id',

  generateId: function() {
    if (this._newId) {
      this._newId++;
    } else {
      this._newId = 1;
    }
    return new Date().getTime() + '.' + this._newId;
  },

  versionField: '__ver',

  incrementVersion: function(record) {
    record[this.versionField] = this.generateId();
  },

  assert: function(desc, test) {
    if (!test) throw new Error("Assertion failed: " + desc);
  },

  capitalize: function(str) {
    return str.charAt(0).toUpperCase() + str.slice(1);
  },

  arrayToOptions: function(arr) {
    var options = {};
    if (arr) {
      for (var i in arr) {
        if (arr.hasOwnProperty(i)) options[arr[i]] = true;
      }
    }
    return options;
  },

  promisifyException: function(e) {
    return new Orbit.Promise(function(resolve, reject) {
      reject(e);
    });
  }
};

Orbit.NotFoundException = function(type, record) {
  this.type = type;
  this.record = record;
};
Orbit.NotFoundException.prototype = {
  constructor: 'NotFoundException'
};

Orbit.AlreadyExistsException = function(type, record) {
  this.type = type;
  this.record = record;
};
Orbit.AlreadyExistsException.prototype = {
  constructor: 'AlreadyExistsException'
};

export default Orbit;<commit_msg>Simplified versioning for easier traceability<commit_after>import eq from 'orbit/lib/eq';
import clone from 'orbit/lib/clone';

/**
 * Prototype extensions
 */
if (!Array.prototype.forEach) {
  Array.prototype.forEach = function (fn, scope) {
    var i, len;
    for (i = 0, len = this.length; i < len; ++i) {
      if (i in this) {
        fn.call(scope, this[i], i, this);
      }
    }
  };
}

/**
 * Orbit
 */
var Orbit = {
  idField: '__id',

  generateId: function() {
    if (this._newId) {
      this._newId++;
    } else {
      this._newId = 1;
    }
    return new Date().getTime() + '.' + this._newId;
  },

  versionField: '__ver',

  incrementVersion: function(record) {
    record[this.versionField] = this.newVersion();
  },

  newVersion: function() {
    // TODO - versioning scheme should work across sessions
    if (this._newVersion) {
      this._newVersion++;
    } else {
      this._newVersion = 1;
    }
    return this._newVersion;
  },

  assert: function(desc, test) {
    if (!test) throw new Error("Assertion failed: " + desc);
  },

  capitalize: function(str) {
    return str.charAt(0).toUpperCase() + str.slice(1);
  },

  arrayToOptions: function(arr) {
    var options = {};
    if (arr) {
      for (var i in arr) {
        if (arr.hasOwnProperty(i)) options[arr[i]] = true;
      }
    }
    return options;
  },

  promisifyException: function(e) {
    return new Orbit.Promise(function(resolve, reject) {
      reject(e);
    });
  }
};

Orbit.NotFoundException = function(type, record) {
  this.type = type;
  this.record = record;
};
Orbit.NotFoundException.prototype = {
  constructor: 'NotFoundException'
};

Orbit.AlreadyExistsException = function(type, record) {
  this.type = type;
  this.record = record;
};
Orbit.AlreadyExistsException.prototype = {
  constructor: 'AlreadyExistsException'
};

export default Orbit;<|endoftext|>


<commit_before>/**
 * Defines a model that loosely resembles the structure of a mongoose document property.
 * @mongoose-option - Denotes that the given value will be used to defined the mongoose SchemaType option of the same name.
 */

import mongoose from 'mongoose';
import ChimeraSchema from '../schema';

const { Mixed } = mongoose.Schema.Types;
const schema = new ChimeraSchema('ChimeraField', {
	/**
	 * The name that will be used to uniquely identify the property on the model.
	 * This will be set as the key value in the generated mongoose schema.
	 */
	name: {
		type: String,
		required: true
	},

	/**
	 * @mongoose-option
	 * A secondary name to use to reference the field.
	 */
	alias: {
		type: String,
		default: ''
	},

	/**
	 * @mongoose-option
	 * The primitive data-type for the contents of the field.
	 */
	type: {
		type: String,
		required: true,
		enum: Object.keys(mongoose.SchemaTypes)
	},

	/**
	 * @mongoose-option
	 * Used to enforce if this field should require a value (neither null nor undefined)
	*/
	required: {
		type: Mixed,
		default: false
	},

	/**
	 * @mongoose-option
	 * Used to specify a default value that should be set when this field is left blank.
	 */
	default: {
		type: Mixed,
		default: undefined
	},

	/**
	 * @mongoose-option
	 * Used to specify a validation scheme that should performed for this field
	 */
	validate: {
		type: Object,
		default: undefined
	},

	/**
	 * @mongoose-option
	 * Used to enforce unique values in the field by enabling unique indexing in the ODM
	 */
	unique: {
		type: Boolean,
		default: false
	},

	/**
	 * @mongoose-option
	 * Used to determine if this field should be indexed for quicker filtering.
	 */
	index: {
		type: Boolean,
		default: false
	}
})
	/** Associations */
	.belongsTo('ChimeraModel', {
		localField: 'chimeraModelId',
		as: 'chimeraModel'
	}, {
		required: true
	})

	/** Indexing */
	.index({ name: 1, chimeraModelId: 1 }, { unique: true });

export default schema;
<commit_msg>Convert validate to validators path.<commit_after>/**
 * Defines a model that loosely resembles the structure of a mongoose document property.
 * @mongoose-option - Denotes that the given value will be used to defined the mongoose SchemaType option of the same name.
 */

import mongoose from 'mongoose';
import ChimeraSchema from '../schema';

const { Mixed } = mongoose.Schema.Types;
const schema = new ChimeraSchema('ChimeraField', {
	/**
	 * The name that will be used to uniquely identify the property on the model.
	 * This will be set as the key value in the generated mongoose schema.
	 */
	name: {
		type: String,
		required: true
	},

	/**
	 * @mongoose-option
	 * A secondary name to use to reference the field.
	 */
	alias: {
		type: String,
		default: ''
	},

	/**
	 * @mongoose-option
	 * The primitive data-type for the contents of the field.
	 */
	type: {
		type: String,
		required: true,
		enum: Object.keys(mongoose.SchemaTypes)
	},

	/**
	 * @mongoose-option
	 * Used to enforce if this field should require a value (neither null nor undefined)
	*/
	required: {
		type: Mixed,
		default: false
	},

	/**
	 * @mongoose-option
	 * Used to specify a default value that should be set when this field is left blank.
	 */
	default: {
		type: Mixed,
		default: undefined
	},

	/**
	 * Used to specify a validation pattern that should be performed for this field
	 */
	validators: {
		type: Object,
		default: undefined
	},

	/**
	 * @mongoose-option
	 * Used to enforce unique values in the field by enabling unique indexing in the ODM
	 */
	unique: {
		type: Boolean,
		default: false
	},

	/**
	 * @mongoose-option
	 * Used to determine if this field should be indexed for quicker filtering.
	 */
	index: {
		type: Boolean,
		default: false
	}
})
	/** Associations */
	.belongsTo('ChimeraModel', {
		localField: 'chimeraModelId',
		as: 'chimeraModel'
	}, {
		required: true
	})

	/** Indexing */
	.index({ name: 1, chimeraModelId: 1 }, { unique: true });

export default schema;
<|endoftext|>


<commit_before>import React from 'react'
import Router from 'next/router'
import Cookies from 'js-cookie'
import { compose } from 'recompose'
import { FormattedMessage, intlShape } from 'react-intl'
import { Mutation } from 'react-apollo'

import { StaticLayout } from '../../components/layouts'
import { LoginForm } from '../../components/forms'
import { LoginMutation } from '../../graphql'
import { pageWithIntl, withData, withLogging } from '../../lib'

const propTypes = {
  intl: intlShape.isRequired,
}

const Login = ({ intl }) => (
  <StaticLayout
    pageTitle={intl.formatMessage({
      defaultMessage: 'Login',
      id: 'user.login.pageTitle',
    })}
  >

        <FormattedMessage defaultMessage="Login" id="user.login.title" />

      <Mutation mutation={LoginMutation}>
        {(login, { loading, error }) => (
          <React.Fragment>
            <LoginForm
              intl={intl}
              loading={loading}
              onSubmit={async ({ email, password }) => {
                // perform the login
                const { data } = await login({ variables: { email, password } })

                // save the user id in a cookie
                if (data.login) {
                  Cookies.set('userId', data.login)
                }

                // redirect to question pool
                Router.push('/questions')
              }}
            />
            {error &&
Login failed ({error.message})
}
          </React.Fragment>
        )}
      </Mutation>

  </StaticLayout>
)

Login.propTypes = propTypes

export default compose(
  withLogging({
    chatlio: false,
    logRocket: false,
  }),
  withData,
  pageWithIntl,
)(Login)
<commit_msg>Add password reset info<commit_after>import React from 'react'
import Router from 'next/router'
import Cookies from 'js-cookie'
import Link from 'next/link'
import { compose } from 'recompose'
import { FormattedMessage, intlShape } from 'react-intl'
import { Mutation } from 'react-apollo'
import { Message } from 'semantic-ui-react'

import { StaticLayout } from '../../components/layouts'
import { LoginForm } from '../../components/forms'
import { LoginMutation } from '../../graphql'
import { pageWithIntl, withData, withLogging } from '../../lib'

const propTypes = {
  intl: intlShape.isRequired,
}

const Login = ({ intl }) => (
  <StaticLayout
    pageTitle={intl.formatMessage({
      defaultMessage: 'Login',
      id: 'user.login.pageTitle',
    })}
  >

        <FormattedMessage defaultMessage="Login" id="user.login.title" />

      <Mutation mutation={LoginMutation}>
        {(login, { loading, error }) => (
          <React.Fragment>
            <Message info>
              <Message.Header>Public Beta</Message.Header>
              <Message.Content>
                To participate in the Klicker 2018 public beta, please{' '}
                <Link href="/user/requestPassword">reset your password</Link> first.
              </Message.Content>
            </Message>
            <LoginForm
              intl={intl}
              loading={loading}
              onSubmit={async ({ email, password }) => {
                // perform the login
                const { data } = await login({ variables: { email, password } })

                // save the user id in a cookie
                if (data.login) {
                  Cookies.set('userId', data.login)
                }

                // redirect to question pool
                Router.push('/questions')
              }}
            />
            {error &&
Login failed ({error.message})
}
          </React.Fragment>
        )}
      </Mutation>

  </StaticLayout>
)

Login.propTypes = propTypes

export default compose(
  withLogging({
    chatlio: false,
    logRocket: false,
  }),
  withData,
  pageWithIntl,
)(Login)
<|endoftext|>


<commit_before>#!/usr/bin/env node

// Modified from https://github.com/Khan/KAS,
// which is MIT licensed

var fs = require("fs");
var path = require("path");
var jison = require("jison");

var grammar = {
    lex: {
        rules: [
            ["\\s+",                '/* skip whitespace */'],

            ["==|!=|<|>|<=|>=",     'return "SIGN"'],

            ["\\*",                 'return "*"'],
            ["\\/",                 'return "/"'],
            ["-",                   'return "-"'],
            ["\\+",                 'return "+"'],
            ["\\%",                 'return "%"'],

            ["\\(",                 'return "("'],
            ["\\)",                 'return ")"'],
            ["\\{",                 'return "}"'],
            ["\\{",                 'return "}"'],
            ["\\|",                 'return "|"'],
            ["\\[",                 'return "["'],
            ["\\]",                 'return "]"'],

            ["=",                   'return "="'],
            ["\\n+",                'return "NEWLINE"'],
            ["\\!",                 'return "!"'],
            ["\\:",                 'return ":"'],

            ["var",                 'return "VARKEYWORD"'],
            ["mutate",              'return "MUTATE"'],

            ['\\"(\\\\.|[^"\\\n])*\\"', 'return "STRING"'],
            ["[0-9]+\\.?",          'return "NUMBER"'],
            ["([0-9]+)?\\.[0-9]+",  'return "NUMBER"'],
            ["[a-zA-Z_$][a-zA-Z0-9_$]*", 'return "IDENTIFIER"'],

            ["$",                   'return "EOF"'],
            [".",                   'return "INVALID"'],
        ],
        options: {
            flex: true              // pick longest matching token
        }
    },
    operators: [
        ["right", "|"],
        ["left", "+", "-"],
        ["left", "*", "/"],
        ["left", "UMINUS"],
        ["right", "^"]
    ],
    start: "program",
    bnf: {
        "program": [
            ["statementList EOF", "return $1;"],
            ["endFile", "return new yy.StatementList([]);"]
        ],
        "endFile": [
            ["EOF", "$$ = $1"],
            ["NEWLINE EOF", "$$ = $2"]
        ],
        "statementList": [
            ["statement", "$$ = [$1]"],
            ["statementList statement", "$$ = $1; $1.push($2);"],
        ],
        "statement": [
            ["NEWLINE", ""],  // discard
            ["statementBody NEWLINE", "$$ = $1"]
        ],
        "statementBody": [
            ["IDENTIFIER = expression", "return new yy.Declaration(false, $1, $3);"],
            ["VARKEYWORD IDENTIFIER = expression", "return new yy.Declaration(true, $2, $4);"],
            ["MUTATE lvalue = expression", "return new yy.Mutation($2, $3)"],
        ],
        "expression": [
            ["lvalue", "$$ = $1"],
            ["rvalue", "$$ = $1"]
        ],
        "lvalue": [
            ["IDENTIFIER", "$$ = $1"],
//            ["tableaccess", "$$ = $1"]
        ],
        "rvalue": [
            ["function", "$$ = $1;"],
            ["literal", "$$ = $1;"]
        ],
//        "tableaccess": [
//
//        ],
        "literal": [
            ["NUMBER", "$$ = $1;"],
            ["STRING", "$$ = $1;"]
        ],
//        "table": [
//            ["{ }", "$$ = new yy.Table([]);"],
//            ["{ fieldList }", "$$ = new yy.Table([]);"]
//        ],
//        "fieldList": [
//            ["field", "$$ = [$1];"],
//            ["field NEWLINE field", "$$ = $1; $1.push($3);"]
//        ],
//        "field": [
//            ["expression", "$$ = new yy.Field(null, $1);"],
//            ["IDENTIFIER : expression", "$$ = new yy.Field($1, $3);"]
//        ],
        "function": [
            ["[ statementList endFunction", "$$ = new yy.Function([], $2);"],
            ["[ argList | statementList endFunction", "$$ = new yy.Function($2, $4);"]
        ],
        "endFunction": [
            ["]", "$$ = $1"],
            ["NEWLINE ]", "$$ = $2"]
        ],
        "additive": [
            ["additive + multiplicative", "$$ = yy.Add.createOrAppend($1, $3);"],
            ["additive - multiplicative", "$$ = yy.Add.createOrAppend($1, yy.Mul.handleNegative($3, \"subtract\"));"],
            ["multiplicative", "$$ = $1;", {prec: "+"}]
        ],
        "multiplicative": [
            // the second term in an implicit multiplication cannot be negative
            ["multiplicative triglog", "$$ = yy.Mul.fold(yy.Mul.createOrAppend($1, $2));"],
            ["multiplicative * negative", "$$ = yy.Mul.fold(yy.Mul.createOrAppend($1, $3));"],
            ["multiplicative / negative", "$$ = yy.Mul.fold(yy.Mul.handleDivide($1, $3));"],
            ["negative", "$$ = $1;"]
        ],
        "negative": [
            ["- negative", "$$ = yy.Mul.handleNegative($2);", {prec: "UMINUS"}],
            ["triglog", "$$ = $1;"]
        ],
        "trig": [
            ["TRIG", "$$ = [yytext];"]
        ],
        "trigfunc": [
            ["trig", "$$ = $1;"],
            ["trig ^ negative", "$$ = $1.concat($3);"],
            ["TRIGINV", "$$ = [yytext];"]
        ],
        "logbase": [
            ["ln", "$$ = yy.Log.natural();"],
            ["log", "$$ = yy.Log.common();"],
            ["log _ subscriptable", "$$ = $3;"]
        ],
        "triglog": [
            ["trigfunc negative", "$$ = yy.Trig.create($1, $2);"],
            ["logbase negative", "$$ = yy.Log.create($1, $2);"],
            ["power", "$$ = $1;"]
        ],
        "power": [
            ["primitive ^ negative", "$$ = new yy.Pow($1, $3);"],
            ["primitive", "$$ = $1;"]
        ],
        "variable": [
            ["VAR", "$$ = yytext;"]
        ],
        "subscriptable": [
            ["variable _ subscriptable", "$$ = new yy.Var($1, $3);"],
            ["variable", "$$ = new yy.Var($1);"],
            ["CONST", "$$ = new yy.Const(yytext.toLowerCase());"],
            ["INT", "$$ = yy.Int.create(Number(yytext));"],
            ["FLOAT", "$$ = yy.Float.create(Number(yytext));"],
            ["( additive )", "$$ = $2.completeParse().addHint('parens');"] // this probably shouldn't be a hint...
        ],
        "invocation": [
            ["sqrt ( additive )", "$$ = yy.Pow.sqrt($3);"],
            ["abs ( additive )", "$$ = new yy.Abs($3);"],
            ["| additive |", "$$ = new yy.Abs($2);"],
            ["function ( additive )", "$$ = new yy.Func($1, $3);"]
        ],
        "primitive": [
            ["subscriptable", "$$ = $1;"],
            ["invocation", "$$ = $1;"]
        ]
    }
};

var prelude = "";
var parser = (new jison.Parser(grammar, {debug: true})).generate({moduleType: "js"});
var postlude = "\n\nexports.parser = parser;\n";

fs.writeFileSync(path.resolve(__dirname, "parser.js"), prelude + parser + postlude);
<commit_msg>yay parser compiling<commit_after>#!/usr/bin/env node

// Modified from https://github.com/Khan/KAS,
// which is MIT licensed

var fs = require("fs");
var path = require("path");
var jison = require("jison");

var grammar = {
    lex: {
        rules: [
            ["\\s+",                '/* skip whitespace */'],

            ["==|!=|<|>|<=|>=",     'return "SIGN"'],

            ["\\*",                 'return "*"'],
            ["\\/",                 'return "/"'],
            ["-",                   'return "-"'],
            ["\\+",                 'return "+"'],
            ["\\%",                 'return "%"'],

            ["\\(",                 'return "("'],
            ["\\)",                 'return ")"'],
            ["\\{",                 'return "}"'],
            ["\\{",                 'return "}"'],
            ["\\|",                 'return "|"'],
            ["\\[",                 'return "["'],
            ["\\]",                 'return "]"'],

            ["=",                   'return "="'],
            ["\\n+",                'return "NEWLINE"'],
            ["\\!",                 'return "!"'],
            ["\\:",                 'return ":"'],

            ["var",                 'return "VARKEYWORD"'],
            ["mutate",              'return "MUTATE"'],

            ['\\"(\\\\.|[^"\\\n])*\\"', 'return "STRING"'],
            ["[0-9]+\\.?",          'return "NUMBER"'],
            ["([0-9]+)?\\.[0-9]+",  'return "NUMBER"'],
            ["[a-zA-Z_$][a-zA-Z0-9_$]*", 'return "IDENTIFIER"'],

            ["$",                   'return "EOF"'],
            [".",                   'return "INVALID"'],
        ],
        options: {
            flex: true              // pick longest matching token
        }
    },
    operators: [
        ["right", "|"],
        ["left", "+", "-"],
        ["left", "*", "/"],
        ["left", "UMINUS"],
        ["right", "^"]
    ],
    start: "program",
    bnf: {
        "program": [
            ["statementList EOF", "return $1;"],
            ["EOF", "return new yy.StatementList([]);"]
        ],
        "statementList": [
            ["statement", "$$ = [$1]"],
            ["statementList statement", "$$ = $1; $1.push($2);"],
        ],
        "statement": [
            ["NEWLINE", ""],  // discard
            ["statementBody NEWLINE", "$$ = $1"]
        ],
        "statementBody": [
            ["IDENTIFIER = expression", "return new yy.Declaration(false, $1, $3);"],
            ["VARKEYWORD IDENTIFIER = expression", "return new yy.Declaration(true, $2, $4);"],
            ["MUTATE lvalue = expression", "return new yy.Mutation($2, $3)"],
        ],
        "expression": [
            ["lvalue", "$$ = $1"],
            ["rvalue", "$$ = $1"]
        ],
        "lvalue": [
            ["IDENTIFIER", "$$ = $1"],
//            ["tableaccess", "$$ = $1"]
        ],
        "rvalue": [
            ["function", "$$ = $1;"],
            ["literal", "$$ = $1;"]
        ],
//        "tableaccess": [
//
//        ],
        "literal": [
            ["NUMBER", "$$ = $1;"],
            ["STRING", "$$ = $1;"]
        ],
//        "table": [
//            ["{ }", "$$ = new yy.Table([]);"],
//            ["{ fieldList }", "$$ = new yy.Table([]);"]
//        ],
//        "fieldList": [
//            ["field", "$$ = [$1];"],
//            ["field NEWLINE field", "$$ = $1; $1.push($3);"]
//        ],
//        "field": [
//            ["expression", "$$ = new yy.Field(null, $1);"],
//            ["IDENTIFIER : expression", "$$ = new yy.Field($1, $3);"]
//        ],
        "function": [
            ["[ statementList ]", "$$ = new yy.Function([], $2);"],
            ["[ argList | statementList ]", "$$ = new yy.Function($2, $4);"]
        ],
        "additive": [
            ["additive + multiplicative", "$$ = yy.Add.createOrAppend($1, $3);"],
            ["additive - multiplicative", "$$ = yy.Add.createOrAppend($1, yy.Mul.handleNegative($3, \"subtract\"));"],
            ["multiplicative", "$$ = $1;", {prec: "+"}]
        ],
        "multiplicative": [
            // the second term in an implicit multiplication cannot be negative
            ["multiplicative triglog", "$$ = yy.Mul.fold(yy.Mul.createOrAppend($1, $2));"],
            ["multiplicative * negative", "$$ = yy.Mul.fold(yy.Mul.createOrAppend($1, $3));"],
            ["multiplicative / negative", "$$ = yy.Mul.fold(yy.Mul.handleDivide($1, $3));"],
            ["negative", "$$ = $1;"]
        ],
        "negative": [
            ["- negative", "$$ = yy.Mul.handleNegative($2);", {prec: "UMINUS"}],
            ["triglog", "$$ = $1;"]
        ],
        "trig": [
            ["TRIG", "$$ = [yytext];"]
        ],
        "trigfunc": [
            ["trig", "$$ = $1;"],
            ["trig ^ negative", "$$ = $1.concat($3);"],
            ["TRIGINV", "$$ = [yytext];"]
        ],
        "logbase": [
            ["ln", "$$ = yy.Log.natural();"],
            ["log", "$$ = yy.Log.common();"],
            ["log _ subscriptable", "$$ = $3;"]
        ],
        "triglog": [
            ["trigfunc negative", "$$ = yy.Trig.create($1, $2);"],
            ["logbase negative", "$$ = yy.Log.create($1, $2);"],
            ["power", "$$ = $1;"]
        ],
        "power": [
            ["primitive ^ negative", "$$ = new yy.Pow($1, $3);"],
            ["primitive", "$$ = $1;"]
        ],
        "variable": [
            ["VAR", "$$ = yytext;"]
        ],
        "subscriptable": [
            ["variable _ subscriptable", "$$ = new yy.Var($1, $3);"],
            ["variable", "$$ = new yy.Var($1);"],
            ["CONST", "$$ = new yy.Const(yytext.toLowerCase());"],
            ["INT", "$$ = yy.Int.create(Number(yytext));"],
            ["FLOAT", "$$ = yy.Float.create(Number(yytext));"],
            ["( additive )", "$$ = $2.completeParse().addHint('parens');"] // this probably shouldn't be a hint...
        ],
        "invocation": [
            ["sqrt ( additive )", "$$ = yy.Pow.sqrt($3);"],
            ["abs ( additive )", "$$ = new yy.Abs($3);"],
            ["| additive |", "$$ = new yy.Abs($2);"],
            ["function ( additive )", "$$ = new yy.Func($1, $3);"]
        ],
        "primitive": [
            ["subscriptable", "$$ = $1;"],
            ["invocation", "$$ = $1;"]
        ]
    }
};

var prelude = "";
var parser = (new jison.Parser(grammar, {debug: true})).generate({moduleType: "js"});
var postlude = "\n\nexports.parser = parser;\n";

fs.writeFileSync(path.resolve(__dirname, "parser.js"), prelude + parser + postlude);
<|endoftext|>