<commit_before>import React, { Component } from 'react';
import { Table, Icon } from 'semantic-ui-react';
import data from './data/food.json';

class List extends Component {
  render() {
    let list = [];

    let categories = data.categories;
    let status = data.status;

    data.foods.forEach((item, index) => {
      if (item.name.toLowerCase().includes(this.props.term) || this.props.term === "") {
        list.push(
          <Table.Row key={ index } >
            <Table.Cell>{ item.name }</Table.Cell>
            <Table.Cell positive={ !item.status } error={ item.status }>
              { item.status ? (
                <Icon name='close' />
              ) : <Icon name='checkmark' /> }
              { status[item.status] }
            </Table.Cell>
            <Table.Cell>{ categories[item.category] }</Table.Cell>
            <Table.Cell warning={ item.hasOwnProperty('note') }>{ item.note }</Table.Cell>
          </Table.Row>
        );
      }
    });

    return (
      <Table celled striped compact unstackable>
        <Table.Header>
          <Table.Row>
            <Table.HeaderCell>Name</Table.HeaderCell>
            <Table.HeaderCell>Edible</Table.HeaderCell>
            <Table.HeaderCell>Category</Table.HeaderCell>
            <Table.HeaderCell>Note</Table.HeaderCell>
          </Table.Row>
        </Table.Header>

        <Table.Body>
          { list }
        </Table.Body>
      </Table>
    );
  }
}

export default List;
<commit_msg>Improve UI<commit_after>import React, { Component } from 'react';
import { Table, Icon } from 'semantic-ui-react';
import data from './data/food.json';

class List extends Component {
  render() {
    let list = [];

    let categories = data.categories;
    let status = data.status;

    data.foods.forEach((item, index) => {
      if (item.name.toLowerCase().includes(this.props.term) || this.props.term === "") {
        list.push(
          <Table.Row positive={ !item.status } negative={ item.status } key={ index } >
            <Table.Cell>
              { !item.status ? (
                <Icon name='checkmark' />
              ) : (
                <Icon name='close' />
              )}
            </Table.Cell>
            <Table.Cell>{ item.name }</Table.Cell>
            <Table.Cell>{ categories[item.category] }</Table.Cell>
            <Table.Cell warning={ item.hasOwnProperty('note') }>{ item.note }</Table.Cell>
          </Table.Row>
        );
      }
    });

    return (
      <Table celled striped compact unstackable>
        <Table.Header>
          <Table.Row>
            <Table.HeaderCell></Table.HeaderCell>
            <Table.HeaderCell>Name</Table.HeaderCell>
            <Table.HeaderCell>Category</Table.HeaderCell>
            <Table.HeaderCell>Note</Table.HeaderCell>
          </Table.Row>
        </Table.Header>

        <Table.Body>
          { list }
        </Table.Body>
      </Table>
    );
  }
}

export default List;
<|endoftext|>


<commit_before>var Twitter = require('twitter');
var Request = require('request');
var fs = require('fs');
var log = require('npmlog');
var Buffer = require('buffer').Buffer;
var HTMLDecoder = new require('html-entities').AllHtmlEntities;

const TWITTER_PROFILE_INTERVAL_MS = 60000;
const TWITTER_CLIENT_INTERVAL_MS = 60000;

/*
  We pass in the full configuration to the constructor since eventually other
  settings will be placed into config (for flags and other forms of auth).
*/
var MatrixTwitter = function (bridge, config) {
  this.app_auth = config.app_auth;
  this.app_twitter = null;
  this.tuser_cache = {};
  this.tclients = {};
  this.sent_tweets = {};
  this.timeline_list = [];
  this.timeline_queue = [];
  this.timeline_period = 0;
  this.timeline_intervalID = null;
  this.msg_queue = [];
  this._bridge = bridge;
  this.tweet_event_cache = {};
};

MatrixTwitter.prototype.start = function(){
  return this.get_bearer_token().then((token) => {
    this.app_auth.bearer_token = token;
    log.info('Twitter','Retrieved token');
    this.app_twitter = new Twitter(this.app_auth);
    setInterval(() => { this._process_head_of_msg_queue(); }, 500);
    this.start_timeline();
  }).catch((error) => {
      log.error('Twitter','Error trying to retrieve bearer token:', error);
      throw "Couldn't get a bearer token for Twitter AS.";
  });
}

MatrixTwitter.prototype._get_bearer_http = function () {
  return new Promise( (resolve,reject) => {
    var key = this.app_auth.consumer_key + ":" + this.app_auth.consumer_secret;
    key = Buffer.from(key, 'ascii').toString('base64');
    var options = {
        url: "https://api.twitter.com/oauth2/token",
        headers: {
            'Authorization': "Basic " + key
        },
        form: "grant_type=client_credentials",
        contentType: "application/x-www-form-urlencoded;charset=UTF-8"
    };
    Request.post(options, function(error, response, body) {
        if (error) {
            reject(error);
        } else if (response.statusCode !== 200){
            reject("Response to bearer token request returned non OK")
            console.log("Body of response:",body);
            console.log("Statuscode of respnse:",response.statusCode);
        } else {
            try {
                var jsonresponse = JSON.parse(body);
                if (jsonresponse.token_type == "bearer") {
                    fs.writeFile("bearer.tok", jsonresponse.access_token, (err) => {
                        if (err) {
                            //This error is unfortunate, but not a failure to retrieve a token so the bridge can run fine.
                            log.error("Twitter","Couldn't write bearer token to file. Reason:",err);
                        }
                    });
                    //Not waiting for callback since it is trivial to get a new token, and can be done async
                    resolve(jsonresponse.bearer_token);
                } else {
                    reject("Request to oauth2/post did not return the correct token type ('bearer'). This is weeeird.");
                    console.log("Body of response:",body);
                }
            } catch (e) {
                reject(e);
            }
        }
    });
  });
}

MatrixTwitter.prototype.get_bearer_token = function () {
  return new Promise((resolve,reject) => {
    fs.readFile('bearer.tok',{encoding:'utf-8'}, (err, content) => {
      if(err){
        log.warn('Twitter',"Token file not found or unreadable. Requesting new token.");
        console.log(err);
        return this._get_bearer_http();
      }
      //Test the token
      var auth = {
        consumer_key: this.app_auth.consumer_key,
        consumer_secret: this.app_auth.consumer_secret,
        bearer_token: content
      };
      this.app_twitter = new Twitter(auth).get('application/rate_limit_status', {}, (error,status,response) => {
        if(response.statusCode == 401){
          log.warn('Twitter',"Authentication with existing token failed. ");
          fs.unlink('bearer.tok', (err) => {
            return this._get_bearer_http();
          });
        }
        else if (response.statusCode == 200){
            log.info('Twitter',"Existing token OK.");
            resolve(content);
        }
        else {
            console.log(error);
            reject("Unexpected response to application/rate_limit_status during bearer token validation. Bailing.");
        }
      });
    });
  });
}

MatrixTwitter.prototype._update_user_timeline = function(profile){
  log.info("[STUB] Update user profile for %s",profile.screen_name);
}

MatrixTwitter.prototype._get_twitter_client = function(sender){
  //Check if we have the account in the cache
  return new Promise( (resolve,reject) =>{
    var id = sender.getId();
    var ts = new Date().getTime();
    var client;
    var creds = sender.get("twitter_oauth");
    if(this.tclients.hasOwnProperty(id)){
      client = this.tclients[id];
      if(ts - client.last_auth < TWITTER_CLIENT_INTERVAL_MS){
        resolve(client);
      }
      client.get("account/verify_credentials",(error,profile) =>{
        if(error){
          delete this.tclients[id];//Invalidate it
          log.info("Twitter","Credentials for " + id + " are no longer valid.");
        }
        client.profile = profile;
        //TODO: Do something with the output ideally like update the users profile.
      });
    }
    if(creds !== undefined && !this.tclients.hasOwnProperty(id)) {
      client = new Twitter({
        consumer_key: this.app_auth.consumer_key,
        consumer_secret: this.app_auth.consumer_secret,
        access_token_key: creds.access_token,
        access_token_secret: creds.access_token_secret
      });
      client.last_auth = ts;
      this.tclients[id] = client;
      client.get("account/verify_credentials",(error,profile) =>{
        if(error){
          delete this.tclients[id];//Invalidate it
          console.log(error);
          log.error("Twitter","We couldn't reauthenticate with the supplied access token for " + id + ". Look into this.");
          reject("Twitter account could not be reauthenticated.");
          //TODO: Possibly find a way to get another key.
        }
        client.profile = profile;
        resolve(client);
      });

    }
    else{
      reject("No twitter account linked.");
    }
  });
}

MatrixTwitter.prototype.send_tweet_to_timeline = function(remote,sender,body){
  var type = remote.get("twitter_type");
  if(type != "timeline"){
    log.error("Twitter","Twitter type was wrong (%s) ",type)
    return;//Where am I meant to send it :(
  }

  var client;

  this._get_twitter_client(sender).then((c) => {
    client = c;
    var timelineID = remote.getId().substr("timeline_".length);
    log.info("Twitter","Trying to tweet " + timelineID);
    return this.get_user_by_id(timelineID)
    //Send away!
  }).then(tuser => {
    var name = "@"+tuser.screen_name;
    if(!body.startsWith(name) && client.profile.screen_name != tuser.screen_name){
      body = (name + " " + body).substr(0,140);
    }
    client.post("statuses/update",{status:body},(error,tweet) => {
      if(error){
        log.error("Twitter","Failed to send tweet.");
        console.log(error);
        return;
      }
      var id = sender.getId();
      log.info("Twitter","Tweet sent from %s!",id);
      if(!this.sent_tweets.hasOwnProperty(id))
      {
        this.sent_tweets[id] = [];
      }
      this.sent_tweets[id].push(tweet.id_str);
    });
  }).catch(err =>{
    log.error("Twiter","Failed to send tweet. %s",err);
  });
}

MatrixTwitter.prototype.get_user_by_id = function(id) {
    var ts = new Date().getTime();
    return new Promise((resolve, reject) => {
        for (var i in this.tuser_cache) {
            var cached = this.tuser_cache[i];
            if (ts - cached.cache_time > TWITTER_PROFILE_INTERVAL_MS) {
                continue;
            }
            if (cached.user != null && cached.user.id_str == id) {
                resolve(cached.user);
            }
        }
        this.app_twitter.get('users/show', {
            user_id: id
        }, (error, user, response) => {
            if (error) {
                log.error('Twitter',"get_user_by_id: GET /users/show returned: ", error);
                reject(error);
            } else {
                this.tuser_cache[user.screen_name] = {
                    cache_time: ts,
                    user: user
                };
                resolve(user);
            }
        });
    });
}

MatrixTwitter.prototype.get_user = function(name) {
    log.info('Twitter',"Looking up @" + name);
    return new Promise((resolve, reject) => {
        var ts = new Date().getTime();
        if (this.tuser_cache[name] != undefined) {
            log.info('Twitter',"Checking cache for @" + name);
            var cached = this.tuser_cache[name];
            if (ts - cached.cache_time < TWITTER_PROFILE_INTERVAL_MS) {
                resolve(cached.user);
            }
        }

        log.info('Twitter',"Checking twitter for @" + name);
        this.app_twitter.get('users/show', {
            screen_name: name
        }, (error, user, response) => {
            if (error) {
                this.tuser_cache[name] = {
                    cache_time: ts,
                    user: null
                };
                reject(error);
            }
            this.tuser_cache[name] = {
                cache_time: ts,
                user: user
            };
            resolve(user);
        });
    });

}

/*
  Add a user's timeline to the timeline processor. Tweets will be automatically send to
  the given room.
*/
MatrixTwitter.prototype.add_timeline = function(userid, localroom, remoteroom) {
    var obj = {
        "user_id": userid,
        "local": localroom,
        "remote": remoteroom
    };
    this.timeline_list.push(obj);
    this.timeline_queue.push(obj);
    log.info('Twitter',"Added Timeline: %s",userid);
}

MTwitter.prototype.remove_timeline = function(userid){
  const tlfind = (tline) => { tline.user_id == userid };
  this.timeline_list  = this.timeline_list.splice(this.timeline_list.findIndex(tlfind),1);
  this.timeline_queue = this.timeline_queue.splice(this.timeline_queue.findIndex(tlfind),1);
}

/*
  This function will fill the content structure for a new matrix message
  for a given tweet.
*/
MatrixTwitter.prototype.tweet_to_matrix_content = function(tweet, type) {
    return {
        "body": new HTMLDecoder().decode(tweet.text),
        "created_at": tweet.created_at,
        "likes": tweet.favorite_count,
        "reblogs": tweet.retweet_count,
        "tweet_id": tweet.id_str,
        "tags": tweet.entities.hashtags,
        "msgtype": type
    }
}

//Runs every 500ms to help not overflow the room.
MatrixTwitter.prototype._process_head_of_msg_queue = function(){
  if(this.msg_queue.length > 0){
    var msg = this.msg_queue.shift();
    var intent = this._bridge.getIntent(msg.userId);
    intent.sendEvent(msg.roomId, msg.type, msg.content).then( (id) => {
      //TODO: Cache this for..reasons.
    });
  }
}

/*
  Process a given tweet (including resolving any parent tweets), and
  submit it to the given room. This function is recursive, limited to the depth
  set.
  roomid - Matrix Room ID of the room that we are processing.
  depth - The maximum depth of the tweet chain (replies to replies) to be traversed.
  Set this to how deep you wish to traverse and it will be decreased when the
  function calls itself.
*/
MatrixTwitter.prototype.process_tweet = function(roomid, tweet, depth) {
    //console.log(tweet);
    depth--;
    if (depth < 0) {
        return;
    }

    var muser = "@twitter_" + tweet.user.id_str + ":" + bridge.opts.domain;
    var intent = this._bridge.getIntent(muser);

    var type = "m.text";
    if (tweet.in_reply_to_status_id_str != null) {
        type = "m.notice"; // A nicer way to show previous tweets
    }

    if (tweet.in_reply_to_status_id_str != null) {
        this.app_twitter.get('statuses/show/' + tweet.in_reply_to_status_id_str, {}, (error, newtweet, response) => {
            if (!error) {
                this.process_tweet(roomid, newtweet, depth);
                return;
            }
            log.error("Twitter","process_tweet: GET /statuses/show returned: %s", error);
        });
    }
    this.msg_queue.push(
      {
        userId:muser,
        roomId:roomid,
        type:"m.room.message",
        content:this.tweet_to_matrix_content(tweet, type)
      }
    );
}

/*
  Internal function to process the timeline queue.
*/
MatrixTwitter.prototype._process_timeline = function(self) {
    if (this.timeline_queue.length < 1) {
        return;
    }

    var tline = this.timeline_queue.shift();
    var id = tline.remote.getId().substr("@twitter_".length);

    var req = {
        user_id: id,
        count: 3
    };
    var since = tline.remote.get("twitter_since");
    if (since != undefined) {
        req.since_id = since;
    }

    this.app_twitter.get('statuses/user_timeline', req, (error, feed, response) => {
        if(error){
          log.error("Twitter","_process_timeline: GET /statuses/user_timeline returned: %s", error);
          return;
        }
        if (feed.length > 0) {
            tline.remote.set("twitter_since", feed[0].id_str, 3);
            feed.reverse().forEach((item) => {
                this.process_tweet(tline.local.roomId, item, 3);
            });
            this._bridge.getRoomStore().setRemoteRoom(tline.remote);
        }
    });
    this.timeline_queue.push(tline);
}

MatrixTwitter.prototype.stop_timeline = function() {
    if (this.timeline_intervalID) {
        clearInterval(this.timeline_intervalID);
        this.timeline_intervalID = null;
    }
}

MatrixTwitter.prototype.start_timeline = function() {
    this.timeline_period = 3050; //Twitter allows 300 calls per 15 minute (We add 50 milliseconds for a little safety).
    this.timeline_intervalID = setInterval(() => {this._process_timeline();}, this.timeline_period);
}

module.exports = {
    MatrixTwitter: MatrixTwitter
}
<commit_msg>Oops. Wrong class name<commit_after>var Twitter = require('twitter');
var Request = require('request');
var fs = require('fs');
var log = require('npmlog');
var Buffer = require('buffer').Buffer;
var HTMLDecoder = new require('html-entities').AllHtmlEntities;

const TWITTER_PROFILE_INTERVAL_MS = 60000;
const TWITTER_CLIENT_INTERVAL_MS = 60000;

/*
  We pass in the full configuration to the constructor since eventually other
  settings will be placed into config (for flags and other forms of auth).
*/
var MatrixTwitter = function (bridge, config) {
  this.app_auth = config.app_auth;
  this.app_twitter = null;
  this.tuser_cache = {};
  this.tclients = {};
  this.sent_tweets = {};
  this.timeline_list = [];
  this.timeline_queue = [];
  this.timeline_period = 0;
  this.timeline_intervalID = null;
  this.msg_queue = [];
  this._bridge = bridge;
  this.tweet_event_cache = {};
};

MatrixTwitter.prototype.start = function(){
  return this.get_bearer_token().then((token) => {
    this.app_auth.bearer_token = token;
    log.info('Twitter','Retrieved token');
    this.app_twitter = new Twitter(this.app_auth);
    setInterval(() => { this._process_head_of_msg_queue(); }, 500);
    this.start_timeline();
  }).catch((error) => {
      log.error('Twitter','Error trying to retrieve bearer token:', error);
      throw "Couldn't get a bearer token for Twitter AS.";
  });
}

MatrixTwitter.prototype._get_bearer_http = function () {
  return new Promise( (resolve,reject) => {
    var key = this.app_auth.consumer_key + ":" + this.app_auth.consumer_secret;
    key = Buffer.from(key, 'ascii').toString('base64');
    var options = {
        url: "https://api.twitter.com/oauth2/token",
        headers: {
            'Authorization': "Basic " + key
        },
        form: "grant_type=client_credentials",
        contentType: "application/x-www-form-urlencoded;charset=UTF-8"
    };
    Request.post(options, function(error, response, body) {
        if (error) {
            reject(error);
        } else if (response.statusCode !== 200){
            reject("Response to bearer token request returned non OK")
            console.log("Body of response:",body);
            console.log("Statuscode of respnse:",response.statusCode);
        } else {
            try {
                var jsonresponse = JSON.parse(body);
                if (jsonresponse.token_type == "bearer") {
                    fs.writeFile("bearer.tok", jsonresponse.access_token, (err) => {
                        if (err) {
                            //This error is unfortunate, but not a failure to retrieve a token so the bridge can run fine.
                            log.error("Twitter","Couldn't write bearer token to file. Reason:",err);
                        }
                    });
                    //Not waiting for callback since it is trivial to get a new token, and can be done async
                    resolve(jsonresponse.bearer_token);
                } else {
                    reject("Request to oauth2/post did not return the correct token type ('bearer'). This is weeeird.");
                    console.log("Body of response:",body);
                }
            } catch (e) {
                reject(e);
            }
        }
    });
  });
}

MatrixTwitter.prototype.get_bearer_token = function () {
  return new Promise((resolve,reject) => {
    fs.readFile('bearer.tok',{encoding:'utf-8'}, (err, content) => {
      if(err){
        log.warn('Twitter',"Token file not found or unreadable. Requesting new token.");
        console.log(err);
        return this._get_bearer_http();
      }
      //Test the token
      var auth = {
        consumer_key: this.app_auth.consumer_key,
        consumer_secret: this.app_auth.consumer_secret,
        bearer_token: content
      };
      this.app_twitter = new Twitter(auth).get('application/rate_limit_status', {}, (error,status,response) => {
        if(response.statusCode == 401){
          log.warn('Twitter',"Authentication with existing token failed. ");
          fs.unlink('bearer.tok', (err) => {
            return this._get_bearer_http();
          });
        }
        else if (response.statusCode == 200){
            log.info('Twitter',"Existing token OK.");
            resolve(content);
        }
        else {
            console.log(error);
            reject("Unexpected response to application/rate_limit_status during bearer token validation. Bailing.");
        }
      });
    });
  });
}

MatrixTwitter.prototype._update_user_timeline = function(profile){
  log.info("[STUB] Update user profile for %s",profile.screen_name);
}

MatrixTwitter.prototype._get_twitter_client = function(sender){
  //Check if we have the account in the cache
  return new Promise( (resolve,reject) =>{
    var id = sender.getId();
    var ts = new Date().getTime();
    var client;
    var creds = sender.get("twitter_oauth");
    if(this.tclients.hasOwnProperty(id)){
      client = this.tclients[id];
      if(ts - client.last_auth < TWITTER_CLIENT_INTERVAL_MS){
        resolve(client);
      }
      client.get("account/verify_credentials",(error,profile) =>{
        if(error){
          delete this.tclients[id];//Invalidate it
          log.info("Twitter","Credentials for " + id + " are no longer valid.");
        }
        client.profile = profile;
        //TODO: Do something with the output ideally like update the users profile.
      });
    }
    if(creds !== undefined && !this.tclients.hasOwnProperty(id)) {
      client = new Twitter({
        consumer_key: this.app_auth.consumer_key,
        consumer_secret: this.app_auth.consumer_secret,
        access_token_key: creds.access_token,
        access_token_secret: creds.access_token_secret
      });
      client.last_auth = ts;
      this.tclients[id] = client;
      client.get("account/verify_credentials",(error,profile) =>{
        if(error){
          delete this.tclients[id];//Invalidate it
          console.log(error);
          log.error("Twitter","We couldn't reauthenticate with the supplied access token for " + id + ". Look into this.");
          reject("Twitter account could not be reauthenticated.");
          //TODO: Possibly find a way to get another key.
        }
        client.profile = profile;
        resolve(client);
      });

    }
    else{
      reject("No twitter account linked.");
    }
  });
}

MatrixTwitter.prototype.send_tweet_to_timeline = function(remote,sender,body){
  var type = remote.get("twitter_type");
  if(type != "timeline"){
    log.error("Twitter","Twitter type was wrong (%s) ",type)
    return;//Where am I meant to send it :(
  }

  var client;

  this._get_twitter_client(sender).then((c) => {
    client = c;
    var timelineID = remote.getId().substr("timeline_".length);
    log.info("Twitter","Trying to tweet " + timelineID);
    return this.get_user_by_id(timelineID)
    //Send away!
  }).then(tuser => {
    var name = "@"+tuser.screen_name;
    if(!body.startsWith(name) && client.profile.screen_name != tuser.screen_name){
      body = (name + " " + body).substr(0,140);
    }
    client.post("statuses/update",{status:body},(error,tweet) => {
      if(error){
        log.error("Twitter","Failed to send tweet.");
        console.log(error);
        return;
      }
      var id = sender.getId();
      log.info("Twitter","Tweet sent from %s!",id);
      if(!this.sent_tweets.hasOwnProperty(id))
      {
        this.sent_tweets[id] = [];
      }
      this.sent_tweets[id].push(tweet.id_str);
    });
  }).catch(err =>{
    log.error("Twiter","Failed to send tweet. %s",err);
  });
}

MatrixTwitter.prototype.get_user_by_id = function(id) {
    var ts = new Date().getTime();
    return new Promise((resolve, reject) => {
        for (var i in this.tuser_cache) {
            var cached = this.tuser_cache[i];
            if (ts - cached.cache_time > TWITTER_PROFILE_INTERVAL_MS) {
                continue;
            }
            if (cached.user != null && cached.user.id_str == id) {
                resolve(cached.user);
            }
        }
        this.app_twitter.get('users/show', {
            user_id: id
        }, (error, user, response) => {
            if (error) {
                log.error('Twitter',"get_user_by_id: GET /users/show returned: ", error);
                reject(error);
            } else {
                this.tuser_cache[user.screen_name] = {
                    cache_time: ts,
                    user: user
                };
                resolve(user);
            }
        });
    });
}

MatrixTwitter.prototype.get_user = function(name) {
    log.info('Twitter',"Looking up @" + name);
    return new Promise((resolve, reject) => {
        var ts = new Date().getTime();
        if (this.tuser_cache[name] != undefined) {
            log.info('Twitter',"Checking cache for @" + name);
            var cached = this.tuser_cache[name];
            if (ts - cached.cache_time < TWITTER_PROFILE_INTERVAL_MS) {
                resolve(cached.user);
            }
        }

        log.info('Twitter',"Checking twitter for @" + name);
        this.app_twitter.get('users/show', {
            screen_name: name
        }, (error, user, response) => {
            if (error) {
                this.tuser_cache[name] = {
                    cache_time: ts,
                    user: null
                };
                reject(error);
            }
            this.tuser_cache[name] = {
                cache_time: ts,
                user: user
            };
            resolve(user);
        });
    });

}

/*
  Add a user's timeline to the timeline processor. Tweets will be automatically send to
  the given room.
*/
MatrixTwitter.prototype.add_timeline = function(userid, localroom, remoteroom) {
    var obj = {
        "user_id": userid,
        "local": localroom,
        "remote": remoteroom
    };
    this.timeline_list.push(obj);
    this.timeline_queue.push(obj);
    log.info('Twitter',"Added Timeline: %s",userid);
}

MatrixTwitter.prototype.remove_timeline = function(userid){
  const tlfind = (tline) => { tline.user_id == userid };
  this.timeline_list  = this.timeline_list.splice(this.timeline_list.findIndex(tlfind),1);
  this.timeline_queue = this.timeline_queue.splice(this.timeline_queue.findIndex(tlfind),1);
}

/*
  This function will fill the content structure for a new matrix message
  for a given tweet.
*/
MatrixTwitter.prototype.tweet_to_matrix_content = function(tweet, type) {
    return {
        "body": new HTMLDecoder().decode(tweet.text),
        "created_at": tweet.created_at,
        "likes": tweet.favorite_count,
        "reblogs": tweet.retweet_count,
        "tweet_id": tweet.id_str,
        "tags": tweet.entities.hashtags,
        "msgtype": type
    }
}

//Runs every 500ms to help not overflow the room.
MatrixTwitter.prototype._process_head_of_msg_queue = function(){
  if(this.msg_queue.length > 0){
    var msg = this.msg_queue.shift();
    var intent = this._bridge.getIntent(msg.userId);
    intent.sendEvent(msg.roomId, msg.type, msg.content).then( (id) => {
      //TODO: Cache this for..reasons.
    });
  }
}

/*
  Process a given tweet (including resolving any parent tweets), and
  submit it to the given room. This function is recursive, limited to the depth
  set.
  roomid - Matrix Room ID of the room that we are processing.
  depth - The maximum depth of the tweet chain (replies to replies) to be traversed.
  Set this to how deep you wish to traverse and it will be decreased when the
  function calls itself.
*/
MatrixTwitter.prototype.process_tweet = function(roomid, tweet, depth) {
    //console.log(tweet);
    depth--;
    if (depth < 0) {
        return;
    }

    var muser = "@twitter_" + tweet.user.id_str + ":" + bridge.opts.domain;
    var intent = this._bridge.getIntent(muser);

    var type = "m.text";
    if (tweet.in_reply_to_status_id_str != null) {
        type = "m.notice"; // A nicer way to show previous tweets
    }

    if (tweet.in_reply_to_status_id_str != null) {
        this.app_twitter.get('statuses/show/' + tweet.in_reply_to_status_id_str, {}, (error, newtweet, response) => {
            if (!error) {
                this.process_tweet(roomid, newtweet, depth);
                return;
            }
            log.error("Twitter","process_tweet: GET /statuses/show returned: %s", error);
        });
    }
    this.msg_queue.push(
      {
        userId:muser,
        roomId:roomid,
        type:"m.room.message",
        content:this.tweet_to_matrix_content(tweet, type)
      }
    );
}

/*
  Internal function to process the timeline queue.
*/
MatrixTwitter.prototype._process_timeline = function(self) {
    if (this.timeline_queue.length < 1) {
        return;
    }

    var tline = this.timeline_queue.shift();
    var id = tline.remote.getId().substr("@twitter_".length);

    var req = {
        user_id: id,
        count: 3
    };
    var since = tline.remote.get("twitter_since");
    if (since != undefined) {
        req.since_id = since;
    }

    this.app_twitter.get('statuses/user_timeline', req, (error, feed, response) => {
        if(error){
          log.error("Twitter","_process_timeline: GET /statuses/user_timeline returned: %s", error);
          return;
        }
        if (feed.length > 0) {
            tline.remote.set("twitter_since", feed[0].id_str, 3);
            feed.reverse().forEach((item) => {
                this.process_tweet(tline.local.roomId, item, 3);
            });
            this._bridge.getRoomStore().setRemoteRoom(tline.remote);
        }
    });
    this.timeline_queue.push(tline);
}

MatrixTwitter.prototype.stop_timeline = function() {
    if (this.timeline_intervalID) {
        clearInterval(this.timeline_intervalID);
        this.timeline_intervalID = null;
    }
}

MatrixTwitter.prototype.start_timeline = function() {
    this.timeline_period = 3050; //Twitter allows 300 calls per 15 minute (We add 50 milliseconds for a little safety).
    this.timeline_intervalID = setInterval(() => {this._process_timeline();}, this.timeline_period);
}

module.exports = {
    MatrixTwitter: MatrixTwitter
}
<|endoftext|>


<commit_before>
const THREE = require('three')
const CANNON = require('cannon')
// const PointerLockControls = require('./PointerLockControls');
import store from '../store';

import { PointerLockControls } from './PointerLockControls';

var sphereShape, sphereBody, world, physicsMaterial, walls=[], balls=[], ballMeshes=[], boxes=[], boxMeshes=[], players=[], playerMeshes=[];
var camera, scene, renderer, light;
var geometry, material, mesh;
var controls,time = Date.now();

export function initCannon() {
//     // Setup our world
    world = new CANNON.World();
    world.quatNormalizeSkip = 0;
    world.quatNormalizeFast = false;
    var solver = new CANNON.GSSolver();
    world.defaultContactMaterial.contactEquationStiffness = 1e9;
    world.defaultContactMaterial.contactEquationRelaxation = 4;
    solver.iterations = 7;
    solver.tolerance = 0.1;
    var split = true;
    if(split)
        world.solver = new CANNON.SplitSolver(solver);
    else
        world.solver = solver;
    world.gravity.set(0,-20,0);
    world.broadphase = new CANNON.NaiveBroadphase();

//     // Create a slippery material (friction coefficient = 0.0)
    physicsMaterial = new CANNON.Material("slipperyMaterial");
    var physicsContactMaterial = new CANNON.ContactMaterial(physicsMaterial,
                                                            physicsMaterial,
                                                            0.0, // friction coefficient
                                                            0.3  // restitution
                                                            );
//     // We must add the contact materials to the world
    world.addContactMaterial(physicsContactMaterial);

//     // Create a sphere
    var mass = 5, radius = 1.3;
    sphereShape = new CANNON.Sphere(radius);
    sphereBody = new CANNON.Body({ mass: mass });
    sphereBody.addShape(sphereShape);
    sphereBody.position.set(0,5,0);
    sphereBody.linearDamping = 0.9;
    world.addBody(sphereBody);

    // Create a plane
    var groundShape = new CANNON.Plane();
    var groundBody = new CANNON.Body({ mass: 0 });
    groundBody.addShape(groundShape);
    groundBody.quaternion.setFromAxisAngle(new CANNON.Vec3(1,0,0),-Math.PI/2);
    world.addBody(groundBody);
}

  // SHOOTING BOMBS HERE

   // cannon sphere(radius)
var ballShape = new CANNON.Sphere(1.5);

// three sphere(radius, numFaces per xyz) higher num means rounder sphere
// 32 should be enough for spheres
var ballGeometry = new THREE.SphereGeometry(ballShape.radius, 32, 32);

// generates a vector with no units if you want units you input
// Vector3(x,y,z)
var shootDirection = new THREE.Vector3();

// speed of ball (m/s maybe?)
var shootVelo = 15;

export function init() {
    camera = new THREE.PerspectiveCamera( 55, window.innerWidth / window.innerHeight, 0.1, 1000 );
    camera.position.set(0, 3, 0)
    scene = new THREE.Scene();
    scene.fog = new THREE.Fog( 0x000000, 0, 500 );
    var ambient = new THREE.AmbientLight( 0x111111 );
    scene.add( ambient );
    light = new THREE.SpotLight( 0xffffff );
    light.position.set( 10, 30, 20 );
    light.target.position.set( 0, 0, 0 );
    if(true){
        light.castShadow = false;
        light.shadowCameraNear = 20;
        light.shadowCameraFar = 50;//camera.far;
        light.shadowCameraFov = 40;
        light.shadowMapBias = 0.1;
        // light.shadowMapDarkness = 0.7;
        light.shadowMapWidth = 2*512;
        // light.shadowMapHeight = 2*512;
        // light.shadowCameraVisible = true;
    }
    scene.add( light );

    // this attaches bomb to the player (maybe)
    // look at PointerLockControls function
    // sphereBody.position = (0,5,0) so the sphere should be 5+ in y direction above camera

    controls = new PointerLockControls( camera , sphereBody );
    scene.add( controls.getObject() );

    // floor
    geometry = new THREE.PlaneGeometry( 125, 125, 50, 50 );
    geometry.applyMatrix( new THREE.Matrix4().makeRotationX( - Math.PI / 2 ) );
    material = new THREE.MeshLambertMaterial( { color: 0xdddddd } );
    mesh = new THREE.Mesh( geometry, material );
    mesh.castShadow = true;
    mesh.receiveShadow = true;
    scene.add( mesh );

    renderer = new THREE.WebGLRenderer();
    renderer.shadowMapEnabled = true;
    renderer.shadowMapSoft = true;
    renderer.setSize( window.innerWidth, window.innerHeight );
    renderer.setClearColor( scene.fog.color, 1 );
    document.body.appendChild( renderer.domElement );
    window.addEventListener( 'resize', onWindowResize, false );

    createMap();

    // add event listen to actually shoot
  if (controls) {
    window.addEventListener("click",function(e){
      if(controls.enabled==true){
          // because sphereBody position is dependent on camera position
          var x = sphereBody.position.x;
          var y = sphereBody.position.y;
          var z = sphereBody.position.z;

          // create the ball
          var ballBody = new CANNON.Body({ mass: 1 });
          ballBody.addShape(ballShape);
          var ballMesh = new THREE.Mesh( ballGeometry, material );
          world.addBody(ballBody);

          // add it to the scene
          scene.add(ballMesh);

          // shadow affects
          ballMesh.castShadow = true;
          ballMesh.receiveShadow = true;

          // push it into our global balls array

          balls.push(ballBody);

          // push ball meshes
          ballMeshes.push(ballMesh);

          // get its direction using getShootDir function
          // returns shootDirection altered with correct data
          getShootDir(shootDirection);

          // give it a velocity
          // shootVelo is global defined as 15
          ballBody.velocity.set(  shootDirection.x * shootVelo,
                                  shootDirection.y * shootVelo,
                                  shootDirection.z * shootVelo);

          // Move the ball outside the player sphere
          // not sure about this shit here
          // x,y,z adjusted so it's actually updating the position of the sphere
          x += shootDirection.x * (sphereShape.radius*1.02 + ballShape.radius);
          y += shootDirection.y * (sphereShape.radius*1.02 + ballShape.radius);
          z += shootDirection.z * (sphereShape.radius*1.02 + ballShape.radius);
          ballBody.position.set(x,y,z);
          ballMesh.position.set(x,y,z);
      }
    });
  }
}

export function createMap() {
  // Add boxes
    var halfExtents = new CANNON.Vec3(2,2,2);
    var boxShape = new CANNON.Box(halfExtents);
    var boxGeometry = new THREE.BoxGeometry(halfExtents.x*1.9,halfExtents.y*1.9,halfExtents.z*1.9);

    var wallShape = new CANNON.Box(halfExtents);
    var wallGeometry = new THREE.BoxGeometry(halfExtents.x*2,halfExtents.y*3.5,halfExtents.z*2);

    // // Map 1 = Wall, 2 = StaticBox
    let map = [ // 1  2  3  4  5  6  7  8  9  10 11 12
               [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], // 0
               [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], // 1
               [1, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 1], // 2
               [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], // 3
               [1, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 1], // 4
               [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], // 5
               [1, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 1], // 6
               [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], // 7
               [1, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 1], // 8
               [1, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 1],
               [1, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 1], // 8
               [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
               [1, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 1], // 8
               [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
               [1, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 1], // 8
               [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
               [1, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 1], // 8
               [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], // 9
               [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], // 10
               ]

  let mapW = map.length, mapH = map[0].length;

  for (let j = 0; j < mapW; j++) {
    for (let k = 0; k < mapH; k++) {

      let x = (j + mapW) * 4 - 100;
      let y = 2
      let z = -(k + mapW) * 4 + 100;

      if (map[j][k] === 2) { // create box

        var boxBody = new CANNON.Body({ mass: 0 }); //
        boxBody.addShape(boxShape) //
        var boxMesh = new THREE.Mesh( boxGeometry, material );
        world.addBody(boxBody); //
        scene.add(boxMesh);
        boxBody.position.set(x,y,z);
        boxMesh.position.set(x,y,z);
        boxMesh.castShadow = true;
        boxMesh.receiveShadow = true;
        boxes.push(boxBody);
        boxMeshes.push(boxMesh);

      } else if (map[j][k] === 1){ // create wall

        var wallBody = new CANNON.Body({ mass: 0 }); //
        wallBody.addShape(wallShape); //
        var wallMesh = new THREE.Mesh( wallGeometry, material );
        world.addBody(wallBody);//
        scene.add(wallMesh);
        wallBody.position.set(x,y,z); //
        wallMesh.position.set(x,y,z);
        wallMesh.castShadow = true;
        wallMesh.receiveShadow = true;
        boxes.push(wallBody);
        boxMeshes.push(wallMesh);

      } else if (map[j][k] === 3){ // create wall

        var boxBody = new CANNON.Body({ mass: 1 }); //
        boxBody.addShape(boxShape) //
        let color = new THREE.MeshLambertMaterial( { color: 0x8B4513 } );
        var boxMesh = new THREE.Mesh( boxGeometry, color );
        world.addBody(boxBody); //
        scene.add(boxMesh);
        boxBody.position.set(x,y,z);
        boxMesh.position.set(x,y,z);
        boxMesh.castShadow = true;
        boxMesh.receiveShadow = true;
        boxes.push(boxBody);
        boxMeshes.push(boxMesh);
      }

    }
  }
}

export function onWindowResize() {
    camera.aspect = window.innerWidth / window.innerHeight;
    camera.updateProjectionMatrix();
    renderer.setSize( window.innerWidth, window.innerHeight );
}

var dt = 1/60; // change in time for walking

  // animate the walking and the box positions movements

export function animate() {

    setTimeout(() => {
      if(socket) {
        socket.emit('update_players_position', {
            position: {
              x: sphereBody.position.x,
              y: sphereBody.position.y,
              z: sphereBody.position.z
            },
            id: socket.id
        });
      }
      requestAnimationFrame( animate );
    }, 1000 / 45)
    if(controls.enabled){
        world.step(dt); // function that allows walking from CANNON

        // Update ball positions
        // the bombs in our game

        // UPDATES PLAYERS HERE

        let state = store.getState();
        let playerIds = Object.keys(state.players.otherPlayers)

        if (playerIds.length > players.length) {
          var halfExtents = new CANNON.Vec3(2,2,2);
          var boxShape = new CANNON.Box(halfExtents);
          var boxGeometry = new THREE.BoxGeometry(halfExtents.x*1.9,halfExtents.y*1.9,halfExtents.z*1.9);

          var playerBox = new CANNON.Body({ mass: 1 }); //
          playerBox.addShape(boxShape) //
          let color = new THREE.MeshLambertMaterial( { color: 0x8B4513 } );
          var playerMesh = new THREE.Mesh( boxGeometry, color );
          world.addBody(playerBox); //
          scene.add(playerMesh);
          let pos = state.players.otherPlayers[playerIds[playerIds.length - 1]];

          let {x, y, z} = pos;

          playerBox.position.set(x, y + 5, z);
          playerMesh.position.set(x, y + 5, z);
          playerMesh.castShadow = true;
          playerMesh.receiveShadow = true;
          players.push(playerBox);
          playerMeshes.push(playerMesh);
        }

        for(let i=0; i < players.length; i++){

            playerMeshes[i].position.copy(state.players.otherPlayers[playerIds[i]]);
            playerMeshes[i].quaternion.copy(players[i].quaternion);
        }

        for(let i=0; i<balls.length; i++){
            ballMeshes[i].position.copy(balls[i].position);
            ballMeshes[i].quaternion.copy(balls[i].quaternion);
        }
        // // Update box positions
        for(let i=0; i<boxes.length; i++){
            boxMeshes[i].position.copy(boxes[i].position);
            boxMeshes[i].quaternion.copy(boxes[i].quaternion);
        }
    }

    controls.update( Date.now() - time );
    renderer.render( scene, camera );
    time = Date.now();
}

  // this is outdated should use raycaster instead since it gives more info anyway
  // also projector is moved.
  // to adjust to use raycaster we need to adjust yawObject and pitch object

  TODO: // HERE
var projector = new THREE.Projector();

// get shoot direction might need to be adjusted to use ray caster instead
const getShootDir = function(targetVec){
    var vector = targetVec;
    targetVec.set(0,0,1);
    projector.unprojectVector(vector, camera);
    var ray = new THREE.Ray(sphereBody.position, vector.sub(sphereBody.position).normalize() );
    targetVec.copy(ray.direction);
}

export { scene, camera, renderer, controls, light, getShootDir }
<commit_msg>color changed<commit_after>
const THREE = require('three')
const CANNON = require('cannon')
// const PointerLockControls = require('./PointerLockControls');
import store from '../store';

import { PointerLockControls } from './PointerLockControls';

var sphereShape, sphereBody, world, physicsMaterial, walls=[], balls=[], ballMeshes=[], boxes=[], boxMeshes=[], players=[], playerMeshes=[];
var camera, scene, renderer, light;
var geometry, material, mesh;
var controls,time = Date.now();

export function initCannon() {
//     // Setup our world
    world = new CANNON.World();
    world.quatNormalizeSkip = 0;
    world.quatNormalizeFast = false;
    var solver = new CANNON.GSSolver();
    world.defaultContactMaterial.contactEquationStiffness = 1e9;
    world.defaultContactMaterial.contactEquationRelaxation = 4;
    solver.iterations = 7;
    solver.tolerance = 0.1;
    var split = true;
    if(split)
        world.solver = new CANNON.SplitSolver(solver);
    else
        world.solver = solver;
    world.gravity.set(0,-20,0);
    world.broadphase = new CANNON.NaiveBroadphase();

//     // Create a slippery material (friction coefficient = 0.0)
    physicsMaterial = new CANNON.Material("slipperyMaterial");
    var physicsContactMaterial = new CANNON.ContactMaterial(physicsMaterial,
                                                            physicsMaterial,
                                                            0.0, // friction coefficient
                                                            0.3  // restitution
                                                            );
//     // We must add the contact materials to the world
    world.addContactMaterial(physicsContactMaterial);

//     // Create a sphere
    var mass = 5, radius = 1.3;
    sphereShape = new CANNON.Sphere(radius);
    sphereBody = new CANNON.Body({ mass: mass });
    sphereBody.addShape(sphereShape);
    sphereBody.position.set(0,5,0);
    sphereBody.linearDamping = 0.9;
    world.addBody(sphereBody);

    // Create a plane
    var groundShape = new CANNON.Plane();
    var groundBody = new CANNON.Body({ mass: 0 });
    groundBody.addShape(groundShape);
    groundBody.quaternion.setFromAxisAngle(new CANNON.Vec3(1,0,0),-Math.PI/2);
    world.addBody(groundBody);
}

  // SHOOTING BOMBS HERE

   // cannon sphere(radius)
var ballShape = new CANNON.Sphere(1.5);

// three sphere(radius, numFaces per xyz) higher num means rounder sphere
// 32 should be enough for spheres
var ballGeometry = new THREE.SphereGeometry(ballShape.radius, 32, 32);

// generates a vector with no units if you want units you input
// Vector3(x,y,z)
var shootDirection = new THREE.Vector3();

// speed of ball (m/s maybe?)
var shootVelo = 15;

export function init() {
    camera = new THREE.PerspectiveCamera( 55, window.innerWidth / window.innerHeight, 0.1, 1000 );
    camera.position.set(0, 3, 0)
    scene = new THREE.Scene();
    scene.fog = new THREE.Fog( 0x000000, 0, 500 );
    var ambient = new THREE.AmbientLight( 0xffffff );
    scene.add( ambient );
    light = new THREE.SpotLight( 0xffffff );
    light.position.set( 10, 30, 20 );
    light.target.position.set( 0, 0, 0 );
    // if(true){
    //     light.castShadow = false;
    //     light.shadowCameraNear = 20;
    //     light.shadowCameraFar = 50;//camera.far;
    //     light.shadowCameraFov = 40;
    //     light.shadowMapBias = 0.1;
    //     light.shadowMapDarkness = 0.7;
    //     light.shadowMapWidth = 2*512;
    //     light.shadowMapHeight = 2*512;
    //     light.shadowCameraVisible = true;
    // }
    scene.add( light );

    // this attaches bomb to the player (maybe)
    // look at PointerLockControls function
    // sphereBody.position = (0,5,0) so the sphere should be 5+ in y direction above camera

    controls = new PointerLockControls( camera , sphereBody );
    scene.add( controls.getObject() );

    // floor
    geometry = new THREE.PlaneBufferGeometry( 125, 125, 50, 50 );
    geometry.applyMatrix( new THREE.Matrix4().makeRotationX( - Math.PI / 2 ) );
    material = new THREE.MeshLambertMaterial( { color: 0x3f7cba } );
    mesh = new THREE.Mesh( geometry, material );
    mesh.castShadow = true;
    mesh.receiveShadow = true;
    scene.add( mesh );

    renderer = new THREE.WebGLRenderer();
    // renderer.shadowMapEnabled = true;
    // renderer.shadowMapSoft = true;
    renderer.setSize( window.innerWidth, window.innerHeight );
    renderer.setClearColor( scene.fog.color, 1 );
    document.body.appendChild( renderer.domElement );
    window.addEventListener( 'resize', onWindowResize, false );

    createMap();

    // add event listen to actually shoot
  if (controls) {
    window.addEventListener("click",function(e){
      if(controls.enabled==true){
          // because sphereBody position is dependent on camera position
          var x = sphereBody.position.x;
          var y = sphereBody.position.y;
          var z = sphereBody.position.z;

          // create the ball
          var ballBody = new CANNON.Body({ mass: 1 });
          ballBody.addShape(ballShape);
          var ballMesh = new THREE.Mesh( ballGeometry, material );
          world.addBody(ballBody);

          // add it to the scene
          scene.add(ballMesh);

          // shadow affects
          ballMesh.castShadow = true;
          ballMesh.receiveShadow = true;

          // push it into our global balls array

          balls.push(ballBody);

          // push ball meshes
          ballMeshes.push(ballMesh);

          // get its direction using getShootDir function
          // returns shootDirection altered with correct data
          getShootDir(shootDirection);

          // give it a velocity
          // shootVelo is global defined as 15
          ballBody.velocity.set(  shootDirection.x * shootVelo,
                                  shootDirection.y * shootVelo,
                                  shootDirection.z * shootVelo);

          // Move the ball outside the player sphere
          // not sure about this shit here
          // x,y,z adjusted so it's actually updating the position of the sphere
          x += shootDirection.x * (sphereShape.radius*1.02 + ballShape.radius);
          y += shootDirection.y * (sphereShape.radius*1.02 + ballShape.radius);
          z += shootDirection.z * (sphereShape.radius*1.02 + ballShape.radius);
          ballBody.position.set(x,y,z);
          ballMesh.position.set(x,y,z);
      }
    });
  }
}

export function createMap() {
  // Add boxes
    var halfExtents = new CANNON.Vec3(2,2,2);
    var boxShape = new CANNON.Box(halfExtents);
    var boxGeometry = new THREE.BoxGeometry(halfExtents.x*1.9,halfExtents.y*1.9,halfExtents.z*1.9);

    var wallShape = new CANNON.Box(halfExtents);
    var wallGeometry = new THREE.BoxGeometry(halfExtents.x*2,halfExtents.y*3.5,halfExtents.z*2);

    // // Map 1 = Wall, 2 = StaticBox
    let map = [ // 1  2  3  4  5  6  7  8  9  10 11 12
               [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], // 0
               [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], // 1
               [1, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 1], // 2
               [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], // 3
               [1, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 1], // 4
               [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], // 5
               [1, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 1], // 6
               [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], // 7
               [1, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 1], // 8
               [1, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 1], // 9
               [1, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 1], // 10
               [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], // 11
               [1, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 1], // 12
               [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], // 13
               [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], // 14
               ]

  let mapW = map.length, mapH = map[0].length;

  for (let j = 0; j < mapW; j++) {
    for (let k = 0; k < mapH; k++) {

      let x = (j + mapW) * 4 - 100;
      let y = 2
      let z = -(k + mapW) * 4 + 100;

      if (map[j][k] === 2) { // create box

        var boxBody = new CANNON.Body({ mass: 0 }); //
        boxBody.addShape(boxShape) //
        var boxMesh = new THREE.Mesh( boxGeometry, material );
        world.addBody(boxBody); //
        scene.add(boxMesh);
        boxBody.position.set(x,y,z);
        boxMesh.position.set(x,y,z);
        boxMesh.castShadow = true;
        boxMesh.receiveShadow = true;
        boxes.push(boxBody);
        boxMeshes.push(boxMesh);

      } else if (map[j][k] === 1){ // create wall

        var wallBody = new CANNON.Body({ mass: 0 }); //
        wallBody.addShape(wallShape); //
        var wallMesh = new THREE.Mesh( wallGeometry, material );
        world.addBody(wallBody);//
        scene.add(wallMesh);
        wallBody.position.set(x,y,z); //
        wallMesh.position.set(x,y,z);
        wallMesh.castShadow = true;
        wallMesh.receiveShadow = true;
        boxes.push(wallBody);
        boxMeshes.push(wallMesh);

      } else if (map[j][k] === 3){ // create wall

        var boxBody = new CANNON.Body({ mass: 1 }); //
        boxBody.addShape(boxShape) //
        let color = new THREE.MeshLambertMaterial( { color: 0x8B4513 } );
        var boxMesh = new THREE.Mesh( boxGeometry, color );
        world.addBody(boxBody); //
        scene.add(boxMesh);
        boxBody.position.set(x,y,z);
        boxMesh.position.set(x,y,z);
        boxMesh.castShadow = true;
        boxMesh.receiveShadow = true;
        boxes.push(boxBody);
        boxMeshes.push(boxMesh);
      }

    }
  }
}

export function onWindowResize() {
    camera.aspect = window.innerWidth / window.innerHeight;
    camera.updateProjectionMatrix();
    renderer.setSize( window.innerWidth, window.innerHeight );
}

var dt = 1/60; // change in time for walking

  // animate the walking and the box positions movements

export function animate() {

    setTimeout(() => {
      if(socket) {
        socket.emit('update_players_position', {
            position: {
              x: sphereBody.position.x,
              y: sphereBody.position.y,
              z: sphereBody.position.z
            },
            id: socket.id
        });
      }
      requestAnimationFrame( animate );
    }, 1000 / 45)
    if(controls.enabled){
        world.step(dt); // function that allows walking from CANNON

        // Update ball positions
        // the bombs in our game

        // UPDATES PLAYERS HERE

        let state = store.getState();
        let playerIds = Object.keys(state.players.otherPlayers)

        if (playerIds.length > players.length) {
          var halfExtents = new CANNON.Vec3(2,2,2);
          var boxShape = new CANNON.Box(halfExtents);
          var boxGeometry = new THREE.BoxGeometry(halfExtents.x*1.9,halfExtents.y*1.9,halfExtents.z*1.9);

          var playerBox = new CANNON.Body({ mass: 1 }); //
          playerBox.addShape(boxShape) //
          let color = new THREE.MeshLambertMaterial( { color: 0x8B4513 } );
          var playerMesh = new THREE.Mesh( boxGeometry, color );
          world.addBody(playerBox); //
          scene.add(playerMesh);
          let pos = state.players.otherPlayers[playerIds[playerIds.length - 1]];

          let {x, y, z} = pos;

          playerBox.position.set(x, y + 5, z);
          playerMesh.position.set(x, y + 5, z);
          playerMesh.castShadow = true;
          playerMesh.receiveShadow = true;
          players.push(playerBox);
          playerMeshes.push(playerMesh);
        }

        for(let i=0; i < players.length; i++){

            playerMeshes[i].position.copy(state.players.otherPlayers[playerIds[i]]);
            playerMeshes[i].quaternion.copy(players[i].quaternion);
        }

        for(let i=0; i<balls.length; i++){
            ballMeshes[i].position.copy(balls[i].position);
            ballMeshes[i].quaternion.copy(balls[i].quaternion);
        }
        // // Update box positions
        for(let i=0; i<boxes.length; i++){
            boxMeshes[i].position.copy(boxes[i].position);
            boxMeshes[i].quaternion.copy(boxes[i].quaternion);
        }
    }

    controls.update( Date.now() - time );
    renderer.render( scene, camera );
    time = Date.now();
}

  // this is outdated should use raycaster instead since it gives more info anyway
  // also projector is moved.
  // to adjust to use raycaster we need to adjust yawObject and pitch object

  TODO: // HERE
var projector = new THREE.Projector();

// get shoot direction might need to be adjusted to use ray caster instead
const getShootDir = function(targetVec){
    var vector = targetVec;
    targetVec.set(0,0,1);
    projector.unprojectVector(vector, camera);
    var ray = new THREE.Ray(sphereBody.position, vector.sub(sphereBody.position).normalize() );
    targetVec.copy(ray.direction);
}

export { scene, camera, renderer, controls, light, getShootDir }
<|endoftext|>


<commit_before>var SiteMap = require('sitemap.js').SiteMap;
var Doc = require('ngdoc.js').Doc;

describe('sitemap', function(){
  it('should render empty sitemap', function(){
    var map = new SiteMap([]);
    expect(map.render()).toEqual([
      '<?xml version="1.0" encoding="UTF-8"?>',
      '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">',
      '</urlset>', ''].join('\n'));
  });

  it('should render ngdoc url', function(){
    var map = new SiteMap([new Doc({name: 'a.b.c<>\'"&'})]);
    expect(map.render()).toContain([
      ' <url>',
      '<loc>http://docs.angularjs.org/#!a.b.c<>'"&</loc>',
      '<changefreq>weekly</changefreq>',
      '</url>'].join(''));

  });
});
<commit_msg>Fix sitemap include (to work on case sensitive linux)<commit_after>var SiteMap = require('SiteMap.js').SiteMap;
var Doc = require('ngdoc.js').Doc;

describe('sitemap', function(){
  it('should render empty sitemap', function(){
    var map = new SiteMap([]);
    expect(map.render()).toEqual([
      '<?xml version="1.0" encoding="UTF-8"?>',
      '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">',
      '</urlset>', ''].join('\n'));
  });

  it('should render ngdoc url', function(){
    var map = new SiteMap([new Doc({name: 'a.b.c<>\'"&'})]);
    expect(map.render()).toContain([
      ' <url>',
      '<loc>http://docs.angularjs.org/#!a.b.c<>'"&</loc>',
      '<changefreq>weekly</changefreq>',
      '</url>'].join(''));

  });
});
<|endoftext|>


<commit_before>export { ActivationFunction };

import { Int } from "./ValueDesc_Base.js";
import * as Weights from "../Weights.js";
import * as FloatValue from "../FloatValue.js";

/**
 * Describe activation function parameter's id, range, name.
 *
 * For inputDomainLinear,
 *   - RELU6 is linear between[ 0, 6 ].
 *   - TANH is almost linear between[ -0.005, +0.005 ].
 *   - SIN is almost linear between[ -0.005, +0.005 ].
 *   - COS is almost linear between[ -( ( PI / 2 ) + 0.005 ), -( ( PI / 2 ) - 0.005 ) ].
 *   - SIGMOID is alomost linear between[ -0.125, +0.125 ].
 *   - RELU is linear between[ 0, +Infinity ].
 */
class ActivationFunction extends Int {

  constructor() {

    // Note:
    //   - NONE: Beware. It easily results in infinity value because it does not have upper bound.
    //   - RELU: Beware. It easily results in infinity value because it does not have upper bound.
    //   - SOFTPLUS: Avoid. Backend WASM does not support it.
    //   - ERF: Avoid. Backend WASM does not support it.
    //
    //   - TANH, SIN, ERF are good if pass-through by only scale (i.e. without translate) is needed. Because the output range of
    //       them includes both negative and positive near the origin point. (On the other hand, RELU, RELU6 are not good for this
    //       purpose.)

    super( 0, 5,
      [ "NONE",  "RELU6",  "TANH",  "SIN",  "COS",  "SIGMOID" ], // "RELU" ], //  "SOFTPLUS" ],

//!!! ...unfinished... (2022/01/10)
// Add ActivationFunction.Info.linearRange (the output range for linearDomain).
// When calculating ActivationEscaping bounds array of pass-through part, use it instead of normal info.range.

      [
        new ActivationFunction.Info( 0, null, null, null ),

        new ActivationFunction.Info( 1, tf.relu6,
          new FloatValue.Bounds( 0, 6 ), new FloatValue.Bounds( 0, 6 ) ),

        new ActivationFunction.Info( 2, tf.tanh,
          new FloatValue.Bounds( -0.005, +0.005 ), new FloatValue.Bounds( -1, +1 ) ),

        new ActivationFunction.Info( 3, tf.sin,
          new FloatValue.Bounds( -0.005, +0.005 ), new FloatValue.Bounds( -1, +1 ) ),

        new ActivationFunction.Info( 4, tf.cos,
          new FloatValue.Bounds( -( ( Math.PI / 2 ) + 0.005 ), -( ( Math.PI / 2 ) - 0.005 ) ), new FloatValue.Bounds( -1, +1 ) ),

        new ActivationFunction.Info( 5, tf.sigmoid,
          new FloatValue.Bounds( -0.125, +0.125 ), new FloatValue.Bounds( 0, 1 ) ),

        // (2021/12/09 Remarked)
        //
        // The input linear domain and output range of RELU are [ 0, +Infinity ]. However, it is not so friendly to interact with Infinity
        // because the results may be Infinity or even NaN. This is more obvious for scale-translate into linear domain in PointDepthPoint.
        // So, the RELU is excluded from the activation function list.
        //
        //new ActivationFunction.Info( 6, tf.relu,
        //  //new FloatValue.Bounds( 0, Weights.Base.ValueBounds.upper ), new FloatValue.Bounds( 0, Weights.Base.ValueBounds.upper ) ),
        //  new FloatValue.Bounds( 0, +Infinity ), new FloatValue.Bounds( 0, +Infinity ) ),

        //new ActivationFunction.Info( 7, tf.softplus,
        //  new Base( 0, 6 ), Weights.Base.ValueBounds ),
      ]
    );

  }

  /**
   * Convert activation function id to information object.
   *
   * @param {number} nActivationId
   *   It should be one of ValueDesc.ActivationFunction.Singleton.Ids.Xxx. (e.g. ValueDesc.ActivationFunction.Singleton.Ids.NONE,
   * ValueDesc.ActivationFunction.Singleton.Ids.RELU6, ValueDesc.ActivationFunction.Singleton.Ids.COS, ...)
   *
   * @return {ActivationFunction.Info}
   *   It should be one of ValueDesc.ActivationFunction.Singleton.integerToObjectMap according to the nActivationId.
   */
  getInfoById( nActivationId ) {
    let info = this.integerToObjectMap.get( nActivationId );
    return info;
  }

}

//!!! ...unfinished... (2022/01/10)
// Add ActivationFunction.Info.linearRange (the output range for linearDomain).
// When calculating ActivationEscaping bounds array of pass-through part, use it instead of normal info.range.

/**
 *
 * @member {number} nActivationId
 *   The activation function id (ValueDesc.ActivationFunction.Singleton.Ids.Xxx).
 *
 * @member {Function} pfn
 *   The activation function. (e.g. tf.relu6, tf.tanh, tf.sin, tf.cos, tf.sigmoid, tf.relu)
 *
 * @member {FloatValue.Bounds} inputDomainLinear
 *   The input value lower and upper bounds of the activation function for keeping the mapping from input to output almost linear. In
 * general speaking, an activation function is non-linear in the whole domain. However, inside this special part of the domain, it looks
 * almost like a linear function.
 *
 * @member {FloatValue.Bounds} outputRange
 *   The output value lower and upper bounds of the activation function.
 */
ActivationFunction.Info = class {
  constructor( nActivationId, pfn, inputDomainLinear, outputRange ) {
    this.nActivationId = nActivationId;
    this.pfn = pfn;
    this.inputDomainLinear = inputDomainLinear;
    this.outputRange = outputRange;
  }
}

/** The only one ValueDesc.ActivationFunction instance. */
ActivationFunction.Singleton = new ActivationFunction;
<commit_msg>Update ValueDesc_ActivationFunction.js<commit_after>export { ActivationFunction };

import { Int } from "./ValueDesc_Base.js";
import * as Weights from "../Weights.js";
import * as FloatValue from "../FloatValue.js";

/**
 * Describe activation function parameter's id, range, name.
 *
 * For inputDomainLinear,
 *   - RELU6 is linear between[ 0, 6 ].
 *   - TANH is almost linear between[ -0.005, +0.005 ].
 *   - SIN is almost linear between[ -0.005, +0.005 ].
 *   - COS is almost linear between[ -( ( PI / 2 ) + 0.005 ), -( ( PI / 2 ) - 0.005 ) ].
 *   - SIGMOID is alomost linear between[ -0.125, +0.125 ].
 *   - RELU is linear between[ 0, +Infinity ].
 */
class ActivationFunction extends Int {

  constructor() {

    // Note:
    //   - NONE: Beware. It easily results in infinity value because it does not have upper bound.
    //   - RELU: Beware. It easily results in infinity value because it does not have upper bound.
    //   - SOFTPLUS: Avoid. Backend WASM does not support it.
    //   - ERF: Avoid. Backend WASM does not support it.
    //
    //   - TANH, SIN, ERF are good if pass-through by only scale (i.e. without translate) is needed. Because the output range of
    //       them includes both negative and positive near the origin point. (On the other hand, RELU, RELU6 are not good for this
    //       purpose.)

    super( 0, 5,
      [ "NONE",  "RELU6",  "TANH",  "SIN",  "COS",  "SIGMOID" ], // "RELU" ], //  "SOFTPLUS" ],

//!!! ...unfinished... (2022/01/10)
// Add ActivationFunction.Info.outputRangeLinear (the output range for linearDomainLinear).
// When calculating ActivationEscaping bounds array of pass-through part, use it instead of normal info.range.

      [
        new ActivationFunction.Info( 0, null, null, null ),

        new ActivationFunction.Info( 1, tf.relu6,
          new FloatValue.Bounds( 0, 6 ), new FloatValue.Bounds( 0, 6 ) ),

        new ActivationFunction.Info( 2, tf.tanh,
          new FloatValue.Bounds( -0.005, +0.005 ), new FloatValue.Bounds( -1, +1 ) ),

        new ActivationFunction.Info( 3, tf.sin,
          new FloatValue.Bounds( -0.005, +0.005 ), new FloatValue.Bounds( -1, +1 ) ),

        new ActivationFunction.Info( 4, tf.cos,
          new FloatValue.Bounds( -( ( Math.PI / 2 ) + 0.005 ), -( ( Math.PI / 2 ) - 0.005 ) ), new FloatValue.Bounds( -1, +1 ) ),

        new ActivationFunction.Info( 5, tf.sigmoid,
          new FloatValue.Bounds( -0.125, +0.125 ), new FloatValue.Bounds( 0, 1 ) ),

        // (2021/12/09 Remarked)
        //
        // The input linear domain and output range of RELU are [ 0, +Infinity ]. However, it is not so friendly to interact with Infinity
        // because the results may be Infinity or even NaN. This is more obvious for scale-translate into linear domain in PointDepthPoint.
        // So, the RELU is excluded from the activation function list.
        //
        //new ActivationFunction.Info( 6, tf.relu,
        //  //new FloatValue.Bounds( 0, Weights.Base.ValueBounds.upper ), new FloatValue.Bounds( 0, Weights.Base.ValueBounds.upper ) ),
        //  new FloatValue.Bounds( 0, +Infinity ), new FloatValue.Bounds( 0, +Infinity ) ),

        //new ActivationFunction.Info( 7, tf.softplus,
        //  new Base( 0, 6 ), Weights.Base.ValueBounds ),
      ]
    );

  }

  /**
   * Convert activation function id to information object.
   *
   * @param {number} nActivationId
   *   It should be one of ValueDesc.ActivationFunction.Singleton.Ids.Xxx. (e.g. ValueDesc.ActivationFunction.Singleton.Ids.NONE,
   * ValueDesc.ActivationFunction.Singleton.Ids.RELU6, ValueDesc.ActivationFunction.Singleton.Ids.COS, ...)
   *
   * @return {ActivationFunction.Info}
   *   It should be one of ValueDesc.ActivationFunction.Singleton.integerToObjectMap according to the nActivationId.
   */
  getInfoById( nActivationId ) {
    let info = this.integerToObjectMap.get( nActivationId );
    return info;
  }

}

//!!! ...unfinished... (2022/01/10)
// Add ActivationFunction.Info.outputRangeLinear (the output range for linearDomainLinear).
// When calculating ActivationEscaping bounds array of pass-through part, use it instead of normal info.range.

/**
 *
 * @member {number} nActivationId
 *   The activation function id (ValueDesc.ActivationFunction.Singleton.Ids.Xxx).
 *
 * @member {Function} pfn
 *   The activation function. (e.g. tf.relu6, tf.tanh, tf.sin, tf.cos, tf.sigmoid, tf.relu)
 *
 * @member {FloatValue.Bounds} inputDomainLinear
 *   The input value lower and upper bounds of the activation function for keeping the mapping from input to output almost linear. In
 * general speaking, an activation function is non-linear in the whole domain. However, inside this special part of the domain, it looks
 * almost like a linear function.
 *
 * @member {FloatValue.Bounds} outputRange
 *   The output value lower and upper bounds of the activation function.
 */
ActivationFunction.Info = class {
  constructor( nActivationId, pfn, inputDomainLinear, outputRange ) {
    this.nActivationId = nActivationId;
    this.pfn = pfn;
    this.inputDomainLinear = inputDomainLinear;
    this.outputRange = outputRange;
  }
}

/** The only one ValueDesc.ActivationFunction instance. */
ActivationFunction.Singleton = new ActivationFunction;
<|endoftext|>


<commit_before>// Modified from:
// https://raw.github.com/kanaka/noVNC/d890e8640f20fba3215ba7be8e0ff145aeb8c17c/include/base64.js

'use strict';

// A trick for browserified version.
// Since we make browserifier to ignore `buffer` module, NodeBuffer will be undefined
var NodeBuffer = require('buffer').Buffer;

var Type       = require('../type');

var BASE64_PADDING = '=';

var BASE64_BINTABLE = [
  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,
  52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1,  0, -1, -1,
  -1,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14,
  15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,
  -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
  41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1
];

var BASE64_CHARTABLE =
  'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'.split('');

function validateYamlBinary(data) {
  var value, code, idx = 0, result = [], leftbits, leftdata;

  leftbits = 0; // number of bits decoded, but yet to be appended
  leftdata = 0; // bits decoded, but yet to be appended

  // Convert one by one.
  for (idx = 0; idx < data.length; idx += 1) {
    code = data.charCodeAt(idx);
    value = BASE64_BINTABLE[code & 0x7F];

    // Skip LF(NL) || CR
    if (0x0A !== code && 0x0D !== code) {
      // Fail on illegal characters
      if (-1 === value) {
        return false;
      }

      // Collect data into leftdata, update bitcount
      leftdata = (leftdata << 6) | value;
      leftbits += 6;

      // If we have 8 or more bits, append 8 bits to the result
      if (leftbits >= 8) {
        leftbits -= 8;

        // Append if not padding.
        if (BASE64_PADDING !== data.charAt(idx)) {
          result.push((leftdata >> leftbits) & 0xFF);
        }

        leftdata &= (1 << leftbits) - 1;
      }
    }
  }

  // If there are any bits left, the base64 string was corrupted
  if (leftbits) {
    return false;
  } else {
    return true;
  }
}

function resolveYamlBinary(data) {
  var value, code, idx = 0, result = [], leftbits, leftdata;

  leftbits = 0; // number of bits decoded, but yet to be appended
  leftdata = 0; // bits decoded, but yet to be appended

  // Convert one by one.
  for (idx = 0; idx < data.length; idx += 1) {
    code = data.charCodeAt(idx);
    value = BASE64_BINTABLE[code & 0x7F];

    // Skip LF(NL) || CR
    if (0x0A !== code && 0x0D !== code) {
      // Fail on illegal characters
      if (-1 === value) {
        throw new Error('birany resolve error');
      }

      // Collect data into leftdata, update bitcount
      leftdata = (leftdata << 6) | value;
      leftbits += 6;

      // If we have 8 or more bits, append 8 bits to the result
      if (leftbits >= 8) {
        leftbits -= 8;

        // Append if not padding.
        if (BASE64_PADDING !== data.charAt(idx)) {
          result.push((leftdata >> leftbits) & 0xFF);
        }

        leftdata &= (1 << leftbits) - 1;
      }
    }
  }

  // If there are any bits left, the base64 string was corrupted
  if (leftbits) {
    throw new Error('birany resolve error');
  }

  // Wrap into Buffer for NodeJS and leave Array for browser
  if (NodeBuffer) {
    return new NodeBuffer(result);
  }

  return result;
}

function representYamlBinary(object /*, style*/) {
  var result = '', index, length, rest;

  // Convert every three bytes to 4 ASCII characters.
  for (index = 0, length = object.length - 2; index < length; index += 3) {
    result += BASE64_CHARTABLE[object[index + 0] >> 2];
    result += BASE64_CHARTABLE[((object[index + 0] & 0x03) << 4) + (object[index + 1] >> 4)];
    result += BASE64_CHARTABLE[((object[index + 1] & 0x0F) << 2) + (object[index + 2] >> 6)];
    result += BASE64_CHARTABLE[object[index + 2] & 0x3F];
  }

  rest = object.length % 3;

  // Convert the remaining 1 or 2 bytes, padding out to 4 characters.
  if (0 !== rest) {
    index = object.length - rest;
    result += BASE64_CHARTABLE[object[index + 0] >> 2];

    if (2 === rest) {
      result += BASE64_CHARTABLE[((object[index + 0] & 0x03) << 4) + (object[index + 1] >> 4)];
      result += BASE64_CHARTABLE[(object[index + 1] & 0x0F) << 2];
      result += BASE64_PADDING;
    } else {
      result += BASE64_CHARTABLE[(object[index + 0] & 0x03) << 4];
      result += BASE64_PADDING + BASE64_PADDING;
    }
  }

  return result;
}

function isBinary(object) {
  return NodeBuffer && NodeBuffer.isBuffer(object);
}

module.exports = new Type('tag:yaml.org,2002:binary', {
  loadKind: 'scalar',
  loadValidator: validateYamlBinary,
  loadResolver: resolveYamlBinary,
  dumpPredicate: isBinary,
  dumpRepresenter: representYamlBinary
});
<commit_msg>bin type cleanup<commit_after>// Modified from:
// https://raw.github.com/kanaka/noVNC/d890e8640f20fba3215ba7be8e0ff145aeb8c17c/include/base64.js

'use strict';

// A trick for browserified version.
// Since we make browserifier to ignore `buffer` module, NodeBuffer will be undefined
var NodeBuffer = require('buffer').Buffer;

var Type       = require('../type');

var BASE64_PADDING = '=';

var BASE64_BINTABLE = [
  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,
  52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1,  0, -1, -1,
  -1,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14,
  15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,
  -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
  41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1
];

var BASE64_CHARTABLE =
  'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'.split('');

function validateYamlBinary(data) {
  var code, idx = 0, len = data.length, leftbits;

  leftbits = 0; // number of bits decoded, but yet to be appended

  // Convert one by one.
  for (idx = 0; idx < len; idx += 1) {
    code = data.charCodeAt(idx);

    // Skip LF(NL) || CR
    if (0x0A === code || 0x0D === code) { continue; }

    // Fail on illegal characters
    if (-1 === BASE64_BINTABLE[code & 0x7F]) {
      return false;
    }

    // update bitcount
    leftbits += 6;

    // If we have 8 or more bits, append 8 bits to the result
    if (leftbits >= 8) {
      leftbits -= 8;
    }
  }

  // If there are any bits left, the base64 string was corrupted
  if (leftbits) {
    return false;
  } else {
    return true;
  }
}

function resolveYamlBinary(data) {
  var value, code, idx = 0, len = data.length, result = [], leftbits, leftdata;

  leftbits = 0; // number of bits decoded, but yet to be appended
  leftdata = 0; // bits decoded, but yet to be appended

  // Convert one by one.
  for (idx = 0; idx < len; idx += 1) {
    code = data.charCodeAt(idx);
    value = BASE64_BINTABLE[code & 0x7F];

    // Skip LF(NL) || CR
    if (0x0A === code || 0x0D === code) { continue; }

    // Collect data into leftdata, update bitcount
    leftdata = (leftdata << 6) | value;
    leftbits += 6;

    // If we have 8 or more bits, append 8 bits to the result
    if (leftbits >= 8) {
      leftbits -= 8;

      // Append if not padding.
      if (BASE64_PADDING !== data.charAt(idx)) {
        result.push((leftdata >> leftbits) & 0xFF);
      }

      leftdata &= (1 << leftbits) - 1;
    }
  }

  // Wrap into Buffer for NodeJS and leave Array for browser
  if (NodeBuffer) {
    return new NodeBuffer(result);
  }

  return result;
}

function representYamlBinary(object /*, style*/) {
  var result = '', index, length, rest;

  // Convert every three bytes to 4 ASCII characters.
  for (index = 0, length = object.length - 2; index < length; index += 3) {
    result += BASE64_CHARTABLE[object[index + 0] >> 2];
    result += BASE64_CHARTABLE[((object[index + 0] & 0x03) << 4) + (object[index + 1] >> 4)];
    result += BASE64_CHARTABLE[((object[index + 1] & 0x0F) << 2) + (object[index + 2] >> 6)];
    result += BASE64_CHARTABLE[object[index + 2] & 0x3F];
  }

  rest = object.length % 3;

  // Convert the remaining 1 or 2 bytes, padding out to 4 characters.
  if (0 !== rest) {
    index = object.length - rest;
    result += BASE64_CHARTABLE[object[index + 0] >> 2];

    if (2 === rest) {
      result += BASE64_CHARTABLE[((object[index + 0] & 0x03) << 4) + (object[index + 1] >> 4)];
      result += BASE64_CHARTABLE[(object[index + 1] & 0x0F) << 2];
      result += BASE64_PADDING;
    } else {
      result += BASE64_CHARTABLE[(object[index + 0] & 0x03) << 4];
      result += BASE64_PADDING + BASE64_PADDING;
    }
  }

  return result;
}

function isBinary(object) {
  return NodeBuffer && NodeBuffer.isBuffer(object);
}

module.exports = new Type('tag:yaml.org,2002:binary', {
  loadKind: 'scalar',
  loadValidator: validateYamlBinary,
  loadResolver: resolveYamlBinary,
  dumpPredicate: isBinary,
  dumpRepresenter: representYamlBinary
});
<|endoftext|>