<commit_before>// @flow

import * as React from 'react'
import { StyleSheet } from 'react-native'
import SafeArea, { type SafeAreaInsets } from 'react-native-safe-area'

type Direction =
  | 'top'
  | 'bottom'
  | 'left'
  | 'right'
  | 'topLeft'     // DEPRECATED
  | 'topAndLeft'
  | 'topRight'    // DEPRECATED
  | 'topAndRight'
  | 'bottomLeft'  // DEPRECATED
  | 'bottomAndLeft'
  | 'bottomRight' // DEPRECATED
  | 'bottomAndRight'
  | 'vertical'
  | 'horizontal'
  | 'verticalAndLeft'
  | 'verticalAndRight'
  | 'horizontalAndTop'
  | 'horizontalAndBottom'
  | 'all'
;

type Props = any;
type State = {
  safeAreaInsets: SafeAreaInsets,
};

export function withSafeArea(
  WrappedComponent: React.ComponentType<any>,
  applyTo: 'margin' | 'padding' | 'absolutePosition' | 'contentInset' = 'margin',
  direction: Direction = 'all'
): React.ComponentType<any> {
  let _direction = direction

  const match = _direction.match(/^(top|bottom)(Left|Right)$/)
  if (match) {
    _direction = `${match[1]}And${match[2]}`

    // eslint-disable-next-line
    console.warn(`'${direction}' is deprecated. Use '${_direction}' instead.`)
  }

  const applysToTop = (
    _direction === 'top' ||
    _direction === 'topAndLeft' ||
    _direction === 'topAndRight' ||
    _direction === 'vertical' ||
    _direction === 'verticalAndLeft' ||
    _direction === 'verticalAndRight' ||
    _direction === 'horizontalAndTop' ||
    _direction === 'all'
  )
  const applysToBottom = (
    _direction === 'bottom' ||
    _direction === 'bottomAndLeft' ||
    _direction === 'bottomAndRight' ||
    _direction === 'vertical' ||
    _direction === 'verticalAndLeft' ||
    _direction === 'verticalAndRight' ||
    _direction === 'horizontalAndBottom' ||
    _direction === 'all'
  )
  const applysToLeft = (
    _direction === 'left' ||
    _direction === 'topAndLeft' ||
    _direction === 'bottomAndLeft' ||
    _direction === 'horizontal' ||
    _direction === 'horizontalAndTop' ||
    _direction === 'horizontalAndBottom' ||
    _direction === 'verticalAndLeft' ||
    _direction === 'all'
  )
  const applysToRight = (
    _direction === 'right' ||
    _direction === 'topAndRight' ||
    _direction === 'bottomAndRight' ||
    _direction === 'horizontal' ||
    _direction === 'horizontalAndTop' ||
    _direction === 'horizontalAndBottom' ||
    _direction === 'verticalAndRight' ||
    _direction === 'all'
  )

  return class extends React.Component<Props, State> {
    state = { safeAreaInsets: { top: 0, bottom: 0, left: 0, right: 0 } }
    wrappedRef: any = null
    onSafeAreaInsetsDidChange = this.onSafeAreaInsetsDidChange.bind(this)

    componentWillMount(): void {
      SafeArea.getSafeAreaInsetsForRootView()
        .then(result => this.onSafeAreaInsetsDidChange(result))
    }

    componentDidMount(): void {
      SafeArea.addEventListener('safeAreaInsetsForRootViewDidChange', this.onSafeAreaInsetsDidChange)
    }

    componentWillUnmount(): void {
      SafeArea.removeEventListener(
        'safeAreaInsetsForRootViewDidChange',
        this.onSafeAreaInsetsDidChange
      )
    }

    get currentSafeAreaInsets(): SafeAreaInsets {
      return this.state.safeAreaInsets
    }

    get _injectedProps(): Props {
      const isVerticalInverted = this.props.inverted && !this.props.horizontal
      const isHorizontalInverted = this.props.inverted && this.props.horizontal

      const { safeAreaInsets } = this.state
      const top = !isVerticalInverted ? safeAreaInsets.top : safeAreaInsets.bottom
      const bottom = !isVerticalInverted ? safeAreaInsets.bottom : safeAreaInsets.top
      const left = !isHorizontalInverted ? safeAreaInsets.left : safeAreaInsets.right
      const right = !isHorizontalInverted ? safeAreaInsets.right : safeAreaInsets.left

      if (applyTo === 'contentInset') {
        const contentInset = this.props.contentInset || {}
        const contentOffset = this.props.contentOffset || {}
        const injected = {
          automaticallyAdjustContentInsets: false,
          contentInset: { ...contentInset },
          contentOffset: { ...contentOffset },
        }

        if (applysToTop || applysToBottom) {
          if (applysToTop) {
            injected.contentInset.top = (contentInset.top || 0) + top
            if (this.wrappedRef && this.wrappedRef.getScrollResponder) {
              const scrollView = this.wrappedRef.getScrollResponder()
              if (scrollView && scrollView._scrollAnimatedValue) {
                scrollView._scrollAnimatedValue.setOffset(injected.contentInset.top)
              }
            }
            injected.contentOffset.y = (contentOffset.y || 0) - top
          }
          if (applysToBottom) {
            injected.contentInset.bottom = (contentInset.bottom || 0) + bottom
          }
        }
        if (applysToLeft || applysToRight) {
          if (applysToLeft) {
            injected.contentInset.left = (contentInset.left || 0) + left
          }
          if (applysToRight) {
            injected.contentInset.right = (contentInset.right || 0) + right
          }
          injected.contentOffset.x = (contentOffset.x || 0) - left
        }

        return injected
      }

      const style = StyleSheet.flatten([this.props.style]) || {}
      const injected = { style: { ...style } }

      if (applyTo === 'margin') {
        if (applysToTop) {
          const marginTop = style.marginTop || style.marginVertical || style.margin || 0
          injected.style.marginTop = marginTop + top
        }
        if (applysToBottom) {
          const marginBottom = style.marginBottom || style.marginVertical || style.margin || 0
          injected.style.marginBottom = marginBottom + bottom
        }
        if (applysToLeft) {
          const marginLeft = style.marginLeft || style.marginHorizontal || style.margin || 0
          injected.style.marginLeft = marginLeft + left
        }
        if (applysToRight) {
          const marginRight = style.marginRight || style.marginHorizontal || style.margin || 0
          injected.style.marginRight = marginRight + right
        }
      } else if (applyTo === 'padding') {
        if (applysToTop) {
          const paddingTop = style.paddingTop || style.paddingVertical || style.padding || 0
          injected.style.paddingTop = paddingTop + top
        }
        if (applysToBottom) {
          const paddingBottom = style.paddingBottom || style.paddingVertical || style.padding || 0
          injected.style.paddingBottom = paddingBottom + bottom
        }
        if (applysToLeft) {
          const paddingLeft = style.paddingLeft || style.paddingHorizontal || style.padding || 0
          injected.style.paddingLeft = paddingLeft + left
        }
        if (applysToRight) {
          const paddingRight = style.paddingRight || style.paddingHorizontal || style.padding || 0
          injected.style.paddingRight = paddingRight + right
        }
      } else if (applyTo === 'absolutePosition') {
        if (applysToTop) {
          injected.style.top = style.top + top
        }
        if (applysToBottom) {
          injected.style.bottom = style.bottom + bottom
        }
        if (applysToLeft) {
          injected.style.left = style.left + left
        }
        if (applysToRight) {
          injected.style.right = style.right + right
        }
      }

      return injected
    }

    onSafeAreaInsetsDidChange(result: { safeAreaInsets: SafeAreaInsets }): void {
      const { safeAreaInsets } = result
      this.setState({ safeAreaInsets })
    }

    render(): React.Node {
      return (
        <WrappedComponent
          ref={(ref) => { this.wrappedRef = ref }}
          {...this.props}
          {...this._injectedProps}
        />
      )
    }
  }
}
<commit_msg>Fix cycle requirements warning<commit_after>// @flow

import * as React from 'react'
import { StyleSheet } from 'react-native'
import SafeArea from './SafeArea'
import { type SafeAreaInsets } from './TypeDefinition'

type Direction =
  | 'top'
  | 'bottom'
  | 'left'
  | 'right'
  | 'topLeft'     // DEPRECATED
  | 'topAndLeft'
  | 'topRight'    // DEPRECATED
  | 'topAndRight'
  | 'bottomLeft'  // DEPRECATED
  | 'bottomAndLeft'
  | 'bottomRight' // DEPRECATED
  | 'bottomAndRight'
  | 'vertical'
  | 'horizontal'
  | 'verticalAndLeft'
  | 'verticalAndRight'
  | 'horizontalAndTop'
  | 'horizontalAndBottom'
  | 'all'
;

type Props = any;
type State = {
  safeAreaInsets: SafeAreaInsets,
};

export function withSafeArea(
  WrappedComponent: React.ComponentType<any>,
  applyTo: 'margin' | 'padding' | 'absolutePosition' | 'contentInset' = 'margin',
  direction: Direction = 'all'
): React.ComponentType<any> {
  let _direction = direction

  const match = _direction.match(/^(top|bottom)(Left|Right)$/)
  if (match) {
    _direction = `${match[1]}And${match[2]}`

    // eslint-disable-next-line
    console.warn(`'${direction}' is deprecated. Use '${_direction}' instead.`)
  }

  const applysToTop = (
    _direction === 'top' ||
    _direction === 'topAndLeft' ||
    _direction === 'topAndRight' ||
    _direction === 'vertical' ||
    _direction === 'verticalAndLeft' ||
    _direction === 'verticalAndRight' ||
    _direction === 'horizontalAndTop' ||
    _direction === 'all'
  )
  const applysToBottom = (
    _direction === 'bottom' ||
    _direction === 'bottomAndLeft' ||
    _direction === 'bottomAndRight' ||
    _direction === 'vertical' ||
    _direction === 'verticalAndLeft' ||
    _direction === 'verticalAndRight' ||
    _direction === 'horizontalAndBottom' ||
    _direction === 'all'
  )
  const applysToLeft = (
    _direction === 'left' ||
    _direction === 'topAndLeft' ||
    _direction === 'bottomAndLeft' ||
    _direction === 'horizontal' ||
    _direction === 'horizontalAndTop' ||
    _direction === 'horizontalAndBottom' ||
    _direction === 'verticalAndLeft' ||
    _direction === 'all'
  )
  const applysToRight = (
    _direction === 'right' ||
    _direction === 'topAndRight' ||
    _direction === 'bottomAndRight' ||
    _direction === 'horizontal' ||
    _direction === 'horizontalAndTop' ||
    _direction === 'horizontalAndBottom' ||
    _direction === 'verticalAndRight' ||
    _direction === 'all'
  )

  return class extends React.Component<Props, State> {
    state = { safeAreaInsets: { top: 0, bottom: 0, left: 0, right: 0 } }
    wrappedRef: any = null
    onSafeAreaInsetsDidChange = this.onSafeAreaInsetsDidChange.bind(this)

    componentWillMount(): void {
      SafeArea.getSafeAreaInsetsForRootView()
        .then(result => this.onSafeAreaInsetsDidChange(result))
    }

    componentDidMount(): void {
      SafeArea.addEventListener('safeAreaInsetsForRootViewDidChange', this.onSafeAreaInsetsDidChange)
    }

    componentWillUnmount(): void {
      SafeArea.removeEventListener(
        'safeAreaInsetsForRootViewDidChange',
        this.onSafeAreaInsetsDidChange
      )
    }

    get currentSafeAreaInsets(): SafeAreaInsets {
      return this.state.safeAreaInsets
    }

    get _injectedProps(): Props {
      const isVerticalInverted = this.props.inverted && !this.props.horizontal
      const isHorizontalInverted = this.props.inverted && this.props.horizontal

      const { safeAreaInsets } = this.state
      const top = !isVerticalInverted ? safeAreaInsets.top : safeAreaInsets.bottom
      const bottom = !isVerticalInverted ? safeAreaInsets.bottom : safeAreaInsets.top
      const left = !isHorizontalInverted ? safeAreaInsets.left : safeAreaInsets.right
      const right = !isHorizontalInverted ? safeAreaInsets.right : safeAreaInsets.left

      if (applyTo === 'contentInset') {
        const contentInset = this.props.contentInset || {}
        const contentOffset = this.props.contentOffset || {}
        const injected = {
          automaticallyAdjustContentInsets: false,
          contentInset: { ...contentInset },
          contentOffset: { ...contentOffset },
        }

        if (applysToTop || applysToBottom) {
          if (applysToTop) {
            injected.contentInset.top = (contentInset.top || 0) + top
            if (this.wrappedRef && this.wrappedRef.getScrollResponder) {
              const scrollView = this.wrappedRef.getScrollResponder()
              if (scrollView && scrollView._scrollAnimatedValue) {
                scrollView._scrollAnimatedValue.setOffset(injected.contentInset.top)
              }
            }
            injected.contentOffset.y = (contentOffset.y || 0) - top
          }
          if (applysToBottom) {
            injected.contentInset.bottom = (contentInset.bottom || 0) + bottom
          }
        }
        if (applysToLeft || applysToRight) {
          if (applysToLeft) {
            injected.contentInset.left = (contentInset.left || 0) + left
          }
          if (applysToRight) {
            injected.contentInset.right = (contentInset.right || 0) + right
          }
          injected.contentOffset.x = (contentOffset.x || 0) - left
        }

        return injected
      }

      const style = StyleSheet.flatten([this.props.style]) || {}
      const injected = { style: { ...style } }

      if (applyTo === 'margin') {
        if (applysToTop) {
          const marginTop = style.marginTop || style.marginVertical || style.margin || 0
          injected.style.marginTop = marginTop + top
        }
        if (applysToBottom) {
          const marginBottom = style.marginBottom || style.marginVertical || style.margin || 0
          injected.style.marginBottom = marginBottom + bottom
        }
        if (applysToLeft) {
          const marginLeft = style.marginLeft || style.marginHorizontal || style.margin || 0
          injected.style.marginLeft = marginLeft + left
        }
        if (applysToRight) {
          const marginRight = style.marginRight || style.marginHorizontal || style.margin || 0
          injected.style.marginRight = marginRight + right
        }
      } else if (applyTo === 'padding') {
        if (applysToTop) {
          const paddingTop = style.paddingTop || style.paddingVertical || style.padding || 0
          injected.style.paddingTop = paddingTop + top
        }
        if (applysToBottom) {
          const paddingBottom = style.paddingBottom || style.paddingVertical || style.padding || 0
          injected.style.paddingBottom = paddingBottom + bottom
        }
        if (applysToLeft) {
          const paddingLeft = style.paddingLeft || style.paddingHorizontal || style.padding || 0
          injected.style.paddingLeft = paddingLeft + left
        }
        if (applysToRight) {
          const paddingRight = style.paddingRight || style.paddingHorizontal || style.padding || 0
          injected.style.paddingRight = paddingRight + right
        }
      } else if (applyTo === 'absolutePosition') {
        if (applysToTop) {
          injected.style.top = style.top + top
        }
        if (applysToBottom) {
          injected.style.bottom = style.bottom + bottom
        }
        if (applysToLeft) {
          injected.style.left = style.left + left
        }
        if (applysToRight) {
          injected.style.right = style.right + right
        }
      }

      return injected
    }

    onSafeAreaInsetsDidChange(result: { safeAreaInsets: SafeAreaInsets }): void {
      const { safeAreaInsets } = result
      this.setState({ safeAreaInsets })
    }

    render(): React.Node {
      return (
        <WrappedComponent
          ref={(ref) => { this.wrappedRef = ref }}
          {...this.props}
          {...this._injectedProps}
        />
      )
    }
  }
}
<|endoftext|>


<commit_before>// xssblacklist.js
//
// Middleware to serve an error page to browsers with XSS problems
//
// Copyright 2011-2012, E14N https://e14n.com/
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

var uaParser = require("ua-parser-js");

var xssCheck = function(req, res, next) {
    var ua = uaParser(req.headers["user-agent"]);

    if (ua.browser.name === "IE" && Number(ua.browser.major) < 11) {
        res.render("xss-error");
        return;
    }

    next();
};

exports.xssCheck = xssCheck;
<commit_msg>Polish up the XSS blacklist code<commit_after>// xssblacklist.js
//
// Middleware to serve an error page to browsers with XSS problems
//
// Copyright 2011-2012, E14N https://e14n.com/
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

var uaParser = require("ua-parser-js");

var xssCheck = function(req, res, next) {
    var ua = uaParser(req.headers["user-agent"]);

    if (ua.browser.name === "IE" && Number(ua.browser.major) < 11) {
        res.status(400);
        res.render("xss-error", {page: {title: "Security error"}});
        return;
    }

    next();
};

exports.xssCheck = xssCheck;
<|endoftext|>


<commit_before>'use strict';

//const recast = require('./botlogic/recast.js');
const apiai = require('./../botlogic/apiai.js');
const facebook = require('./../channels/facebook.js');
const telegram = require('./../channels/telegram.js');
const aslan = require('./../channels/aslan-messenger.js');
const pr = require('./processing.js');
const fd = require('./field.js');

var messageReceived;

/*
*   Fonction appelée par les channels lorsque l'on reçoit un message
*/
function receivedMessage(message) {
    messageReceived = message;
    if(message.location != undefined) {
        getLastIntent(message);
    } else {
        runLogicLayer(message);
    }
}

/*
*   Fonction qu lance la couche logique avec NLP
*/
function runLogicLayer(message) {
    /*botlogic.defineCallback(callbackLogicLayer);
    if(message.senderID != undefined && message.text != undefined) {
        botlogic.sendMessage(message.text, `session-${message.senderID}`, {});
    }*/
    /*recast.sendMessage(message.text, callbackLogicLayer);*/
    apiai.sendMessage(message.senderID, message.text, callbackLogicLayer)
}

/*
*   Fonction de callback appelée par la couche logique
*/
function callbackLogicLayer(response) {
    console.log("APIAI sended : ", JSON.stringify(response));
    var intent = response.result.metadata.intentName;
    processing(intent, response);
}

/*
*   Fonction qui traite le message en fonction du contexte du message
*   La fonction renvoie la réponse à la channel
*/
function processing(intent, response) {
    switch(intent) {
        case "bonjour" :
            pr.processingGrettings(messageReceived, response);
            break;
        case "heure" :
            pr.processingHour(response);
            break;
        case "fontaine" :
            pr.processingFountain(response);
            break;
        case "habitant":
            pr.processingCitizen(response);
            break;
        case "jour":
            pr.processingDate(response);
            break;
        case "meteo":
            pr.processingWeather(response);
            break;
        case "restaurant":
            pr.processingRestaurant(response, null);
            break;
        default :
            prepareMessage(response.result.fulfillment.speech);
    }
}

/*
*   Fonction qui prépare le message
*   Recherche de champs à completer
*   Voir la documentation pour le formalisme
*    {{qr:Oui}} {{qr:Non}}
*/
function prepareMessage(response) {
    var messages = [];
    var replie = response;
    var fields = fd.extractFields(replie);
    var quickreplies = extractQuickReplies(fields);
    replie = fd.removeFields(replie);
    if(quickreplies.length > 0) {
        prepareMessageWithQuickReply(replie, quickreplies, messages);
    } else if(replie != undefined ) {
        prepareMessageWithText(replie, messages);
    }
    sendMessages(messages);
}

/*
*   Fonction qui extrait les quick replies
*/
function extractQuickReplies(fields) {
    var quickreplies = [];
    for(var i=0;i<fields.length;i++)
    {
        var json = undefined;
        try {
            json = JSON.parse(fields[i]);
        } catch (err){
        }
        if(json != undefined && json.qr != undefined && json.qr.length > 0) {
            for(var j=0;j<json.qr.length;j++) {
                quickreplies.push(json.qr[j]);
            }
        }
    }
    return quickreplies;
}

/*
*   Fonction qui prépare un message de type text
*/
function prepareMessageWithText(text, messages) {
    var message = {
        type: "text",
        senderID: messageReceived.senderID,
        channel: messageReceived.channel,
        text: text
    };
    messages.push(message);
}

/*
*   Fonction qui prépare un message de type quickreply
*/
function prepareMessageWithQuickReply(text, quickreply, messages) {
    var message = {
        type: "quickreply",
        senderID: messageReceived.senderID,
        channel: messageReceived.channel,
        text: text,
        choices:[]
    }
    if(Array.isArray(quickreply)) {
        for(var i=0;i<quickreply.length;i++) {
            message.choices.push(quickreply[i]);
        }
    } else {
        message.choices.push(quickreply);
    }
    messages.push(message);
}

function askLocation() {
    var message = {
        type: "location",
        senderID: messageReceived.senderID,
        channel: messageReceived.channel,
        text: "J'ai besoin de votre localisation"
    }
    sendMessage([message]);
}

/*
*   Fonction qui appelle la fonction d'envoie de message
*/
function sendMessages(messages) {
    if(messages.length > 0) {
        switch(messages[0].channel) {
        case "Facebook":
            facebook.sendMessages(messages);
            break;
        case "Telegram":
            telegram.sendMessages(messages);
            break;
        case "Aslan":
            aslan.sendMessages(messages);
            break;
        default:
            return;
        }
    }
}

function getLastIntent(message) {
    db.getData("conversation", {sessionId: message.senderId}, function(data) {
        if(data.length == 0) {
            console.log("Aucun intent trouvé");
        } else {
            switch(data[0].result.metadata.intentName) {
            case "restaurant":
                apiai.sendMessage(message.senderID, "[localisation:success]", callbackLogicLayer)
                pr.processingRestaurant(message.location);
                break;
            default:
               break;
            }
        }
    });
}

exports.askLocation = askLocation;
exports.receivedMessage = receivedMessage;
exports.prepareMessage = prepareMessage;<commit_msg>fix bug<commit_after>'use strict';

//const recast = require('./botlogic/recast.js');
const apiai = require('./../botlogic/apiai.js');
const facebook = require('./../channels/facebook.js');
const telegram = require('./../channels/telegram.js');
const aslan = require('./../channels/aslan-messenger.js');
const pr = require('./processing.js');
const fd = require('./field.js');

var messageReceived;

/*
*   Fonction appelée par les channels lorsque l'on reçoit un message
*/
function receivedMessage(message) {
    messageReceived = message;
    if(message.location != undefined) {
        getLastIntent(message);
    } else {
        runLogicLayer(message);
    }
}

/*
*   Fonction qu lance la couche logique avec NLP
*/
function runLogicLayer(message) {
    /*botlogic.defineCallback(callbackLogicLayer);
    if(message.senderID != undefined && message.text != undefined) {
        botlogic.sendMessage(message.text, `session-${message.senderID}`, {});
    }*/
    /*recast.sendMessage(message.text, callbackLogicLayer);*/
    apiai.sendMessage(message.senderID, message.text, callbackLogicLayer)
}

/*
*   Fonction de callback appelée par la couche logique
*/
function callbackLogicLayer(response) {
    console.log("APIAI sended : ", JSON.stringify(response));
    var intent = response.result.metadata.intentName;
    processing(intent, response);
}

/*
*   Fonction qui traite le message en fonction du contexte du message
*   La fonction renvoie la réponse à la channel
*/
function processing(intent, response) {
    switch(intent) {
        case "bonjour" :
            pr.processingGrettings(messageReceived, response);
            break;
        case "heure" :
            pr.processingHour(response);
            break;
        case "fontaine" :
            pr.processingFountain(response);
            break;
        case "habitant":
            pr.processingCitizen(response);
            break;
        case "jour":
            pr.processingDate(response);
            break;
        case "meteo":
            pr.processingWeather(response);
            break;
        case "restaurant":
            pr.processingRestaurant(response, null);
            break;
        default :
            prepareMessage(response.result.fulfillment.speech);
    }
}

/*
*   Fonction qui prépare le message
*   Recherche de champs à completer
*   Voir la documentation pour le formalisme
*    {{qr:Oui}} {{qr:Non}}
*/
function prepareMessage(response) {
    var messages = [];
    var replie = response;
    var fields = fd.extractFields(replie);
    var quickreplies = extractQuickReplies(fields);
    replie = fd.removeFields(replie);
    if(quickreplies.length > 0) {
        prepareMessageWithQuickReply(replie, quickreplies, messages);
    } else if(replie != undefined ) {
        prepareMessageWithText(replie, messages);
    }
    sendMessages(messages);
}

/*
*   Fonction qui extrait les quick replies
*/
function extractQuickReplies(fields) {
    var quickreplies = [];
    for(var i=0;i<fields.length;i++)
    {
        var json = undefined;
        try {
            json = JSON.parse(fields[i]);
        } catch (err){
        }
        if(json != undefined && json.qr != undefined && json.qr.length > 0) {
            for(var j=0;j<json.qr.length;j++) {
                quickreplies.push(json.qr[j]);
            }
        }
    }
    return quickreplies;
}

/*
*   Fonction qui prépare un message de type text
*/
function prepareMessageWithText(text, messages) {
    var message = {
        type: "text",
        senderID: messageReceived.senderID,
        channel: messageReceived.channel,
        text: text
    };
    messages.push(message);
}

/*
*   Fonction qui prépare un message de type quickreply
*/
function prepareMessageWithQuickReply(text, quickreply, messages) {
    var message = {
        type: "quickreply",
        senderID: messageReceived.senderID,
        channel: messageReceived.channel,
        text: text,
        choices:[]
    }
    if(Array.isArray(quickreply)) {
        for(var i=0;i<quickreply.length;i++) {
            message.choices.push(quickreply[i]);
        }
    } else {
        message.choices.push(quickreply);
    }
    messages.push(message);
}

function askLocation() {
    var message = {
        type: "location",
        senderID: messageReceived.senderID,
        channel: messageReceived.channel,
        text: "J'ai besoin de votre localisation"
    }
    sendMessages([message]);
}

/*
*   Fonction qui appelle la fonction d'envoie de message
*/
function sendMessages(messages) {
    if(messages.length > 0) {
        switch(messages[0].channel) {
        case "Facebook":
            facebook.sendMessages(messages);
            break;
        case "Telegram":
            telegram.sendMessages(messages);
            break;
        case "Aslan":
            aslan.sendMessages(messages);
            break;
        default:
            return;
        }
    }
}

function getLastIntent(message) {
    db.getData("conversation", {sessionId: message.senderId}, function(data) {
        if(data.length == 0) {
            console.log("Aucun intent trouvé");
        } else {
            switch(data[0].result.metadata.intentName) {
            case "restaurant":
                apiai.sendMessage(message.senderID, "[localisation:success]", callbackLogicLayer)
                pr.processingRestaurant(message.location);
                break;
            default:
               break;
            }
        }
    });
}

exports.askLocation = askLocation;
exports.receivedMessage = receivedMessage;
exports.prepareMessage = prepareMessage;<|endoftext|>


<commit_before>/* qml.core javascript code */

if (!_globals.core)
	_globals.core = {}

_globals.core.Object = function(parent) {
	this.parent = parent;
	this._local = {}
	this._changedHandlers = {}
}

_globals.core.Object.prototype._update = function(name, value) {}

_globals.core.Object.prototype._setId = function (name) {
	var p = this;
	while(p) {
		p._local[name] = this;
		p = p.parent;
	}
}

_globals.core.Object.prototype.onChanged = function (name, callback) {
	if (name in this._changedHandlers)
		this._changedHandlers[name].push(callback);
	else
		this._changedHandlers[name] = [callback];
}

_globals.core.Object.prototype._emitChanged = function (name, value) {
	if (name in this._changedHandlers) {
		var handlers = this._changedHandlers[name];
		handlers.forEach(function(callback) { callback(value); });
	}
}

_globals.core.Object.prototype.get = function (name) {
	if (name in this._local)
		return this._local[name];
	if (this.hasOwnProperty(name))
		return this[name];
	console.log(name, this);
	throw ("invalid property requested: '" + name + "' in context of " + this);
}

function setup(context) {
	_globals.core.Item.prototype.children = []

	_globals.core.Border.prototype._update = function(name, value) {
		switch(name) {
			case 'width': this.parent.element.css('border-width', value); return;
			case 'color': this.parent.element.css('border-color', value); return;
		}
	}

	_globals.core.Item.prototype._update = function(name, value) {
		switch(name) {
			case 'width': 	this.element.css('width', value); this.right.value = this.x + value; return;
			case 'height':	this.element.css('height', value); this.bottom.value = this.y + value; return;
			case 'x':		this.element.css('left', value); this.left.value = value; this.right.value = value + this.width; return;
			case 'y':		this.element.css('top', value); this.top.value = value; this.bottom.value = value + this.height; return;
			case 'radius':	this.element.css('border-radius', value); return;
		}
		_globals.core.Object.prototype._update.apply(this, arguments);
	}

	_globals.core.Font.prototype._update = function(name, value) {
		switch(name) {
			case 'pointSize': this.parent.element.css('font-size', value + "pt"); return;
			case 'pixelSize': this.parent.element.css('font-size', value + "px"); return;
			case 'italic': this.parent.element.css('font-style', value? 'italic': 'normal'); return;
		}
		_globals.core.Object.prototype._update.apply(this, arguments);
	}

	_globals.core.Text.prototype._update = function(name, value) {
		switch(name) {
			case 'text': this.element.text(value); return;
		}
		_globals.core.Item.prototype._update.apply(this, arguments);
	}

	_globals.core.Rectangle.prototype._update = function(name, value) {
		switch(name) {
			case 'color': this.element.css('background-color', value); return;
		}
		_globals.core.Item.prototype._update.apply(this, arguments);
	}
}

exports.Context = function() {
	var windowW = $(window).width();
	var windowH = $(window).height();
	console.log("window size: " + windowW + "x" + windowH);
	var body = $('body');
	var div = $("

");
	body.append(div)
	//fixme: derive context from Object
	this._local = {}
	this.element = div
	this.element.css({width: windowW, height: windowH});
	console.log("context created");

	setup(this);
}

exports.Context.prototype.start = function(name) {
	var proto;
	if (typeof name == 'string') {
		console.log('creating component...', name);
		var path = name.split('.');
		proto = _globals;
		for (var i = 0; i < path.length; ++i)
			proto = proto[path[i]]
	}
	else
		proto = name;
	var instance = Object.create(proto.prototype);
	proto.apply(instance, [this]);
	return instance;
}

exports.addProperty = function(self, type, name) {
	var value;
	switch(type) {
		case 'int':			value = 0;
		case 'bool':		value = false;
		case 'real':		value = 0.0;
		default: if (type[0].toUpperCase() == type[0]) value = null;
	}
	Object.defineProperty(self, name, {
		get: function() {
			return value;
		},
		set: function(newValue) {
			oldValue = value;
			if (oldValue != newValue) {
				value = newValue;
				self._update(name, newValue, oldValue);
				self._emitChanged(name, newValue);
			}
		}
	});
}

exports._bootstrap = function(self, name) {
	switch(name) {
		case 'core.Item':
			if (self.element)
				throw "double ctor call";
			self.element = $('
');
			self.parent.element.append(self.element);
			break;
	}
}
<commit_msg>moved _emitChanged into base _update()<commit_after>/* qml.core javascript code */

if (!_globals.core)
	_globals.core = {}

_globals.core.Object = function(parent) {
	this.parent = parent;
	this._local = {}
	this._changedHandlers = {}
}

_globals.core.Object.prototype._update = function(name, value) {
	if (name in this._changedHandlers) {
		var handlers = this._changedHandlers[name];
		handlers.forEach(function(callback) { callback(value); });
	}
}

_globals.core.Object.prototype._setId = function (name) {
	var p = this;
	while(p) {
		p._local[name] = this;
		p = p.parent;
	}
}

_globals.core.Object.prototype.onChanged = function (name, callback) {
	if (name in this._changedHandlers)
		this._changedHandlers[name].push(callback);
	else
		this._changedHandlers[name] = [callback];
}

_globals.core.Object.prototype.get = function (name) {
	if (name in this._local)
		return this._local[name];
	if (this.hasOwnProperty(name))
		return this[name];
	console.log(name, this);
	throw ("invalid property requested: '" + name + "' in context of " + this);
}

function setup(context) {
	_globals.core.Item.prototype.children = []

	_globals.core.Border.prototype._update = function(name, value) {
		switch(name) {
			case 'width': this.parent.element.css('border-width', value); return;
			case 'color': this.parent.element.css('border-color', value); return;
		}
		_globals.core.Object.prototype._update.apply(this, arguments);
	}

	_globals.core.Item.prototype._update = function(name, value) {
		switch(name) {
			case 'width': 	this.element.css('width', value); this.right.value = this.x + value; return;
			case 'height':	this.element.css('height', value); this.bottom.value = this.y + value; return;
			case 'x':		this.element.css('left', value); this.left.value = value; this.right.value = value + this.width; return;
			case 'y':		this.element.css('top', value); this.top.value = value; this.bottom.value = value + this.height; return;
			case 'radius':	this.element.css('border-radius', value); return;
		}
		_globals.core.Object.prototype._update.apply(this, arguments);
	}

	_globals.core.Font.prototype._update = function(name, value) {
		switch(name) {
			case 'pointSize': this.parent.element.css('font-size', value + "pt"); return;
			case 'pixelSize': this.parent.element.css('font-size', value + "px"); return;
			case 'italic': this.parent.element.css('font-style', value? 'italic': 'normal'); return;
		}
		_globals.core.Object.prototype._update.apply(this, arguments);
	}

	_globals.core.Text.prototype._update = function(name, value) {
		switch(name) {
			case 'text': this.element.text(value); return;
		}
		_globals.core.Item.prototype._update.apply(this, arguments);
	}

	_globals.core.Rectangle.prototype._update = function(name, value) {
		switch(name) {
			case 'color': this.element.css('background-color', value); return;
		}
		_globals.core.Item.prototype._update.apply(this, arguments);
	}
}

exports.Context = function() {
	var windowW = $(window).width();
	var windowH = $(window).height();
	console.log("window size: " + windowW + "x" + windowH);
	var body = $('body');
	var div = $("

");
	body.append(div)
	//fixme: derive context from Object
	this._local = {}
	this.element = div
	this.element.css({width: windowW, height: windowH});
	console.log("context created");

	setup(this);
}

exports.Context.prototype.start = function(name) {
	var proto;
	if (typeof name == 'string') {
		console.log('creating component...', name);
		var path = name.split('.');
		proto = _globals;
		for (var i = 0; i < path.length; ++i)
			proto = proto[path[i]]
	}
	else
		proto = name;
	var instance = Object.create(proto.prototype);
	proto.apply(instance, [this]);
	return instance;
}

exports.addProperty = function(self, type, name) {
	var value;
	switch(type) {
		case 'int':			value = 0;
		case 'bool':		value = false;
		case 'real':		value = 0.0;
		default: if (type[0].toUpperCase() == type[0]) value = null;
	}
	Object.defineProperty(self, name, {
		get: function() {
			return value;
		},
		set: function(newValue) {
			oldValue = value;
			if (oldValue != newValue) {
				value = newValue;
				self._update(name, newValue, oldValue);
			}
		}
	});
}

exports._bootstrap = function(self, name) {
	switch(name) {
		case 'core.Item':
			if (self.element)
				throw "double ctor call";
			self.element = $('
');
			self.parent.element.append(self.element);
			break;
	}
}
<|endoftext|>


<commit_before>var ledpi = {
    _channels: 24,
    _bits:     12,

    _chromath: require('chromath'),
    _driver: new require('leddriver')(this._channels, this._bits),

    _current: {
        preset: 'off',
        timer: null,
        state: {
            h: 0,
            s: 0,
            l: 0,
            rgb: ''
        }
    },

    getStatus: function() {
        console.log('[ledpi] sending status');

        return this._current.preset === 'off' ? 'off' : this._current.preset.getName();
    },

    run: function(preset) {
        this.reset();

        if (preset === 'off') {
            return;
        }

        try {
            this._current.preset = require('./programs/'+preset+'.js');
        } catch(err) {
            if (err.code == 'MODULE_NOT_FOUND') {
                console.log('[ledpi] unknown preset "%s"', preset);
                this.reset();
                return;
            }
        }

        // run preset
        this._current.preset.run(this._current, this._driver);
    },

    /**
     * Special program to turn all LEDs off.
     * @return void
     */
    reset: function() {
        console.log('[ledpi] resetting LED');

        this._current.state = {
            h: 0,
            s: 0,
            l: 0,
            rgb: ''
        };

        if (this._current.timer) {
            clearInterval(this._current.timer);
        }

        this.current.timer = null;
        this.current.preset = 'off';

        this._driver.setRGB("#000000", 0, 1, 2);
        this._driver.send();
    }
};

exports.getStatus = ledpi.getStatus;
exports.run       = ledpi.run;
<commit_msg>fixed wrong use of "this" (we're not in an instance)<commit_after>var ledpi = {
    _channels: 24,
    _bits:     12,

    _chromath: require('chromath'),
    _driver: new require('leddriver')(ledpi._channels, ledpi._bits),

    _current: {
        preset: 'off',
        timer: null,
        state: {
            h: 0,
            s: 0,
            l: 0,
            rgb: ''
        }
    },

    getStatus: function() {
        console.log('[ledpi] sending status');

        return ledpi._current.preset === 'off' ? 'off' : ledpi._current.preset.getName();
    },

    run: function(preset) {
        ledpi.reset();

        if (preset === 'off') {
            return;
        }

        try {
            ledpi._current.preset = require('./programs/'+preset+'.js');
        } catch(err) {
            if (err.code == 'MODULE_NOT_FOUND') {
                console.log('[ledpi] unknown preset "%s"', preset);
                ledpi.reset();
                return;
            }
        }

        // run preset
        ledpi._current.preset.run(ledpi._current, ledpi._driver);
    },

    /**
     * Special program to turn all LEDs off.
     * @return void
     */
    reset: function() {
        console.log('[ledpi] resetting LED');

        ledpi._current.state = {
            h: 0,
            s: 0,
            l: 0,
            rgb: ''
        };

        if (ledpi._current.timer) {
            clearInterval(ledpi._current.timer);
        }

        ledpi.current.timer = null;
        ledpi.current.preset = 'off';

        ledpi._driver.setRGB("#000000", 0, 1, 2);
        ledpi._driver.send();
    }
};

exports.getStatus = ledpi.getStatus;
exports.run       = ledpi.run;
<|endoftext|>


<commit_before>'use strict';

var indent = [0];
var pos = {
	col: 0,
	row: 0
}

var rules = {
	space: [
		/^ +/,
		function (raw) {
			pos.col += raw.length;
			return false;
		}
	],
	terminator: [
		/^\n+/,
		function (raw, lex, modify, increment) {
			pos.col = 0;
			pos.row += raw.length;

			var indentation = /^\t*/.exec(lex.remaining.substr(raw.length))[0].length;
			increment(indentation);

			pos.col += indentation;

			var tokens = ['TERMINATOR'];

			if (indentation > indent[0]) {
				// indentation level increased
				indent.unshift(indentation);
				tokens.push('IND');
			} else if (indentation < indent[0]) {
				// indentation level decreased
				while (indentation < indent[0]) {
					tokens.push('DED');
					tokens.push('TERMINATOR');
					indent.shift();
				}
			}

			return tokens;
		}
	],
	comment: [
		/^\#[^\n]*/,
		function (raw) {
			pos.col += raw.length;
			return 'COMMENT';
		}
	],
	identifier: [
		/^[a-zA-Z\$\_][a-zA-Z0-9\$\_]*/,
		function (raw, lex, modify) {
			pos.col += raw.length;

			if (RESERVED_AR.indexOf(raw) > -1 || RESERVED_JS.indexOf(raw) > -1) {
				// reserved ARTHUR or JS word

				// this bit of code is really what this entire custom lexer is
				// about. to solve the problem of the "dangling else" I needed a
				// lexer that would remove the ambiguous TERMINATOR that occured
				// between IF blocks and ELSE blocks. I needed to build my own because
				// Lex.js didn't offer the granular support I required. anyway,
				// enough rambling: here it is, stupid thing
				var removedPrevTerminator = ['else', 'elseif', 'catch', 'finally'];
				if ((removedPrevTerminator.indexOf(raw) !== -1) && lex.tokens[lex.tokens.length - 1] === 'TERMINATOR') {
					lex.tokens.pop();
					lex.literals.pop();
				}

				if (raw === 'typeof') {
					if (lex.tokens[lex.tokens.length - 1] === '!') {
						lex.tokens.pop();
						lex.literals.pop();
						modify('!typeof');
					}
					return 'LOGIC';
				} else if (raw === 'instanceof') {
					if (lex.tokens[lex.tokens.length - 1] === '!') {
						lex.tokens.pop();
						lex.literals.pop();
						modify('!instanceof');
					}
					return 'LOGIC';
				}

				return raw.toUpperCase();
			} else {
				return 'IDENTIFIER';
			}
		}
	],
	logicSymbol: [
		/^\>\=|^\<\=|^\=\=|^\!\=|^\&\&|^\|\||^\>|^\</,
		function (raw) {
			pos.col += raw.length;

			return 'LOGIC';
		}
	],
	literalSymbol: [
		/^\+\+|^\+|^\-\-|^\.\.|^\.|^\-|^\/|^\*\*|^\*|^\,|^\(|^\)|^\[|^\]|^\{|^\}|^\=|^\:|^\?|^\@|^\!/,
		function (raw) {
			pos.col += raw.length;

			if (['+', '-', '*', '/', '**'].indexOf(raw) > -1) {
				return 'MATH';
			} else {
				return raw;
			}
		}
	],
	string: [
		/^\'(?:[^\'\\]|\\.)*\'/,
		function (raw, lex, modify) {
			pos.col += raw.length;

			// remove quotes from string
			modify(raw.substr(1).substr(0, raw.length - 2));

			return 'STRING';
		}
	],
	number: [
		/^\-?[0-9]+(?:\.[0-9]+)?/,
		function (raw) {
			pos.col += raw.length;

			return 'NUMBER';
		}
	],
	regex: [
		/^\/(?:[^\/\\]|\\.)+\//,
		function (raw) {
			pos.col += raw.length;

			return 'REGEX';
		}
	],
	unexpected: [
		/^./,
		function (raw, lex) {
			throw Error('Unexpected "' + raw + '" at line ' + (pos.row + 1) + ', column ' + (pos.col + 1));
		}
	]
};

var WHITESPACE = ['TERMINATOR', 'IND', 'DED'];
var RESERVED_AR = ['def', 'as', 'elseif'];
var RESERVED_JS = ['true', 'false', 'null', 'if', 'else', 'return', 'for', 'while', 'in', 'typeof', 'instanceof', 'break', 'throw', 'new'];

// `check` inspects a specific rule to see if it matches
// the remainder of the string. if the rule does, `check`
// returns the number of
function check(lex, rule) {
	var match = rule[0].exec(lex.remaining);
	if (match !== null) {
		// advance the index
		var advancement = match[0].length;

		var result = rule[1](match[0], lex, function (modification) {
			match[0] = modification;
		}, function (increment) {
			advancement += increment;
		});
		if (result !== false) {
			if (result instanceof Array) {
				// multiple tokens returned
				for (var i = 0, len = result.length; i < len; i++) {
					lex.literals.push(false);
					lex.tokens.push(result[i]);
				}
			} else {
				if (WHITESPACE.indexOf(result) > -1) {
					lex.literals.push(false);
				} else {
					lex.literals.push(match[0]);
				}
				lex.tokens.push(result);
			}
		}
		return advancement;
	} else {
		return false;
	}
}

function Lexer() {
	this.tokens = [];
	this.literals = [];
	this.remaining;
	this.index = 0;
	this.setInput = function (input) {
		this.input = input;
		this.remaining = input;
	};
	this.lex = function () {
		while (this.remaining.length > 0) {
			// `check` returns `number` or `false`
			// if nothing recognizes the symbol, it gets passed
			// to a catch-all `unexpected` which throws an exception
			this.index += check(this, rules.space) ||
				check(this, rules.terminator) ||
				check(this, rules.string) ||
				check(this, rules.number) ||
				check(this, rules.regex) ||
				check(this, rules.comment) ||
				check(this, rules.identifier) ||
				check(this, rules.logicSymbol) ||
				check(this, rules.literalSymbol) ||
				check(this, rules.unexpected);

			this.remaining = this.input.substr(this.index);
		}

		return {
			tokens: this.tokens,
			literals: this.literals
		};
	};
}

// this chunk wraps the above code into an interface
// compatible with Jison. when `setInput` is called,
// the lexer tokenizes the ENTIRE string, modifying
// the stream as required. the stream is then fed token
// by token back to Jison as needed
exports.lexer = function () {
	var scanner = new Lexer();
	var tokens, literals;
	var i = -1;
	this.setInput = function (input, returnQuick) {
		scanner.setInput(input);
		var results = scanner.lex();
		tokens = results.tokens;
		literals = results.literals;
		if (returnQuick === true) {
			console.log(tokens);
			return;
		}
		return this;
	};

	this.lex = function () {
		i++;
		if (literals[i] !== false) {
			this.yytext = literals[i];
		}
		return tokens[i];
	}
};<commit_msg>add try/catch/finally as reserved words<commit_after>'use strict';

var indent = [0];
var pos = {
	col: 0,
	row: 0
}

var rules = {
	space: [
		/^ +/,
		function (raw) {
			pos.col += raw.length;
			return false;
		}
	],
	terminator: [
		/^\n+/,
		function (raw, lex, modify, increment) {
			pos.col = 0;
			pos.row += raw.length;

			var indentation = /^\t*/.exec(lex.remaining.substr(raw.length))[0].length;
			increment(indentation);

			pos.col += indentation;

			var tokens = ['TERMINATOR'];

			if (indentation > indent[0]) {
				// indentation level increased
				indent.unshift(indentation);
				tokens.push('IND');
			} else if (indentation < indent[0]) {
				// indentation level decreased
				while (indentation < indent[0]) {
					tokens.push('DED');
					tokens.push('TERMINATOR');
					indent.shift();
				}
			}

			return tokens;
		}
	],
	comment: [
		/^\#[^\n]*/,
		function (raw) {
			pos.col += raw.length;
			return 'COMMENT';
		}
	],
	identifier: [
		/^[a-zA-Z\$\_][a-zA-Z0-9\$\_]*/,
		function (raw, lex, modify) {
			pos.col += raw.length;

			if (RESERVED_AR.indexOf(raw) > -1 || RESERVED_JS.indexOf(raw) > -1) {
				// reserved ARTHUR or JS word

				// this bit of code is really what this entire custom lexer is
				// about. to solve the problem of the "dangling else" I needed a
				// lexer that would remove the ambiguous TERMINATOR that occured
				// between IF blocks and ELSE blocks. I needed to build my own because
				// Lex.js didn't offer the granular support I required. anyway,
				// enough rambling: here it is, stupid thing
				var removedPrevTerminator = ['else', 'elseif', 'catch', 'finally'];
				if ((removedPrevTerminator.indexOf(raw) !== -1) && lex.tokens[lex.tokens.length - 1] === 'TERMINATOR') {
					lex.tokens.pop();
					lex.literals.pop();
				}

				if (raw === 'typeof') {
					if (lex.tokens[lex.tokens.length - 1] === '!') {
						lex.tokens.pop();
						lex.literals.pop();
						modify('!typeof');
					}
					return 'LOGIC';
				} else if (raw === 'instanceof') {
					if (lex.tokens[lex.tokens.length - 1] === '!') {
						lex.tokens.pop();
						lex.literals.pop();
						modify('!instanceof');
					}
					return 'LOGIC';
				}

				return raw.toUpperCase();
			} else {
				return 'IDENTIFIER';
			}
		}
	],
	logicSymbol: [
		/^\>\=|^\<\=|^\=\=|^\!\=|^\&\&|^\|\||^\>|^\</,
		function (raw) {
			pos.col += raw.length;

			return 'LOGIC';
		}
	],
	literalSymbol: [
		/^\+\+|^\+|^\-\-|^\.\.|^\.|^\-|^\/|^\*\*|^\*|^\,|^\(|^\)|^\[|^\]|^\{|^\}|^\=|^\:|^\?|^\@|^\!/,
		function (raw) {
			pos.col += raw.length;

			if (['+', '-', '*', '/', '**'].indexOf(raw) > -1) {
				return 'MATH';
			} else {
				return raw;
			}
		}
	],
	string: [
		/^\'(?:[^\'\\]|\\.)*\'/,
		function (raw, lex, modify) {
			pos.col += raw.length;

			// remove quotes from string
			modify(raw.substr(1).substr(0, raw.length - 2));

			return 'STRING';
		}
	],
	number: [
		/^\-?[0-9]+(?:\.[0-9]+)?/,
		function (raw) {
			pos.col += raw.length;

			return 'NUMBER';
		}
	],
	regex: [
		/^\/(?:[^\/\\]|\\.)+\//,
		function (raw) {
			pos.col += raw.length;

			return 'REGEX';
		}
	],
	unexpected: [
		/^./,
		function (raw, lex) {
			throw Error('Unexpected "' + raw + '" at line ' + (pos.row + 1) + ', column ' + (pos.col + 1));
		}
	]
};

var WHITESPACE = ['TERMINATOR', 'IND', 'DED'];
var RESERVED_AR = ['def', 'as', 'elseif'];
var RESERVED_JS = ['true', 'false', 'null', 'if', 'else', 'return', 'for', 'while', 'in', 'typeof', 'instanceof', 'break', 'throw', 'new', 'try', 'catch', 'finally'];

// `check` inspects a specific rule to see if it matches
// the remainder of the string. if the rule does, `check`
// returns the number of
function check(lex, rule) {
	var match = rule[0].exec(lex.remaining);
	if (match !== null) {
		// advance the index
		var advancement = match[0].length;

		var result = rule[1](match[0], lex, function (modification) {
			match[0] = modification;
		}, function (increment) {
			advancement += increment;
		});
		if (result !== false) {
			if (result instanceof Array) {
				// multiple tokens returned
				for (var i = 0, len = result.length; i < len; i++) {
					lex.literals.push(false);
					lex.tokens.push(result[i]);
				}
			} else {
				if (WHITESPACE.indexOf(result) > -1) {
					lex.literals.push(false);
				} else {
					lex.literals.push(match[0]);
				}
				lex.tokens.push(result);
			}
		}
		return advancement;
	} else {
		return false;
	}
}

function Lexer() {
	this.tokens = [];
	this.literals = [];
	this.remaining;
	this.index = 0;
	this.setInput = function (input) {
		this.input = input;
		this.remaining = input;
	};
	this.lex = function () {
		while (this.remaining.length > 0) {
			// `check` returns `number` or `false`
			// if nothing recognizes the symbol, it gets passed
			// to a catch-all `unexpected` which throws an exception
			this.index += check(this, rules.space) ||
				check(this, rules.terminator) ||
				check(this, rules.string) ||
				check(this, rules.number) ||
				check(this, rules.regex) ||
				check(this, rules.comment) ||
				check(this, rules.identifier) ||
				check(this, rules.logicSymbol) ||
				check(this, rules.literalSymbol) ||
				check(this, rules.unexpected);

			this.remaining = this.input.substr(this.index);
		}

		return {
			tokens: this.tokens,
			literals: this.literals
		};
	};
}

// this chunk wraps the above code into an interface
// compatible with Jison. when `setInput` is called,
// the lexer tokenizes the ENTIRE string, modifying
// the stream as required. the stream is then fed token
// by token back to Jison as needed
exports.lexer = function () {
	var scanner = new Lexer();
	var tokens, literals;
	var i = -1;
	this.setInput = function (input, returnQuick) {
		scanner.setInput(input);
		var results = scanner.lex();
		tokens = results.tokens;
		literals = results.literals;
		if (returnQuick === true) {
			console.log(tokens);
			return;
		}
		return this;
	};

	this.lex = function () {
		i++;
		if (literals[i] !== false) {
			this.yytext = literals[i];
		}
		return tokens[i];
	};
};<|endoftext|>


<commit_before>var unicode = require('unicode-categories');

// http://es5.github.com/#x7.6
// ECMAscript identifier starts with `$`, `_`,
// or letter from (Lu Ll Lt Lm Lo Nl) unicode groups.
// Then identifier can also be from groups (Nd, Mn, Mc, or Pc).
// Roy identifier cannot have letter u03BB (greek lowercase lambda)
// because it's used in anonymous functions.
var IDENTIFIER = new RegExp(
    unicode.ECMA.identifier.source.replace('\\u03BB', '')
);

var NUMBER = /^-?[0-9]+(\.[0-9]+)?/;
var COMMENT = /^\/\/.*/;
var WHITESPACE = /^[^\n\S]+/;
var INDENT = /^(?:\n[^\n\S]*)+/;

var chunk;
var indent;
var indents;
var tokens;
var lineno;

var identifierToken = function() {
    var value,
        name,
        token = IDENTIFIER.exec(chunk);
    if(token) {
        value = token[0];
        switch(value) {
        case 'true':
        case 'false':
            name = 'BOOLEAN';
            break;
        case 'let':
        case 'if':
        case 'then':
        case 'else':
        case 'data':
        case 'type':
        case 'match':
        case 'case':
        case 'do':
        case 'return':
        case 'macro':
        case 'with':
            name = value.toUpperCase();
            break;
        default:
            name = 'IDENTIFIER';
            break;
        }
        tokens.push([name, value, lineno]);
        return token[0].length;
    }
    return 0;
};

var numberToken = function() {
    var token = NUMBER.exec(chunk);
    if(token) {
        tokens.push(['NUMBER', token[0], lineno]);
        return token[0].length;
    }
    return 0;
};

var stringToken = function() {
    var firstChar = chunk.charAt(0),
        quoted = false,
        nextChar;
    if(firstChar == '"' || firstChar == "'") {
        for(var i = 1; i < chunk.length; i++) {
            if(!quoted) {
                nextChar = chunk.charAt(i);
                if(nextChar == "\\") {
                    quoted = true;
                } else if(nextChar == firstChar) {
                    tokens.push(['STRING', chunk.substring(0, i + 1), lineno]);
                    return i + 1;
                }
            } else {
                quoted = false;
            }
        }
    }
    return 0;
};

var commentToken = function() {
    var token = COMMENT.exec(chunk);
    if(token) {
        tokens.push(['COMMENT', token[0], lineno]);
        return token[0].length;
    }
    return 0;
};

var whitespaceToken = function() {
    var token = WHITESPACE.exec(chunk);
    if(token) {
        return token[0].length;
    }
    return 0;
};

var lineToken = function() {
    var token = INDENT.exec(chunk);
    if(token) {
        var lastNewline = token[0].lastIndexOf("\n") + 1;
        var size = token[0].length - lastNewline;
        var terminated = false;
        if(size > indent) {
            indents.push(size);
            tokens.push(['INDENT', size - indent, lineno]);
        } else {
            if(size < indent) {
                var last = indents[indents.length - 1];
                while(size < last) {
                    tokens.push(['OUTDENT', last - size, lineno]);
                    indents.pop();
                    last = indents[indents.length - 1];
                }
            }
            if(tokens.length > 0)
                tokens.push(['TERMINATOR', token[0].substring(0, lastNewline), lineno]);
        }
        indent = size;
        return token[0].length;
    }
    return 0;
};

var literalToken = function() {
    var tag = chunk.slice(0, 1);
    var next;
    switch(tag) {
    case '<':
        next = chunk.slice(0, 2);
        if(next == '<-') {
            tokens.push(['LEFTARROW', next, lineno]);
            return 2;
        } else if(next == '<<') {
            tokens.push(['MATH', next, lineno]);
            return 2;
        }
        tokens.push(['COMPARE', tag, lineno]);
        return 1;
    case '>':
        next = chunk.slice(0, 2);
        if(next == '>>') {
            tokens.push(['MATH', next, lineno]);
            return 2;
        }
        tokens.push(['COMPARE', tag, lineno]);
        return 1;
    case '=':
        next = chunk.slice(0, 2);
        if(next == '==') {
            tokens.push(['COMPARE', next, lineno]);
            return 2;
        }
        tokens.push([tag, tag, lineno]);
        return 1;
    case '!':
        next = chunk.slice(0, 2);
        if(next == '!=') {
            tokens.push(['COMPARE', next, lineno]);
            return 2;
        }
        tokens.push([tag, tag, lineno]);
        return 1;
    case '*':
    case '/':
    case '%':
        tokens.push(['MATH', tag, lineno]);
        return 1;
    case '[':
    case '|':
        next = chunk.slice(0, 2);
        switch(next) {
        case '[|':
        case '|]':
            tokens.push([next, next, lineno]);
            return 2;
        }
        tokens.push([tag, tag, lineno]);
        return 1;
    case ')':
        if(tokens[tokens.length-1][0] == 'TERMINATOR') {
            tokens.pop();
        }
        tokens.push([tag, tag, lineno]);
        return 1;
    case '+':
        next = chunk.slice(0, 2);
        if(next == '++') {
            tokens.push(['CONCAT', tag, lineno]);
            return 2;
        }
        tokens.push([tag, tag, lineno]);
        return 1;
    case '-':
        next = chunk.slice(0, 2);
        if (next == '->') {
            tokens.push(['RIGHTARROW', next, lineno]);
            return 2;
        }
        tokens.push([tag, tag, lineno]);
        return 1;
    case '&':
        next = chunk.slice(0, 2);
        if(next == '&&') {
            tokens.push(['BOOLOP', next, lineno]);
            return 2;
        }
        tokens.push([tag, tag, lineno]);
        return 1;
    case '|':
        next = chunk.slice(0, 2);
        if(next == '||') {
            tokens.push(['BOOLOP', next, lineno]);
            return 2;
        }
        tokens.push([tag, tag, lineno]);
        return 1;
    case 'λ':
    case '\\':
        tokens.push(['LAMBDA', tag, lineno]);
        return 1;
    case '←':
        tokens.push(['LEFTARROW', tag, lineno]);
        return 1;
    case '→':
        tokens.push(['RIGHTARROW', tag, lineno]);
        return 1;
    case '⇒':
        tokens.push(['RIGHTFATARROW', tag, lineno]);
        return 1;
    case ']':
    case ':':
    case '.':
    case ',':
    case '{':
    case '}':
    case '(':
        tokens.push([tag, tag, lineno]);
        return 1;
    }
    return 0;
};

exports.tokenise = function(source) {
    indent = 0;
    indents = [];
    tokens = [];
    lineno = 1;
    var i = 0;
    while(chunk = source.slice(i)) {
        var diff = identifierToken() || numberToken() || stringToken() || commentToken() || whitespaceToken() || lineToken() || literalToken();
        if(!diff) {
            throw "Couldn't tokenise: " + chunk.substring(0, chunk.indexOf("\n"));
        }
        lineno += source.slice(i, i + diff).split('\n').length - 1;
        i += diff;
    }
    tokens.push(['EOF', '', lineno]);
    return tokens;
};

if(!module.parent) {
    exports.tokenise([
        "// Testing",
        " ",
        "let x =",
        " 8",
        " if true then 10 else 100",
        " if true then",
        "  false",
        " else",
        "  true",
        " // Inner comment",
        " console.log 10 * 20",
        " console.log [1, 2, 3].length",
        " true",
        "console.log 'example'"
    ].join("\n"));
    console.log(tokens);
}
<commit_msg>fix lexer for token ||<commit_after>var unicode = require('unicode-categories');

// http://es5.github.com/#x7.6
// ECMAscript identifier starts with `$`, `_`,
// or letter from (Lu Ll Lt Lm Lo Nl) unicode groups.
// Then identifier can also be from groups (Nd, Mn, Mc, or Pc).
// Roy identifier cannot have letter u03BB (greek lowercase lambda)
// because it's used in anonymous functions.
var IDENTIFIER = new RegExp(
    unicode.ECMA.identifier.source.replace('\\u03BB', '')
);

var NUMBER = /^-?[0-9]+(\.[0-9]+)?/;
var COMMENT = /^\/\/.*/;
var WHITESPACE = /^[^\n\S]+/;
var INDENT = /^(?:\n[^\n\S]*)+/;

var chunk;
var indent;
var indents;
var tokens;
var lineno;

var identifierToken = function() {
    var value,
        name,
        token = IDENTIFIER.exec(chunk);
    if(token) {
        value = token[0];
        switch(value) {
        case 'true':
        case 'false':
            name = 'BOOLEAN';
            break;
        case 'let':
        case 'if':
        case 'then':
        case 'else':
        case 'data':
        case 'type':
        case 'match':
        case 'case':
        case 'do':
        case 'return':
        case 'macro':
        case 'with':
            name = value.toUpperCase();
            break;
        default:
            name = 'IDENTIFIER';
            break;
        }
        tokens.push([name, value, lineno]);
        return token[0].length;
    }
    return 0;
};

var numberToken = function() {
    var token = NUMBER.exec(chunk);
    if(token) {
        tokens.push(['NUMBER', token[0], lineno]);
        return token[0].length;
    }
    return 0;
};

var stringToken = function() {
    var firstChar = chunk.charAt(0),
        quoted = false,
        nextChar;
    if(firstChar == '"' || firstChar == "'") {
        for(var i = 1; i < chunk.length; i++) {
            if(!quoted) {
                nextChar = chunk.charAt(i);
                if(nextChar == "\\") {
                    quoted = true;
                } else if(nextChar == firstChar) {
                    tokens.push(['STRING', chunk.substring(0, i + 1), lineno]);
                    return i + 1;
                }
            } else {
                quoted = false;
            }
        }
    }
    return 0;
};

var commentToken = function() {
    var token = COMMENT.exec(chunk);
    if(token) {
        tokens.push(['COMMENT', token[0], lineno]);
        return token[0].length;
    }
    return 0;
};

var whitespaceToken = function() {
    var token = WHITESPACE.exec(chunk);
    if(token) {
        return token[0].length;
    }
    return 0;
};

var lineToken = function() {
    var token = INDENT.exec(chunk);
    if(token) {
        var lastNewline = token[0].lastIndexOf("\n") + 1;
        var size = token[0].length - lastNewline;
        var terminated = false;
        if(size > indent) {
            indents.push(size);
            tokens.push(['INDENT', size - indent, lineno]);
        } else {
            if(size < indent) {
                var last = indents[indents.length - 1];
                while(size < last) {
                    tokens.push(['OUTDENT', last - size, lineno]);
                    indents.pop();
                    last = indents[indents.length - 1];
                }
            }
            if(tokens.length > 0)
                tokens.push(['TERMINATOR', token[0].substring(0, lastNewline), lineno]);
        }
        indent = size;
        return token[0].length;
    }
    return 0;
};

var literalToken = function() {
    var tag = chunk.slice(0, 1);
    var next;
    switch(tag) {
    case '<':
        next = chunk.slice(0, 2);
        if(next == '<-') {
            tokens.push(['LEFTARROW', next, lineno]);
            return 2;
        } else if(next == '<<') {
            tokens.push(['MATH', next, lineno]);
            return 2;
        }
        tokens.push(['COMPARE', tag, lineno]);
        return 1;
    case '>':
        next = chunk.slice(0, 2);
        if(next == '>>') {
            tokens.push(['MATH', next, lineno]);
            return 2;
        }
        tokens.push(['COMPARE', tag, lineno]);
        return 1;
    case '=':
        next = chunk.slice(0, 2);
        if(next == '==') {
            tokens.push(['COMPARE', next, lineno]);
            return 2;
        }
        tokens.push([tag, tag, lineno]);
        return 1;
    case '!':
        next = chunk.slice(0, 2);
        if(next == '!=') {
            tokens.push(['COMPARE', next, lineno]);
            return 2;
        }
        tokens.push([tag, tag, lineno]);
        return 1;
    case '*':
    case '/':
    case '%':
        tokens.push(['MATH', tag, lineno]);
        return 1;
    case '[':
    case '|':
        next = chunk.slice(0, 2);
        switch(next) {
        case '[|':
        case '|]':
            tokens.push([next, next, lineno]);
            return 2;
        case '||':
            tokens.push(['BOOLOP', next, lineno]);
            return 2;
        }
        tokens.push([tag, tag, lineno]);
        return 1;
    case ')':
        if(tokens[tokens.length-1][0] == 'TERMINATOR') {
            tokens.pop();
        }
        tokens.push([tag, tag, lineno]);
        return 1;
    case '+':
        next = chunk.slice(0, 2);
        if(next == '++') {
            tokens.push(['CONCAT', tag, lineno]);
            return 2;
        }
        tokens.push([tag, tag, lineno]);
        return 1;
    case '-':
        next = chunk.slice(0, 2);
        if (next == '->') {
            tokens.push(['RIGHTARROW', next, lineno]);
            return 2;
        }
        tokens.push([tag, tag, lineno]);
        return 1;
    case '&':
        next = chunk.slice(0, 2);
        if(next == '&&') {
            tokens.push(['BOOLOP', next, lineno]);
            return 2;
        }
        tokens.push([tag, tag, lineno]);
        return 1;
    case 'λ':
    case '\\':
        tokens.push(['LAMBDA', tag, lineno]);
        return 1;
    case '←':
        tokens.push(['LEFTARROW', tag, lineno]);
        return 1;
    case '→':
        tokens.push(['RIGHTARROW', tag, lineno]);
        return 1;
    case '⇒':
        tokens.push(['RIGHTFATARROW', tag, lineno]);
        return 1;
    case ']':
    case ':':
    case '.':
    case ',':
    case '{':
    case '}':
    case '(':
        tokens.push([tag, tag, lineno]);
        return 1;
    }
    return 0;
};

exports.tokenise = function(source) {
    indent = 0;
    indents = [];
    tokens = [];
    lineno = 1;
    var i = 0;
    while(chunk = source.slice(i)) {
        var diff = identifierToken() || numberToken() || stringToken() || commentToken() || whitespaceToken() || lineToken() || literalToken();
        if(!diff) {
            throw "Couldn't tokenise: " + chunk.substring(0, chunk.indexOf("\n"));
        }
        lineno += source.slice(i, i + diff).split('\n').length - 1;
        i += diff;
    }
    tokens.push(['EOF', '', lineno]);
    return tokens;
};

if(!module.parent) {
    exports.tokenise([
        "// Testing",
        " ",
        "let x =",
        " 8",
        " if true then 10 else 100",
        " if true then",
        "  false",
        " else",
        "  true",
        " // Inner comment",
        " console.log 10 * 20",
        " console.log [1, 2, 3].length",
        " true",
        "console.log 'example'"
    ].join("\n"));
    console.log(tokens);
}
<|endoftext|>


<commit_before>import ShaderProgram from './gl/shader_program';
import GLSL from './gl/glsl';
import Geo from './geo';
import {StyleParser} from './styles/style_parser';

let fs = require('fs');

const shaderSrc_ambientLight = fs.readFileSync(__dirname + '/gl/shaders/ambientLight.glsl', 'utf8');
const shaderSrc_directionalLight = fs.readFileSync(__dirname + '/gl/shaders/directionalLight.glsl', 'utf8');
const shaderSrc_pointLight = fs.readFileSync(__dirname + '/gl/shaders/pointLight.glsl', 'utf8');
const shaderSrc_spotLight = fs.readFileSync(__dirname + '/gl/shaders/spotLight.glsl', 'utf8');

// Abstract light
export default class Light {

    constructor (view, config) {
        this.name = config.name;
        this.view = view;

        if (config.ambient == null || typeof config.ambient === 'number') {
            this.ambient = GLSL.expandVec4(config.ambient || 0);
        }
        else {
            this.ambient = StyleParser.parseColor(config.ambient);
        }

        if (config.diffuse == null || typeof config.diffuse === 'number') {
            this.diffuse = GLSL.expandVec4(config.diffuse != null ? config.diffuse : 1);
        }
        else {
            this.diffuse = StyleParser.parseColor(config.diffuse);
        }

        if (config.specular == null || typeof config.specular === 'number') {
            this.specular = GLSL.expandVec4(config.specular || 0);
        }
        else {
            this.specular = StyleParser.parseColor(config.specular);
        }
    }

    // Create a light by type name, factory-style
    // 'config' must include 'name' and 'type', along with any other type-specific properties
    static create (view, config) {
        if (Light.types[config.type]) {
            return new Light.types[config.type](view, config);
        }
    }

    // Set light for a style: fragment lighting, vertex lighting, or none
    static setMode (mode, style) {
        if (mode === true) {
            mode = 'fragment';
        }
        mode = Light.enabled && ((mode != null) ? mode : 'fragment'); // default to fragment lighting
        style.defines['TANGRAM_LIGHTING_FRAGMENT'] = (mode === 'fragment');
        style.defines['TANGRAM_LIGHTING_VERTEX'] = (mode === 'vertex');
    }

    // Inject all provided light definitions, and calculate cumulative light function
    static inject (lights) {
        // Clear previous injections
        ShaderProgram.removeBlock(Light.block);

        // If lighting is globally disabled, nothing is injected (mostly for debugging or live editing)
        if (!Light.enabled) {
            return;
        }

        // Construct code to calculate each light instance
        let calculateLights = "";
        if (lights && Object.keys(lights).length > 0) {
            // Collect uniques types of lights
            let types = {};
            for (let light_name in lights) {
                types[lights[light_name].type] = true;
            }

            // Inject each type of light
            for (let type in types) {
                Light.types[type].inject();
            }

            // Inject per-instance blocks and construct the list of functions to calculate each light
            for (let light_name in lights) {
                // Define instance
                lights[light_name].inject();

                // Add the calculation function to the list
                calculateLights += `calculateLight(${light_name}, _eyeToPoint, _normal);\n`;
            }
        }
        else {
            // If no light is defined, use 100% omnidirectional diffuse light
            calculateLights = `
                #ifdef TANGRAM_MATERIAL_DIFFUSE
                    light_accumulator_diffuse = vec4(1.);
                #endif
            `;
        }

        // Glue together the final lighting function that sums all the lights
        let calculateFunction = `
            vec4 calculateLighting(in vec3 _eyeToPoint, in vec3 _normal, in vec4 _color) {

                // Do initial material calculations over normal, emission, ambient, diffuse and specular values
                calculateMaterial(_eyeToPoint,_normal);

                // Un roll the loop of individual ligths to calculate
                ${calculateLights}

                //  Final light intensity calculation
                vec4 color = vec4(0.0);

                #ifdef TANGRAM_MATERIAL_EMISSION
                    color = material.emission;
                #endif

                #ifdef TANGRAM_MATERIAL_AMBIENT
                    color += light_accumulator_ambient * _color * material.ambient;
                #else
                    #ifdef TANGRAM_MATERIAL_DIFFUSE
                        color += light_accumulator_ambient * _color * material.diffuse;
                    #endif
                #endif

                #ifdef TANGRAM_MATERIAL_DIFFUSE
                    color += light_accumulator_diffuse * _color * material.diffuse;
                #endif

                #ifdef TANGRAM_MATERIAL_SPECULAR
                    color += light_accumulator_specular * material.specular;
                #endif

                // Clamp final color
                color = clamp(color, 0.0, 1.0);

                return color;
            }`;

        ShaderProgram.addBlock(Light.block, calculateFunction);
    }

    // Common instance definition
    inject () {
        let instance =  `
            uniform ${this.struct_name} u_${this.name};
            ${this.struct_name} ${this.name};
            `;
        let assign = `
            ${this.name} = u_${this.name};\n
        `;

        ShaderProgram.addBlock(Light.block, instance);
        ShaderProgram.addBlock('setup', assign);
    }

    // Update method called once per frame
    update () {
    }

    // Called once per frame per program (e.g. for main render pass, then for each additional
    // pass for feature selection, etc.)
    setupProgram (_program) {
        //  Three common light properties
        _program.uniform('4fv', `u_${this.name}.ambient`, this.ambient);
        _program.uniform('4fv', `u_${this.name}.diffuse`, this.diffuse);
        _program.uniform('4fv', `u_${this.name}.specular`, this.specular);
    }

}

Light.types = {}; // references to subclasses by short name
Light.block = 'lighting'; // shader block name
Light.enabled = true; // lighting can be globally enabled/disabled

// Light subclasses
class AmbientLight extends Light {

    constructor(view, config) {
        super(view, config);
        this.type = 'ambient';
        this.struct_name = 'AmbientLight';
    }

    // Inject struct and calculate function
    static inject() {
        ShaderProgram.addBlock(Light.block, shaderSrc_ambientLight);
    }

    setupProgram (_program) {
        _program.uniform('4fv', `u_${this.name}.ambient`, this.ambient);
    }

}
Light.types['ambient'] = AmbientLight;

class DirectionalLight extends Light {

    constructor(view, config) {
        super(view, config);
        this.type = 'directional';
        this.struct_name = 'DirectionalLight';

        this.direction = (config.direction || [0.2, 0.7, -0.5]).map(parseFloat); // [x, y, z]
    }

    // Inject struct and calculate function
    static inject() {
        ShaderProgram.addBlock(Light.block, shaderSrc_directionalLight);
    }

    setupProgram (_program) {
        super.setupProgram(_program);
        _program.uniform('3fv', `u_${this.name}.direction`, this.direction);
    }

}
Light.types['directional'] = DirectionalLight;

class PointLight extends Light {

    constructor (view, config) {
        super(view, config);
        this.type = 'point';
        this.struct_name = 'PointLight';

        this.position = config.position || [0, 0, '100px'];
        this.position_eye = []; // position in eyespace
        this.origin = config.origin || 'ground';
        this.attenuation = !isNaN(parseFloat(config.attenuation)) ? parseFloat(config.attenuation) : 0;

        if (config.radius) {
            if (Array.isArray(config.radius) && config.radius.length === 2) {
                this.radius = config.radius;
            }
            else {
                this.radius = [null, config.radius];
            }
        }
        else {
            this.radius = null;
        }
    }

    // Inject struct and calculate function
    static inject () {
        ShaderProgram.addBlock(Light.block, shaderSrc_pointLight);
    }

    // Inject isntance-specific settings
    inject() {
        super.inject();

        ShaderProgram.defines['TANGRAM_POINTLIGHT_ATTENUATION_EXPONENT'] = (this.attenuation !== 0);
        ShaderProgram.defines['TANGRAM_POINTLIGHT_ATTENUATION_INNER_RADIUS'] = (this.radius != null && this.radius[0] != null);
        ShaderProgram.defines['TANGRAM_POINTLIGHT_ATTENUATION_OUTER_RADIUS'] = (this.radius != null);
    }

    update () {
        this.updateEyePosition();
    }

    updateEyePosition () {
        if (this.origin === 'world') {
            // For world origin, format is: [longitude, latitude, meters (default) or pixels w/px units]

            // Move light's world position into camera space
            let [x, y] = Geo.latLngToMeters(this.position);
            this.position_eye[0] = x - this.view.camera.position_meters[0];
            this.position_eye[1] = y - this.view.camera.position_meters[1];

            this.position_eye[2] = StyleParser.convertUnits(this.position[2],
                { zoom: this.view.zoom, meters_per_pixel: Geo.metersPerPixel(this.view.zoom) });
            this.position_eye[2] = this.position_eye[2] - this.view.camera.position_meters[2];
        }
        else if (this.origin === 'ground' || this.origin === 'camera') {
            // For camera or ground origin, format is: [x, y, z] in meters (default) or pixels w/px units

            // Light is in camera space by default
            this.position_eye = StyleParser.convertUnits(this.position,
                { zoom: this.view.zoom, meters_per_pixel: Geo.metersPerPixel(this.view.zoom) });

            if (this.origin === 'ground') {
                // Leave light's xy in camera space, but z needs to be moved relative to ground plane
                this.position_eye[2] = this.position_eye[2] - this.view.camera.position_meters[2];
            }
        }
        this.position_eye[3] = 1;
    }

    setupProgram (_program) {
        super.setupProgram(_program);

        _program.uniform('4fv', `u_${this.name}.position`, this.position_eye);

        if(ShaderProgram.defines['TANGRAM_POINTLIGHT_ATTENUATION_EXPONENT']) {
            _program.uniform('1f', `u_${this.name}.attenuationExponent`, this.attenuation);
        }

        if(ShaderProgram.defines['TANGRAM_POINTLIGHT_ATTENUATION_INNER_RADIUS']) {
            _program.uniform('1f', `u_${this.name}.innerRadius`,
                StyleParser.convertUnits(this.radius[0],
                    { zoom: this.view.zoom, meters_per_pixel: Geo.metersPerPixel(this.view.zoom) }));
        }

        if(ShaderProgram.defines['TANGRAM_POINTLIGHT_ATTENUATION_OUTER_RADIUS']) {
            _program.uniform('1f', `u_${this.name}.outerRadius`,
                StyleParser.convertUnits(this.radius[1],
                    { zoom: this.view.zoom, meters_per_pixel: Geo.metersPerPixel(this.view.zoom) }));
        }
    }
}
Light.types['point'] = PointLight;

class SpotLight extends PointLight {

    constructor (view, config) {
        super(view, config);
        this.type = 'spotlight';
        this.struct_name = 'SpotLight';

        this.direction = (config.direction || [0, 0, -1]).map(parseFloat); // [x, y, z]
        this.exponent = config.exponent ? parseFloat(config.exponent) : 0.2;
        this.angle = config.angle ? parseFloat(config.angle) : 20;
    }

    // Inject struct and calculate function
    static inject () {
        ShaderProgram.addBlock(Light.block, shaderSrc_spotLight);
    }

    setupProgram (_program) {
        super.setupProgram(_program);

        _program.uniform('3fv', `u_${this.name}.direction`, this.direction);
        _program.uniform('1f', `u_${this.name}.spotCosCutoff`, Math.cos(this.angle * 3.14159 / 180));
        _program.uniform('1f', `u_${this.name}.spotExponent`, this.exponent);
    }

}
Light.types['spotlight'] = SpotLight;
<commit_msg>lights: change directional light default to provide more common sense results full intensify on things facing straight up (ground plane, tops of buildings), with reasonable shading of extruded objects (building walls)<commit_after>import ShaderProgram from './gl/shader_program';
import GLSL from './gl/glsl';
import Geo from './geo';
import {StyleParser} from './styles/style_parser';

let fs = require('fs');

const shaderSrc_ambientLight = fs.readFileSync(__dirname + '/gl/shaders/ambientLight.glsl', 'utf8');
const shaderSrc_directionalLight = fs.readFileSync(__dirname + '/gl/shaders/directionalLight.glsl', 'utf8');
const shaderSrc_pointLight = fs.readFileSync(__dirname + '/gl/shaders/pointLight.glsl', 'utf8');
const shaderSrc_spotLight = fs.readFileSync(__dirname + '/gl/shaders/spotLight.glsl', 'utf8');

// Abstract light
export default class Light {

    constructor (view, config) {
        this.name = config.name;
        this.view = view;

        if (config.ambient == null || typeof config.ambient === 'number') {
            this.ambient = GLSL.expandVec4(config.ambient || 0);
        }
        else {
            this.ambient = StyleParser.parseColor(config.ambient);
        }

        if (config.diffuse == null || typeof config.diffuse === 'number') {
            this.diffuse = GLSL.expandVec4(config.diffuse != null ? config.diffuse : 1);
        }
        else {
            this.diffuse = StyleParser.parseColor(config.diffuse);
        }

        if (config.specular == null || typeof config.specular === 'number') {
            this.specular = GLSL.expandVec4(config.specular || 0);
        }
        else {
            this.specular = StyleParser.parseColor(config.specular);
        }
    }

    // Create a light by type name, factory-style
    // 'config' must include 'name' and 'type', along with any other type-specific properties
    static create (view, config) {
        if (Light.types[config.type]) {
            return new Light.types[config.type](view, config);
        }
    }

    // Set light for a style: fragment lighting, vertex lighting, or none
    static setMode (mode, style) {
        if (mode === true) {
            mode = 'fragment';
        }
        mode = Light.enabled && ((mode != null) ? mode : 'fragment'); // default to fragment lighting
        style.defines['TANGRAM_LIGHTING_FRAGMENT'] = (mode === 'fragment');
        style.defines['TANGRAM_LIGHTING_VERTEX'] = (mode === 'vertex');
    }

    // Inject all provided light definitions, and calculate cumulative light function
    static inject (lights) {
        // Clear previous injections
        ShaderProgram.removeBlock(Light.block);

        // If lighting is globally disabled, nothing is injected (mostly for debugging or live editing)
        if (!Light.enabled) {
            return;
        }

        // Construct code to calculate each light instance
        let calculateLights = "";
        if (lights && Object.keys(lights).length > 0) {
            // Collect uniques types of lights
            let types = {};
            for (let light_name in lights) {
                types[lights[light_name].type] = true;
            }

            // Inject each type of light
            for (let type in types) {
                Light.types[type].inject();
            }

            // Inject per-instance blocks and construct the list of functions to calculate each light
            for (let light_name in lights) {
                // Define instance
                lights[light_name].inject();

                // Add the calculation function to the list
                calculateLights += `calculateLight(${light_name}, _eyeToPoint, _normal);\n`;
            }
        }
        else {
            // If no light is defined, use 100% omnidirectional diffuse light
            calculateLights = `
                #ifdef TANGRAM_MATERIAL_DIFFUSE
                    light_accumulator_diffuse = vec4(1.);
                #endif
            `;
        }

        // Glue together the final lighting function that sums all the lights
        let calculateFunction = `
            vec4 calculateLighting(in vec3 _eyeToPoint, in vec3 _normal, in vec4 _color) {

                // Do initial material calculations over normal, emission, ambient, diffuse and specular values
                calculateMaterial(_eyeToPoint,_normal);

                // Un roll the loop of individual ligths to calculate
                ${calculateLights}

                //  Final light intensity calculation
                vec4 color = vec4(0.0);

                #ifdef TANGRAM_MATERIAL_EMISSION
                    color = material.emission;
                #endif

                #ifdef TANGRAM_MATERIAL_AMBIENT
                    color += light_accumulator_ambient * _color * material.ambient;
                #else
                    #ifdef TANGRAM_MATERIAL_DIFFUSE
                        color += light_accumulator_ambient * _color * material.diffuse;
                    #endif
                #endif

                #ifdef TANGRAM_MATERIAL_DIFFUSE
                    color += light_accumulator_diffuse * _color * material.diffuse;
                #endif

                #ifdef TANGRAM_MATERIAL_SPECULAR
                    color += light_accumulator_specular * material.specular;
                #endif

                // Clamp final color
                color = clamp(color, 0.0, 1.0);

                return color;
            }`;

        ShaderProgram.addBlock(Light.block, calculateFunction);
    }

    // Common instance definition
    inject () {
        let instance =  `
            uniform ${this.struct_name} u_${this.name};
            ${this.struct_name} ${this.name};
            `;
        let assign = `
            ${this.name} = u_${this.name};\n
        `;

        ShaderProgram.addBlock(Light.block, instance);
        ShaderProgram.addBlock('setup', assign);
    }

    // Update method called once per frame
    update () {
    }

    // Called once per frame per program (e.g. for main render pass, then for each additional
    // pass for feature selection, etc.)
    setupProgram (_program) {
        //  Three common light properties
        _program.uniform('4fv', `u_${this.name}.ambient`, this.ambient);
        _program.uniform('4fv', `u_${this.name}.diffuse`, this.diffuse);
        _program.uniform('4fv', `u_${this.name}.specular`, this.specular);
    }

}

Light.types = {}; // references to subclasses by short name
Light.block = 'lighting'; // shader block name
Light.enabled = true; // lighting can be globally enabled/disabled

// Light subclasses
class AmbientLight extends Light {

    constructor(view, config) {
        super(view, config);
        this.type = 'ambient';
        this.struct_name = 'AmbientLight';
    }

    // Inject struct and calculate function
    static inject() {
        ShaderProgram.addBlock(Light.block, shaderSrc_ambientLight);
    }

    setupProgram (_program) {
        _program.uniform('4fv', `u_${this.name}.ambient`, this.ambient);
    }

}
Light.types['ambient'] = AmbientLight;

class DirectionalLight extends Light {

    constructor(view, config) {
        super(view, config);
        this.type = 'directional';
        this.struct_name = 'DirectionalLight';

        if (config.direction) {
            this.direction = config.direction;
        }
        else {
            // Default directional light maintains full intensity on ground, with basic extrusion shading
            this.direction = [-0.707, 0.707, -0.58]; // [x, y, z]

            if (config.ambient == null) {
                this.ambient = GLSL.expandVec4(0.5);
            }
        }

        this.direction = this.direction.map(parseFloat);
    }

    // Inject struct and calculate function
    static inject() {
        ShaderProgram.addBlock(Light.block, shaderSrc_directionalLight);
    }

    setupProgram (_program) {
        super.setupProgram(_program);
        _program.uniform('3fv', `u_${this.name}.direction`, this.direction);
    }

}
Light.types['directional'] = DirectionalLight;

class PointLight extends Light {

    constructor (view, config) {
        super(view, config);
        this.type = 'point';
        this.struct_name = 'PointLight';

        this.position = config.position || [0, 0, '100px'];
        this.position_eye = []; // position in eyespace
        this.origin = config.origin || 'ground';
        this.attenuation = !isNaN(parseFloat(config.attenuation)) ? parseFloat(config.attenuation) : 0;

        if (config.radius) {
            if (Array.isArray(config.radius) && config.radius.length === 2) {
                this.radius = config.radius;
            }
            else {
                this.radius = [null, config.radius];
            }
        }
        else {
            this.radius = null;
        }
    }

    // Inject struct and calculate function
    static inject () {
        ShaderProgram.addBlock(Light.block, shaderSrc_pointLight);
    }

    // Inject isntance-specific settings
    inject() {
        super.inject();

        ShaderProgram.defines['TANGRAM_POINTLIGHT_ATTENUATION_EXPONENT'] = (this.attenuation !== 0);
        ShaderProgram.defines['TANGRAM_POINTLIGHT_ATTENUATION_INNER_RADIUS'] = (this.radius != null && this.radius[0] != null);
        ShaderProgram.defines['TANGRAM_POINTLIGHT_ATTENUATION_OUTER_RADIUS'] = (this.radius != null);
    }

    update () {
        this.updateEyePosition();
    }

    updateEyePosition () {
        if (this.origin === 'world') {
            // For world origin, format is: [longitude, latitude, meters (default) or pixels w/px units]

            // Move light's world position into camera space
            let [x, y] = Geo.latLngToMeters(this.position);
            this.position_eye[0] = x - this.view.camera.position_meters[0];
            this.position_eye[1] = y - this.view.camera.position_meters[1];

            this.position_eye[2] = StyleParser.convertUnits(this.position[2],
                { zoom: this.view.zoom, meters_per_pixel: Geo.metersPerPixel(this.view.zoom) });
            this.position_eye[2] = this.position_eye[2] - this.view.camera.position_meters[2];
        }
        else if (this.origin === 'ground' || this.origin === 'camera') {
            // For camera or ground origin, format is: [x, y, z] in meters (default) or pixels w/px units

            // Light is in camera space by default
            this.position_eye = StyleParser.convertUnits(this.position,
                { zoom: this.view.zoom, meters_per_pixel: Geo.metersPerPixel(this.view.zoom) });

            if (this.origin === 'ground') {
                // Leave light's xy in camera space, but z needs to be moved relative to ground plane
                this.position_eye[2] = this.position_eye[2] - this.view.camera.position_meters[2];
            }
        }
        this.position_eye[3] = 1;
    }

    setupProgram (_program) {
        super.setupProgram(_program);

        _program.uniform('4fv', `u_${this.name}.position`, this.position_eye);

        if(ShaderProgram.defines['TANGRAM_POINTLIGHT_ATTENUATION_EXPONENT']) {
            _program.uniform('1f', `u_${this.name}.attenuationExponent`, this.attenuation);
        }

        if(ShaderProgram.defines['TANGRAM_POINTLIGHT_ATTENUATION_INNER_RADIUS']) {
            _program.uniform('1f', `u_${this.name}.innerRadius`,
                StyleParser.convertUnits(this.radius[0],
                    { zoom: this.view.zoom, meters_per_pixel: Geo.metersPerPixel(this.view.zoom) }));
        }

        if(ShaderProgram.defines['TANGRAM_POINTLIGHT_ATTENUATION_OUTER_RADIUS']) {
            _program.uniform('1f', `u_${this.name}.outerRadius`,
                StyleParser.convertUnits(this.radius[1],
                    { zoom: this.view.zoom, meters_per_pixel: Geo.metersPerPixel(this.view.zoom) }));
        }
    }
}
Light.types['point'] = PointLight;

class SpotLight extends PointLight {

    constructor (view, config) {
        super(view, config);
        this.type = 'spotlight';
        this.struct_name = 'SpotLight';

        this.direction = (config.direction || [0, 0, -1]).map(parseFloat); // [x, y, z]
        this.exponent = config.exponent ? parseFloat(config.exponent) : 0.2;
        this.angle = config.angle ? parseFloat(config.angle) : 20;
    }

    // Inject struct and calculate function
    static inject () {
        ShaderProgram.addBlock(Light.block, shaderSrc_spotLight);
    }

    setupProgram (_program) {
        super.setupProgram(_program);

        _program.uniform('3fv', `u_${this.name}.direction`, this.direction);
        _program.uniform('1f', `u_${this.name}.spotCosCutoff`, Math.cos(this.angle * 3.14159 / 180));
        _program.uniform('1f', `u_${this.name}.spotExponent`, this.exponent);
    }

}
Light.types['spotlight'] = SpotLight;
<|endoftext|>


<commit_before>const path = require('path');
const jsonServer = require('json-server');
const fs = require('fs-extra');
const faker = require('faker');
const express = require('express');
const { now } = require('./time-now');
const { fe_port, be_port } = require('./ports');
const server = jsonServer.create();
const os = require('os');

faker.seed(12345);

server.all('/*', function(req, res, next) {
  res.setHeader('X-App-Date', now);
  res.setHeader('Access-Control-Expose-Headers', 'X-App-Date');
  next();  // call next() here to move on to next middleware/router
});

const DB = path.join(os.tmpdir(), 'tutor-test-server/backend/db.json');
fs.copySync(path.join(__dirname, './backend/db.json'), DB);

const router = jsonServer.router(DB);
const middlewares = jsonServer.defaults({
  logger: false,
});
const log = require('./log');
server.use(express.json());
server.use(middlewares);
const GET_HANDLERS = {
  setrole: {
    setRole() {  },
    handler(req, resp) { setRole(req.query.role); resp.json({ ok: true }); },
  },
  bootstrap: require('./backend/bootstrap'),
  offerings: require('./backend/offerings'),
  'courses/:courseId/dashboard': require('./backend/dashboard'),
  'courses/:courseId/performance': require('./backend/performance'),
  'courses/:courseId/guide': require('./backend/performance-forecast'),
  'ecosystems/:ecosystemId/readings': require('./backend/readings'),
  'ecosystems/:ecosystemId/exercises/homework_core': require('./backend/exercises'),
  'ecosystems/:ecosystemId/exercises': require('./backend/exercises'),
};

const MULTI_HANDLERS = [
  require('./backend/grading-templates'),
  require('./backend/task-plans'),
  require('./backend/courses'),
  require('./backend/tasks'),
];

// routes that have custom logic
for (let route in GET_HANDLERS) {
  server.get(`/api/${route}`, GET_HANDLERS[route].handler);
}
MULTI_HANDLERS.forEach((handler) => {
  handler.route(server);
});

server.use(jsonServer.rewriter({
  '/api/user/ui_settings': '/ui-settings',
  '/api/log/entry': '/log',
  '/api/log/event/onboarding/:id': '/onboarding',
  '/api/user/tours/:id': '/tours',
  '/api/:key': '/:key',
  '/api/courses/:courseId/plans*': '/previousTaskPlans',
}));
server.use(router);

function setRole(role) {
  for (let route in GET_HANDLERS) {
    GET_HANDLERS[route].setRole(role);
  }
  MULTI_HANDLERS.forEach((handler) => { handler.setRole(role); });
}

server.listen(be_port, () => {
  log('READY', true);
});

process.on('message', (msg) => {
  if (msg.role) {
    setRole(msg.role);
  }
});
<commit_msg>set pracice_exercise route to match new be<commit_after>const path = require('path');
const jsonServer = require('json-server');
const fs = require('fs-extra');
const faker = require('faker');
const express = require('express');
const { now } = require('./time-now');
const { fe_port, be_port } = require('./ports');
const server = jsonServer.create();
const os = require('os');

faker.seed(12345);

server.all('/*', function(req, res, next) {
  res.setHeader('X-App-Date', now);
  res.setHeader('Access-Control-Expose-Headers', 'X-App-Date');
  next();  // call next() here to move on to next middleware/router
});

const DB = path.join(os.tmpdir(), 'tutor-test-server/backend/db.json');
fs.copySync(path.join(__dirname, './backend/db.json'), DB);

const router = jsonServer.router(DB);
const middlewares = jsonServer.defaults({
  logger: false,
});
const log = require('./log');
server.use(express.json());
server.use(middlewares);
const GET_HANDLERS = {
  setrole: {
    setRole() {  },
    handler(req, resp) { setRole(req.query.role); resp.json({ ok: true }); },
  },
  bootstrap: require('./backend/bootstrap'),
  offerings: require('./backend/offerings'),
  'courses/:courseId/dashboard': require('./backend/dashboard'),
  'courses/:courseId/performance': require('./backend/performance'),
  'courses/:courseId/guide': require('./backend/performance-forecast'),
  'ecosystems/:ecosystemId/readings': require('./backend/readings'),
  'ecosystems/:ecosystemId/exercises/homework_core': require('./backend/exercises'),
  'ecosystems/:ecosystemId/practice_exercises': require('./backend/exercises'),
  'ecosystems/:ecosystemId/exercises': require('./backend/exercises'),
};

const MULTI_HANDLERS = [
  require('./backend/grading-templates'),
  require('./backend/task-plans'),
  require('./backend/courses'),
  require('./backend/tasks'),
];

// routes that have custom logic
for (let route in GET_HANDLERS) {
  server.get(`/api/${route}`, GET_HANDLERS[route].handler);
}
MULTI_HANDLERS.forEach((handler) => {
  handler.route(server);
});

server.use(jsonServer.rewriter({
  '/api/user/ui_settings': '/ui-settings',
  '/api/log/entry': '/log',
  '/api/log/event/onboarding/:id': '/onboarding',
  '/api/user/tours/:id': '/tours',
  '/api/:key': '/:key',
  '/api/courses/:courseId/plans*': '/previousTaskPlans',
}));
server.use(router);

function setRole(role) {
  for (let route in GET_HANDLERS) {
    GET_HANDLERS[route].setRole(role);
  }
  MULTI_HANDLERS.forEach((handler) => { handler.setRole(role); });
}

server.listen(be_port, () => {
  log('READY', true);
});

process.on('message', (msg) => {
  if (msg.role) {
    setRole(msg.role);
  }
});
<|endoftext|>