<commit_before>// Reading material
// ----------------
// http://www.nanobit.net/doxy/quake3/g__client_8c-source.html
// G_LogPrint is the method name for printing to the log on this file: https://github.com/id-Software/Quake-III-Arena/blob/dbe4ddb10315479fc00086f08e25d968b4b43c49/code/game/g_main.c
// http://planetquake.gamespy.com/View.php?view=Guides.Detail&id=51&game=4

'use strict';

angular.module('quakeStatsApp')
  .service('GameslogService', ['$http', 'Constants', function ($http, Constants) {
 	this.maps = {
 		"q3ctf1" : "Dueling Keeps",
		"q3ctf3" : "The Stronghold",
 		"q3ctf4" : "Space CTF",
 		"speedyctf" : "Speedy",
 		"q3ctf2": "Troubled Waters",
        "ump3ctf1": "Breakdown",
        "ump3ctf2": "Hydrophobia",
        "ump3ctf3": "Got Wood",
        "ump3ctf4": "Frozen Colors",
        "ump3ctf5": "Railfest 2: 7Zark7 Island",
        "ump3ctf6": "Like spinning plates",
        "ump3ctf7": "The Strong Jaeger"
 	};
 	this.gameslog = null;
 	this.loglines = null;
 	this.blueFlagStatus = Constants.FLAG_STATUS_IN_BASE;
 	this.redFlagStatus = Constants.FLAG_STATUS_IN_BASE;
 	var me = this;

 	this.loadLog = function() {
 		return $http.get('/rest/games/log').success(function(data) {
	    	me.gameslog = data;
	    	me.loglines = me.gameslog.split("\n");
	    });
 	}

 	this.getGameObject = function(line, index) {
    	var startIndex = line.indexOf(Constants.MAP_NAME_KEY) + Constants.MAP_NAME_KEY.length,
    		endIndex =   line.indexOf(Constants.BACKSLASH_KEY, startIndex),
    		key = line.slice(startIndex, endIndex).toLowerCase(),
    		mapname = me.getGameName(key);
    	return {
    		"index" : index,
    		"mapname" : mapname
    	}
    }

    this.getAllGames = function() {
    	var line;
    	var games = [];
    	// FIXME: Remove and use Route Resolve instead
    	if (me.loglines ==  null) {
    		this.loadLog().then(function() {
                // FIXME: Remove suplicated loop (below)
    			for (var index in me.loglines) {
					line = me.loglines[index];
					if (line.indexOf('InitGame:') !== -1) {
                        games.push(me.getGame(index));
					}
		    	}
		    	return games;
    		})
    	}
    	for (var index in me.loglines) {
			line = me.loglines[index];
			if (line.indexOf('InitGame:') !== -1) {
				games.push(me.getGame(index));
			}
    	}
    	return games;
    }

    this.getGame = function(index) {
    	var game = {},
    		record = null,
    		players = {},
    		flags = [],
    		redTeam = [],
    		blueTeam = [],
            score = {},
            bestScorer = null,
            bestFetcher = null,
            bestRebounder = null,
            bestRestorer = null;

        score[Constants.RED] = 0;
        score[Constants.BLUE] = 0;
    	me.redFlagStatus = Constants.FLAG_STATUS_IN_BASE;
		me.blueFlagStatus = Constants.FLAG_STATUS_IN_BASE;

    	for (var i = index; i < me.loglines.length; i++) {
    		record = me.loglines[i];
    		if (i === index) {
    			game.name = me.getGameObject(record, index).mapname;
                game.recordIndex = me.getGameObject(record, index).index;
    		}

			if (record.indexOf('ClientUserinfoChanged') !== -1) {
				players[me.getPlayerObject(record).id] = me.getPlayerObject(record);
			}

            // Flags
			if (record.indexOf('team_CTF_') !== -1) {
                var flag = me.getFlagObject(record, players);
                if (flag.action === "scored!") {
                    if (flag.color === Constants.RED) {
                        score[Constants.RED] += 1;
                    }
                    if (flag.color === Constants.BLUE) {
                        score[Constants.BLUE] += 1;
                    }
                }
				flags.push(flag);
			}

            // ShutdownGame
			if (record.indexOf('ShutdownGame') !== -1) {
				game.players = players;
				game.flags = flags;
                game.score = score;
                game.bestScorer = me.getBest(players, 'scoredFlags');
                game.bestFetcher = me.getBest(players, 'fetchedFlags');
                game.bestRebounder = me.getBest(players, 'reboundedFlags');
                game.bestRestorer = me.getBest(players, 'restoredFlags');
				return game;
			}
    	}
    }

    this.getBest = function(players, prop) {
        var bestScorer = null,
            player = null;
        for (var item in players) {
            player = players[item];
            if (bestScorer == null) {
                bestScorer = player;
                continue;
            }
            if (player[prop] > bestScorer[prop]) {
                bestScorer = player
            }
        }
        return bestScorer;
    }

    this.getPlayerObject = function(record) {
    	var player = {},
    	idStr = record.slice(record.indexOf(Constants.PLAYER_INFO_KEY) + Constants.PLAYER_INFO_KEY.length, record.indexOf(Constants.PLAYER_NAME_KEY)),
        nameStr = record.slice(record.indexOf(Constants.PLAYER_NAME_KEY) + Constants.PLAYER_NAME_KEY.length, record.indexOf(Constants.BACKSLASH_KEY, record.indexOf(Constants.PLAYER_NAME_KEY) + Constants.PLAYER_NAME_KEY.length)),
        teamStr = record.substr(record.indexOf(Constants.TEAM_NUM_KEY) + Constants.TEAM_NUM_KEY.length, 1);

        player.id = parseInt(idStr);
    	player.name = nameStr;
    	player.team = parseInt(teamStr);
        player.fetchedFlags = 0;
        player.restoredFlags = 0;
        player.reboundedFlags = 0;
        player.scoredFlags = 0;
		return player;
    }

    this.getFlagObject = function(record, players) {
    	var flag = {};
    	var idStr = record.slice(record.indexOf('Item: ') + 6, record.indexOf('team_CTF_'));
    	var playerId = parseInt(idStr);
    	var player = players[playerId];

        if (player) {
        	flag.record = record;
        	flag.player = player;
        	if (record.indexOf('redflag') !== -1) {
        		flag.color = Constants.RED;
        		flag.action = me.getRedFlagAction(record, player)
        	}
        	if (record.indexOf('blueflag') !== -1) {
        		flag.color = Constants.BLUE;
        		flag.action = me.getBlueFlagAction(record, player)
        	}
        }
    	return flag;
    }

    this.getRedFlagAction = function(record, player) {
    	if (player.team === 2) {
    		if (me.redFlagStatus === Constants.FLAG_STATUS_IN_BASE) {
	    		me.redFlagStatus = Constants.FLAG_STATUS_FETCHED
                player.fetchedFlags += 1;
	    		return 'fetched';
	    	}
	    	if (me.redFlagStatus === Constants.FLAG_STATUS_FETCHED || me.redFlagStatus === Constants.FLAG_STATUS_REBOUNDED) {
	    		me.redFlagStatus = Constants.FLAG_STATUS_REBOUNDED;
                player.reboundedFlags += 1;
	    		return 'rebounded';
	    	}
    	} else if (player.team === 1) {
    		if (me.redFlagStatus === Constants.FLAG_STATUS_IN_BASE) {
    			me.blueFlagStatus = Constants.FLAG_STATUS_IN_BASE;
                player.scoredFlags += 1;
	    		return 'scored!';
	    	}
	    	if (me.redFlagStatus === Constants.FLAG_STATUS_FETCHED || me.redFlagStatus === Constants.FLAG_STATUS_REBOUNDED) {
	    		me.redFlagStatus = Constants.FLAG_STATUS_IN_BASE;
                player.restoredFlags += 1;
	    		return 'restored';
	    	}
    	}
    }

    this.getBlueFlagAction = function(record, player) {
    	if (player.team === 1) {
    		if (me.blueFlagStatus === Constants.FLAG_STATUS_IN_BASE) {
	    		me.blueFlagStatus = Constants.FLAG_STATUS_FETCHED;
                player.fetchedFlags += 1;
	    		return 'fetched';
	    	}
	    	if (me.blueFlagStatus === Constants.FLAG_STATUS_FETCHED || me.blueFlagStatus === Constants.FLAG_STATUS_REBOUNDED) {
	    		me.blueFlagStatus = Constants.FLAG_STATUS_REBOUNDED;
                player.reboundedFlags += 1;
	    		return 'Rebounded';
	    	}
    	} else if (player.team === 2) {
    		if (me.blueFlagStatus === Constants.FLAG_STATUS_IN_BASE) {
    			me.redFlagStatus = Constants.FLAG_STATUS_IN_BASE;
                player.scoredFlags += 1;
	    		return 'scored!';
	    	}
	    	if (me.blueFlagStatus === Constants.FLAG_STATUS_FETCHED || me.blueFlagStatus === Constants.FLAG_STATUS_REBOUNDED) {
	    		me.blueFlagStatus = Constants.FLAG_STATUS_IN_BASE;
                player.restoredFlags += 1;
	    		return 'Restored';
	    	}
    	}
    }

    this.getGameName = function(key) {
    	var name = key;
    	if (me.maps.hasOwnProperty(key)) {
			name = me.maps[key]
		}
		return name;
    }
  }]);<commit_msg>Remove duplicated games loop<commit_after>// Reading material
// ----------------
// http://www.nanobit.net/doxy/quake3/g__client_8c-source.html
// G_LogPrint is the method name for printing to the log on this file: https://github.com/id-Software/Quake-III-Arena/blob/dbe4ddb10315479fc00086f08e25d968b4b43c49/code/game/g_main.c
// http://planetquake.gamespy.com/View.php?view=Guides.Detail&id=51&game=4

'use strict';

angular.module('quakeStatsApp')
  .service('GameslogService', ['$http', 'Constants', function ($http, Constants) {
 	this.maps = {
 		"q3ctf1" : "Dueling Keeps",
		"q3ctf3" : "The Stronghold",
 		"q3ctf4" : "Space CTF",
 		"speedyctf" : "Speedy",
 		"q3ctf2": "Troubled Waters",
        "ump3ctf1": "Breakdown",
        "ump3ctf2": "Hydrophobia",
        "ump3ctf3": "Got Wood",
        "ump3ctf4": "Frozen Colors",
        "ump3ctf5": "Railfest 2: 7Zark7 Island",
        "ump3ctf6": "Like spinning plates",
        "ump3ctf7": "The Strong Jaeger"
 	};
 	this.gameslog = null;
 	this.loglines = null;
 	this.blueFlagStatus = Constants.FLAG_STATUS_IN_BASE;
 	this.redFlagStatus = Constants.FLAG_STATUS_IN_BASE;
    this.games = [];
 	var me = this;

 	this.loadLog = function() {
 		return $http.get('/rest/games/log').success(function(data) {
	    	me.gameslog = data;
	    	me.loglines = me.gameslog.split("\n");
	    });
 	}

 	this.getGameObject = function(line, index) {
    	var startIndex = line.indexOf(Constants.MAP_NAME_KEY) + Constants.MAP_NAME_KEY.length,
    		endIndex =   line.indexOf(Constants.BACKSLASH_KEY, startIndex),
    		key = line.slice(startIndex, endIndex).toLowerCase(),
    		mapname = me.getGameName(key);
    	return {
    		"index" : index,
    		"mapname" : mapname
    	}
    }

    this.getAllGames = function() {
    	var line;
    	// FIXME: Remove and use Route Resolve instead
    	if (me.loglines ==  null) {
    		this.loadLog().then(function() {
                // FIXME: Remove suplicated loop (below)
    			for (var index in me.loglines) {
					line = me.loglines[index];
					if (line.indexOf('InitGame:') !== -1) {
                        me.games.push(me.getGame(index));
					}
		    	}
		    	return me.games;
    		})
    	}
    	return me.games;
    }

    this.getGame = function(index) {
    	var game = {},
    		record = null,
    		players = {},
    		flags = [],
    		redTeam = [],
    		blueTeam = [],
            score = {},
            bestScorer = null,
            bestFetcher = null,
            bestRebounder = null,
            bestRestorer = null;

        score[Constants.RED] = 0;
        score[Constants.BLUE] = 0;
    	me.redFlagStatus = Constants.FLAG_STATUS_IN_BASE;
		me.blueFlagStatus = Constants.FLAG_STATUS_IN_BASE;

    	for (var i = index; i < me.loglines.length; i++) {
    		record = me.loglines[i];
    		if (i === index) {
    			game.name = me.getGameObject(record, index).mapname;
                game.recordIndex = me.getGameObject(record, index).index;
    		}

			if (record.indexOf('ClientUserinfoChanged') !== -1) {
				players[me.getPlayerObject(record).id] = me.getPlayerObject(record);
			}

            // Flags
			if (record.indexOf('team_CTF_') !== -1) {
                var flag = me.getFlagObject(record, players);
                if (flag.action === "scored!") {
                    if (flag.color === Constants.RED) {
                        score[Constants.RED] += 1;
                    }
                    if (flag.color === Constants.BLUE) {
                        score[Constants.BLUE] += 1;
                    }
                }
				flags.push(flag);
			}

            // ShutdownGame
			if (record.indexOf('ShutdownGame') !== -1) {
				game.players = players;
				game.flags = flags;
                game.score = score;
                game.bestScorer = me.getBest(players, 'scoredFlags');
                game.bestFetcher = me.getBest(players, 'fetchedFlags');
                game.bestRebounder = me.getBest(players, 'reboundedFlags');
                game.bestRestorer = me.getBest(players, 'restoredFlags');
				return game;
			}
    	}
    }

    this.getBest = function(players, prop) {
        var bestScorer = null,
            player = null;
        for (var item in players) {
            player = players[item];
            if (bestScorer == null) {
                bestScorer = player;
                continue;
            }
            if (player[prop] > bestScorer[prop]) {
                bestScorer = player
            }
        }
        return bestScorer;
    }

    this.getPlayerObject = function(record) {
    	var player = {},
    	idStr = record.slice(record.indexOf(Constants.PLAYER_INFO_KEY) + Constants.PLAYER_INFO_KEY.length, record.indexOf(Constants.PLAYER_NAME_KEY)),
        nameStr = record.slice(record.indexOf(Constants.PLAYER_NAME_KEY) + Constants.PLAYER_NAME_KEY.length, record.indexOf(Constants.BACKSLASH_KEY, record.indexOf(Constants.PLAYER_NAME_KEY) + Constants.PLAYER_NAME_KEY.length)),
        teamStr = record.substr(record.indexOf(Constants.TEAM_NUM_KEY) + Constants.TEAM_NUM_KEY.length, 1);

        player.id = parseInt(idStr);
    	player.name = nameStr;
    	player.team = parseInt(teamStr);
        player.fetchedFlags = 0;
        player.restoredFlags = 0;
        player.reboundedFlags = 0;
        player.scoredFlags = 0;
		return player;
    }

    this.getFlagObject = function(record, players) {
    	var flag = {};
    	var idStr = record.slice(record.indexOf('Item: ') + 6, record.indexOf('team_CTF_'));
    	var playerId = parseInt(idStr);
    	var player = players[playerId];

        if (player) {
        	flag.record = record;
        	flag.player = player;
        	if (record.indexOf('redflag') !== -1) {
        		flag.color = Constants.RED;
        		flag.action = me.getRedFlagAction(record, player)
        	}
        	if (record.indexOf('blueflag') !== -1) {
        		flag.color = Constants.BLUE;
        		flag.action = me.getBlueFlagAction(record, player)
        	}
        }
    	return flag;
    }

    this.getRedFlagAction = function(record, player) {
    	if (player.team === 2) {
    		if (me.redFlagStatus === Constants.FLAG_STATUS_IN_BASE) {
	    		me.redFlagStatus = Constants.FLAG_STATUS_FETCHED
                player.fetchedFlags += 1;
	    		return 'fetched';
	    	}
	    	if (me.redFlagStatus === Constants.FLAG_STATUS_FETCHED || me.redFlagStatus === Constants.FLAG_STATUS_REBOUNDED) {
	    		me.redFlagStatus = Constants.FLAG_STATUS_REBOUNDED;
                player.reboundedFlags += 1;
	    		return 'rebounded';
	    	}
    	} else if (player.team === 1) {
    		if (me.redFlagStatus === Constants.FLAG_STATUS_IN_BASE) {
    			me.blueFlagStatus = Constants.FLAG_STATUS_IN_BASE;
                player.scoredFlags += 1;
	    		return 'scored!';
	    	}
	    	if (me.redFlagStatus === Constants.FLAG_STATUS_FETCHED || me.redFlagStatus === Constants.FLAG_STATUS_REBOUNDED) {
	    		me.redFlagStatus = Constants.FLAG_STATUS_IN_BASE;
                player.restoredFlags += 1;
	    		return 'restored';
	    	}
    	}
    }

    this.getBlueFlagAction = function(record, player) {
    	if (player.team === 1) {
    		if (me.blueFlagStatus === Constants.FLAG_STATUS_IN_BASE) {
	    		me.blueFlagStatus = Constants.FLAG_STATUS_FETCHED;
                player.fetchedFlags += 1;
	    		return 'fetched';
	    	}
	    	if (me.blueFlagStatus === Constants.FLAG_STATUS_FETCHED || me.blueFlagStatus === Constants.FLAG_STATUS_REBOUNDED) {
	    		me.blueFlagStatus = Constants.FLAG_STATUS_REBOUNDED;
                player.reboundedFlags += 1;
	    		return 'Rebounded';
	    	}
    	} else if (player.team === 2) {
    		if (me.blueFlagStatus === Constants.FLAG_STATUS_IN_BASE) {
    			me.redFlagStatus = Constants.FLAG_STATUS_IN_BASE;
                player.scoredFlags += 1;
	    		return 'scored!';
	    	}
	    	if (me.blueFlagStatus === Constants.FLAG_STATUS_FETCHED || me.blueFlagStatus === Constants.FLAG_STATUS_REBOUNDED) {
	    		me.blueFlagStatus = Constants.FLAG_STATUS_IN_BASE;
                player.restoredFlags += 1;
	    		return 'Restored';
	    	}
    	}
    }

    this.getGameName = function(key) {
    	var name = key;
    	if (me.maps.hasOwnProperty(key)) {
			name = me.maps[key]
		}
		return name;
    }
  }]);<|endoftext|>


<commit_before>import PropTypes from 'prop-types';
import React, { Fragment } from 'react';
import { Link } from 'react-router-dom';
import { LinkContainer } from 'react-router-bootstrap';
import Navbar from 'react-bootstrap/lib/Navbar';
import Nav from 'react-bootstrap/lib/Nav';
import NavItem from 'react-bootstrap/lib/NavItem';
import { faExternalLinkAlt } from '@fortawesome/free-solid-svg-icons';

import FAIcon from '../fontawesome-icon/FontAwesomeIcon';
import injectT from '../../i18n/injectT';
import { getSearchPageUrl } from '../../utils/searchUtils';

class MainNavbar extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      expanded: false,
    };
  }

  collapseItem() {
    this.setState({ expanded: false });
  }

  toggleCollapse() {
    this.setState(prevState => ({ expanded: !prevState.expanded }));
  }

  render() {
    const {
      activeLink, clearSearchResults, isAdmin, isLoggedIn, t
    } = this.props;

    return (
      <Navbar
        className="app-MainNavbar"
        expanded={this.state.expanded}
        fluid
        onToggle={() => this.toggleCollapse()}
      >
        <Navbar.Header>
          <Navbar.Toggle />
          <Navbar.Brand>
            <Link to="/">Varaamo</Link>
          </Navbar.Brand>
        </Navbar.Header>
        <Navbar.Collapse>
          <Nav activeKey={activeLink}>
            <LinkContainer to={getSearchPageUrl()}>
              <NavItem
                eventKey="search"
                onClick={() => {
                  this.collapseItem();
                  clearSearchResults();
                }}
              >
                {t('Navbar.search')}
              </NavItem>
            </LinkContainer>
            {isLoggedIn && (
              <LinkContainer to="/admin-resources">
                <NavItem eventKey="admin-resources" onClick={() => this.collapseItem()}>
                  {isAdmin ? t('Navbar.adminResources') : t('Navbar.userFavorites')}
                </NavItem>
              </LinkContainer>
            )}
            {isLoggedIn && (
              <LinkContainer to="/manage-reservations">
                <NavItem eventKey="manage-reservations" onClick={() => this.collapseItem()}>
                  {t('Navbar.manageReservations')}
                </NavItem>
              </LinkContainer>
            )}
            {isLoggedIn && (
              <LinkContainer to="/my-reservations">
                <NavItem eventKey="my-reservations" onClick={() => this.collapseItem()}>
                  {t('Navbar.userResources')}
                </NavItem>
              </LinkContainer>
            )}
            {isAdmin
              && (
                <Fragment>
                  <NavItem eventKey="adminMaintenance" href="https://api.hel.fi/respa/ra/" target="_blank">
                    {t('Navbar.adminMaintenance')}
                    <FAIcon icon={faExternalLinkAlt} />
                  </NavItem>

                  <NavItem eventKey="adminGuide" href="https://cityofhelsinki.gitbook.io/varaamo" target="_blank">
                    {t('Navbar.adminGuide')}
                    <FAIcon icon={faExternalLinkAlt} />
                  </NavItem>
                </Fragment>
              )
            }
            <LinkContainer to="/about">
              <NavItem eventKey="about" onClick={() => this.collapseItem()}>
                {t('Navbar.aboutLink')}
              </NavItem>
            </LinkContainer>
          </Nav>
        </Navbar.Collapse>
      </Navbar>
    );
  }
}

MainNavbar.propTypes = {
  activeLink: PropTypes.string.isRequired,
  clearSearchResults: PropTypes.func.isRequired,
  isAdmin: PropTypes.bool.isRequired,
  isLoggedIn: PropTypes.bool.isRequired,
  t: PropTypes.func.isRequired,
};

export default injectT(MainNavbar);
<commit_msg>Add condition that Manage Reservation is visible only to admin or staff<commit_after>import PropTypes from 'prop-types';
import React, { Fragment } from 'react';
import { Link } from 'react-router-dom';
import { LinkContainer } from 'react-router-bootstrap';
import Navbar from 'react-bootstrap/lib/Navbar';
import Nav from 'react-bootstrap/lib/Nav';
import NavItem from 'react-bootstrap/lib/NavItem';
import { faExternalLinkAlt } from '@fortawesome/free-solid-svg-icons';

import FAIcon from '../fontawesome-icon/FontAwesomeIcon';
import injectT from '../../i18n/injectT';
import { getSearchPageUrl } from '../../utils/searchUtils';

class MainNavbar extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      expanded: false,
    };
  }

  collapseItem() {
    this.setState({ expanded: false });
  }

  toggleCollapse() {
    this.setState(prevState => ({ expanded: !prevState.expanded }));
  }

  render() {
    const {
      activeLink, clearSearchResults, isAdmin, isLoggedIn, t
    } = this.props;

    return (
      <Navbar
        className="app-MainNavbar"
        expanded={this.state.expanded}
        fluid
        onToggle={() => this.toggleCollapse()}
      >
        <Navbar.Header>
          <Navbar.Toggle />
          <Navbar.Brand>
            <Link to="/">Varaamo</Link>
          </Navbar.Brand>
        </Navbar.Header>
        <Navbar.Collapse>
          <Nav activeKey={activeLink}>
            <LinkContainer to={getSearchPageUrl()}>
              <NavItem
                eventKey="search"
                onClick={() => {
                  this.collapseItem();
                  clearSearchResults();
                }}
              >
                {t('Navbar.search')}
              </NavItem>
            </LinkContainer>
            {isLoggedIn && (
              <LinkContainer to="/admin-resources">
                <NavItem eventKey="admin-resources" onClick={() => this.collapseItem()}>
                  {isAdmin ? t('Navbar.adminResources') : t('Navbar.userFavorites')}
                </NavItem>
              </LinkContainer>
            )}
            {isLoggedIn && isAdmin && (
              <LinkContainer to="/manage-reservations">
                <NavItem eventKey="manage-reservations" onClick={() => this.collapseItem()}>
                  {t('Navbar.manageReservations')}
                </NavItem>
              </LinkContainer>
            )}
            {isLoggedIn && (
              <LinkContainer to="/my-reservations">
                <NavItem eventKey="my-reservations" onClick={() => this.collapseItem()}>
                  {t('Navbar.userResources')}
                </NavItem>
              </LinkContainer>
            )}
            {isAdmin
              && (
                <Fragment>
                  <NavItem eventKey="adminMaintenance" href="https://api.hel.fi/respa/ra/" target="_blank">
                    {t('Navbar.adminMaintenance')}
                    <FAIcon icon={faExternalLinkAlt} />
                  </NavItem>

                  <NavItem eventKey="adminGuide" href="https://cityofhelsinki.gitbook.io/varaamo" target="_blank">
                    {t('Navbar.adminGuide')}
                    <FAIcon icon={faExternalLinkAlt} />
                  </NavItem>
                </Fragment>
              )
            }
            <LinkContainer to="/about">
              <NavItem eventKey="about" onClick={() => this.collapseItem()}>
                {t('Navbar.aboutLink')}
              </NavItem>
            </LinkContainer>
          </Nav>
        </Navbar.Collapse>
      </Navbar>
    );
  }
}

MainNavbar.propTypes = {
  activeLink: PropTypes.string.isRequired,
  clearSearchResults: PropTypes.func.isRequired,
  isAdmin: PropTypes.bool.isRequired,
  isLoggedIn: PropTypes.bool.isRequired,
  t: PropTypes.func.isRequired,
};

export default injectT(MainNavbar);
<|endoftext|>


<commit_before>module.exports = Shape;

/**
 * Base class for shapes.
 * @class Shape
 * @constructor
 */
function Shape(type){
    this.type = type;

    /**
     * Bounding circle radius of this shape
     * @property boundingRadius
     * @type {Number}
     */
    this.boundingRadius = 0;

    /**
     * Collision group that this shape belongs to (bit mask). See this tutorial.
     * @property collisionGroup
     * @type {Number}
     * @example
     *     // Setup bits for each available group
     *     var PLAYER = Math.pow(2,0),
     *         ENEMY =  Math.pow(2,1),
     *         GROUND = Math.pow(2,2)
     *
     *     // Put shapes into their groups
     *     player1Shape.collisionGroup = PLAYER;
     *     player2Shape.collisionGroup = PLAYER;
     *     enemyShape  .collisionGroup = ENEMY;
     *     groundShape .collisionGroup = GROUND;
     *
     *     // Assign groups that each shape collide with.
     *     // Note that the players can collide with ground and enemies, but not with other players.
     *     player1Shape.collisionMask = ENEMY | GROUND;
     *     player2Shape.collisionMask = ENEMY | GROUND;
     *     enemyShape  .collisionMask = PLAYER | GROUND;
     *     groundShape .collisionMask = PLAYER | ENEMY;
     *
     * @example
     *     // How collision check is done
     *     if(shapeA.collisionGroup & shapeB.collisionMask)!=0 && (shapeB.collisionGroup & shapeA.collisionMask)!=0){
     *         // The shapes will collide
     *     }
     */
    this.collisionGroup = 1;

    /**
     * Collision mask of this shape. See .collisionGroup.
     * @property collisionMask
     * @type {Number}
     */
    this.collisionMask =  1;
    if(type) this.updateBoundingRadius();

    /**
     * Material to use in collisions for this Shape. If this is set to null, the world will use default material properties instead.
     * @property material
     * @type {Material}
     */
    this.material = null;

    /**
     * Area of this shape.
     * @property area
     * @type {Number}
     */
    this.area = 0;

    this.updateArea();
};

Shape.CIRCLE =      1;
Shape.PARTICLE =    2;
Shape.PLANE =       4;
Shape.CONVEX =      8;
Shape.LINE =        16;
Shape.RECTANGLE =   32;
Shape.CAPSULE =     64;

/**
 * Should return the moment of inertia around the Z axis of the body given the total mass. See Wikipedia's list of moments of inertia.
 * @method computeMomentOfInertia
 * @param  {Number} mass
 * @return {Number} If the inertia is infinity or if the object simply isn't possible to rotate, return 0.
 */
Shape.prototype.computeMomentOfInertia = function(mass){
    throw new Error("Shape.computeMomentOfInertia is not implemented in this Shape...");
};

/**
 * Returns the bounding circle radius of this shape.
 * @method updateBoundingRadius
 * @return {Number}
 */
Shape.prototype.updateBoundingRadius = function(){
    throw new Error("Shape.updateBoundingRadius is not implemented in this Shape...");
};

/**
 * Update the .area property of the shape.
 * @method updateArea
 */
Shape.prototype.updateArea = function(){
    // To be implemented in all subclasses
};

/**
 * Compute the world axis-aligned bounding box (AABB) of this shape.
 * @method computeAABB
 * @param  {AABB}   out      The resulting AABB.
 * @param  {Array}  position
 * @param  {Number} angle
 */
Shape.prototype.computeAABB = function(out, position, angle){
    // To be implemented in each subclass
};
<commit_msg>added property .id to Shape<commit_after>module.exports = Shape;

/**
 * Base class for shapes.
 * @class Shape
 * @constructor
 */
function Shape(type){
    this.type = type;

    /**
     * Shape object identifier.
     * @type {Number}
     * @property id
     */
    this.id = Shape.idCounter++;

    /**
     * Bounding circle radius of this shape
     * @property boundingRadius
     * @type {Number}
     */
    this.boundingRadius = 0;

    /**
     * Collision group that this shape belongs to (bit mask). See this tutorial.
     * @property collisionGroup
     * @type {Number}
     * @example
     *     // Setup bits for each available group
     *     var PLAYER = Math.pow(2,0),
     *         ENEMY =  Math.pow(2,1),
     *         GROUND = Math.pow(2,2)
     *
     *     // Put shapes into their groups
     *     player1Shape.collisionGroup = PLAYER;
     *     player2Shape.collisionGroup = PLAYER;
     *     enemyShape  .collisionGroup = ENEMY;
     *     groundShape .collisionGroup = GROUND;
     *
     *     // Assign groups that each shape collide with.
     *     // Note that the players can collide with ground and enemies, but not with other players.
     *     player1Shape.collisionMask = ENEMY | GROUND;
     *     player2Shape.collisionMask = ENEMY | GROUND;
     *     enemyShape  .collisionMask = PLAYER | GROUND;
     *     groundShape .collisionMask = PLAYER | ENEMY;
     *
     * @example
     *     // How collision check is done
     *     if(shapeA.collisionGroup & shapeB.collisionMask)!=0 && (shapeB.collisionGroup & shapeA.collisionMask)!=0){
     *         // The shapes will collide
     *     }
     */
    this.collisionGroup = 1;

    /**
     * Collision mask of this shape. See .collisionGroup.
     * @property collisionMask
     * @type {Number}
     */
    this.collisionMask =  1;
    if(type) this.updateBoundingRadius();

    /**
     * Material to use in collisions for this Shape. If this is set to null, the world will use default material properties instead.
     * @property material
     * @type {Material}
     */
    this.material = null;

    /**
     * Area of this shape.
     * @property area
     * @type {Number}
     */
    this.area = 0;

    this.updateArea();
};

Shape.idCounter = 0;

Shape.CIRCLE =      1;
Shape.PARTICLE =    2;
Shape.PLANE =       4;
Shape.CONVEX =      8;
Shape.LINE =        16;
Shape.RECTANGLE =   32;
Shape.CAPSULE =     64;

/**
 * Should return the moment of inertia around the Z axis of the body given the total mass. See Wikipedia's list of moments of inertia.
 * @method computeMomentOfInertia
 * @param  {Number} mass
 * @return {Number} If the inertia is infinity or if the object simply isn't possible to rotate, return 0.
 */
Shape.prototype.computeMomentOfInertia = function(mass){
    throw new Error("Shape.computeMomentOfInertia is not implemented in this Shape...");
};

/**
 * Returns the bounding circle radius of this shape.
 * @method updateBoundingRadius
 * @return {Number}
 */
Shape.prototype.updateBoundingRadius = function(){
    throw new Error("Shape.updateBoundingRadius is not implemented in this Shape...");
};

/**
 * Update the .area property of the shape.
 * @method updateArea
 */
Shape.prototype.updateArea = function(){
    // To be implemented in all subclasses
};

/**
 * Compute the world axis-aligned bounding box (AABB) of this shape.
 * @method computeAABB
 * @param  {AABB}   out      The resulting AABB.
 * @param  {Array}  position
 * @param  {Number} angle
 */
Shape.prototype.computeAABB = function(out, position, angle){
    // To be implemented in each subclass
};
<|endoftext|>


<commit_before>import ..utils;

/**
 * Shape Base Class
 */
exports = Class(function () {
  this.name = "Shape";

  this.init = function (opts) {
    this.x = opts.x || 0;
    this.y = opts.y || 0;

    utils.addReadOnlyObject(this, 'bounds', {
      minX: function () { return this.x; },
      minY: function () { return this.y; },
      maxX: function () { return this.x; },
      maxY: function () { return this.y; }
    });

    utils.addReadOnlyObject(this, 'center', {
      x: function () { return this.x; },
      y: function () { return this.y; }
    });
  };

  this.getRandomPoint = function () {
    return {
      x: this.x,
      y: this.y
    };
  };
});

/*

Shape Interface
- name: i.e. "Circle" or "Rect"
- x: x-coordinate
- y: y-coordinate
- bounds: read-only object w minX, minY, maxX, maxY properties
- center: read-only object w x and y properties
- getRandomPoint: returns a random point within the shape

Shape Interface (Maybe TODO)
- translate
- rotate
- scale
- collidesWith: could look up physics fns based on shape names

*/
<commit_msg>updated shapes 'maybe TODO' API<commit_after>import ..utils;

/**
 * Shape Base Class
 */
exports = Class(function () {
  this.name = "Shape";

  this.init = function (opts) {
    this.x = opts.x || 0;
    this.y = opts.y || 0;

    utils.addReadOnlyObject(this, 'bounds', {
      minX: function () { return this.x; },
      minY: function () { return this.y; },
      maxX: function () { return this.x; },
      maxY: function () { return this.y; }
    });

    utils.addReadOnlyObject(this, 'center', {
      x: function () { return this.x; },
      y: function () { return this.y; }
    });
  };

  this.getRandomPoint = function () {
    return {
      x: this.x,
      y: this.y
    };
  };
});

/*

Shape Interface
- name: i.e. "Circle" or "Rect"
- x: x-coordinate
- y: y-coordinate
- bounds: read-only object w minX, minY, maxX, maxY properties
- center: read-only object w x and y properties
- getRandomPoint: returns a random point within the shape

Shape Interface (Maybe TODO)
- translate
- rotate
- scale

*/
<|endoftext|>


<commit_before>"use strict";

var smallModifiers = ['kon', 'lili', 'mute', 'sin'],
    narrowModifiers = ['wan', 'tu', 'anu', 'en', 'kin'];

function getSizeOf(token) {
    if (smallModifiers.indexOf(token) > -1) {
        return [1, 0.5];
    } else if (narrowModifiers.indexOf(token) > -1) {
        return [0.5, 1];
    } else {
        return [1, 1];
    }
}

var options = [], hash = {};

function go(units, state, iterator) {
    console.log(state, iterator);
    var newSize, newState, newForbidden, i, j;

    if (!state) {
        var singleSize = getSizeOf(units[0]);
        newState = {
            units: [{token: units[0], size: singleSize, position: [0, 0]}],
            size: singleSize,
            forbidden: [JSON.stringify(singleSize)]
        };

        for (j = 1; j < units.length; j++) {
            go(units, newState, {goesDown: false, index: 1, length: j});
            go(units, newState, {goesDown: true, index: 1, length: j});
        }
        return;
    }

    var goesDown = iterator.goesDown,
        index = iterator.index,
        length = iterator.length;

    newState = JSON.parse(JSON.stringify(state));
    newSize = newState.size;
    newForbidden = newState.forbidden;

    var prevSize = getSizeOf(units[index]),
        glyphPosition = [!goesDown ? state.size[0] : 0, goesDown ? state.size[1] : 0];

    console.log(glyphPosition);

    var sizeSum = [0, 0], addSize;
    // determine size sum
    for (i = index; i < index + length; i++) {
        addSize = getSizeOf(units[i]);
        if ((goesDown && addSize[1] !== prevSize[1]) ||
            (!goesDown && addSize[0] !== prevSize[0])) {
            return;
        }
        sizeSum = [sizeSum[0] + addSize[0], sizeSum[1] + addSize[1]];
    }

    var actualAdded = 0;
    // now add the glyphs one by one
    for (i = index; i < index + length; i++) {
        console.log('i: ', i);
        var glyphSize = [], addX = 0, addY = 0;
        addSize = getSizeOf(units[i]);

        if (goesDown) {
            addY = addSize[1] * state.size[0] / sizeSum[0];
            glyphSize = [addSize[0] * addY / addSize[1], addY];

            if (i === index) {
                newSize[1] += addY;
            }
            if (newForbidden.indexOf(JSON.stringify(glyphPosition)) > -1) {
                return;
            }
        } else {
            addX = addSize[0] * state.size[1] / sizeSum[1];
            glyphSize = [addX, addSize[1] * addX / addSize[0]];

            if (i === index) {
                newSize[0] += addX;
            }

            console.log(addX, glyphSize, newSize, goesDown, state.size);
        }

        prevSize = addSize;
        console.log(units[i], glyphPosition);
        newState.units.push({token: units[i], size: glyphSize, position: glyphPosition});
        actualAdded++;

        // update glyph position
        glyphPosition = [glyphPosition[0] + (goesDown ? glyphSize[0] : 0),
            glyphPosition[1] + (!goesDown ? glyphSize[1] : 0)];

        console.log('update:' + glyphPosition);

        newForbidden.push(JSON.stringify([glyphPosition[0] + (!goesDown ? glyphSize[0] : 0), glyphPosition[1] + (goesDown ? glyphSize[1] : 0)]));
    }

    if (index + actualAdded === units.length) {
        var newOption = {
            state: newState,
            size: newSize,
            ratio: newSize[0] / newSize[1],
            normedRatio: newSize[0] / newSize[1] < 1 ? newSize[0] / newSize[1] : newSize[1] / newSize[0],
            surface: newSize[0] * newSize[1]
        };
        console.log('ADD OPTION ', newOption);

        newOption = normalizeOption(JSON.stringify(newOption));

        if (!hash[JSON.stringify(newOption)]) {
            options.push(newOption);
            hash[JSON.stringify(newOption)] = newOption;
        }
        return;
    }

    for (j = 1; j < units.length - index; j++) {
        go(units, newState, {goesDown: false, index: index + actualAdded, length: j});
        go(units, newState, {goesDown: true, index: index + actualAdded, length: j});
    }
}

function convertNounPhrase(tokens) {
    go(tokens);

    options.sort(function (a, b) {
        return a.surface - b.surface;
        //return b.normedRatio - a.normedRatio;
    });

    options.forEach(function (option) {
        renderOption(option);
    });
}

function renderOption(option) {
    var container = document.createElement('div');
    container.classList.add('toki-nounphrase');
    container.style.width = option.size[0] + 'em';
    container.style.height = option.size[1] + 'em';

    option.state.units.forEach(function (glyph) {
        var element = document.createElement('div');
        element.style.width = glyph.size[0] + 'em';
        element.style.height = glyph.size[1] + 'em';
        element.style.left = glyph.position[0] + 'em';
        element.style.top = glyph.position[1] + 'em';
        element.setAttribute('data-toki-word', glyph.token);

        container.appendChild(element);
    });
    document.getElementById('sitelen').appendChild(container);
}

function normalizeOption(option) {
    option = JSON.parse(option);

    var minSize = 1;
    option.state.units.forEach(function (glyph) {
        if (glyph.size[0] < minSize) {
            minSize = glyph.size[0];
        }
        if (glyph.size[1] < minSize) {
            minSize = glyph.size[1];
        }
    });

    option.size = [option.size[0] / minSize, option.size[1] / minSize];
    option.surface /= minSize * minSize;
    option.state.units.forEach(function (glyph) {
        glyph.size[0] /= minSize;
        glyph.size[1] /= minSize;
        glyph.position[0] /= minSize;
        glyph.position[1] /= minSize;
    });

    return option;
}

var tokens = ['jan', 'tu', 'utala', 'mute','pona', 'wan', 'lili', 'wan'];
//var tokens = ['jan', 'utala', 'pona', 'mi', 'wan'];
//var tokens = ['jan', 'lili', 'pona'];
//tokens = 'kili suli pona mi'.split(' ');

setTimeout(function () {
    convertNounPhrase(tokens);
}, 500);

//function convertToInstructions(structuredSentence) {
//
//    var instructions = [],
//        size;
//
//    structuredSentence.forEach(function (part) {
//
//        switch (part.part) {
//            case 'subject':
//            case 'verbPhrase':
//            case 'directObject':
//                instructions.push.apply(instructions, convertNounPhrase(part));
//                break;
//            case 'punctuation':
//                instructions.push({rule: 'addPunctuation', glyph: part.token === '.' ? 'period' : '', size: 'wide'});
//                break;
//            default:
//                console.log('ERR: unknown part');
//                break;
//        }
//    });
//
//    // determine container sizes
//    for (var i = 0; i < instructions.length; i++) {
//        if (instructions[i].rule === 'openContainer') {
//            var closure = 0, regularGlyphs = 0, narrowGlyphs = 0;
//            for (var j = i; j < instructions.length; j++) {
//                switch (instructions[j].rule) {
//                    case 'openContainer':
//                        closure++;
//                        break;
//                    case 'closeContainer':
//                        closure--;
//                        if (closure === 0) {
//                            // round narrow glyphs
//                            var roundglyphs = Math.round(regularGlyphs + narrowGlyphs / 2);
//                            // add metadata to the container
//                            instructions[i].size = roundglyphs === 1 ? 'regular' :
//                                roundglyphs > 3 || (roundglyphs === 3 && narrowGlyphs === 1) ? 'double' : 'wide';
//                            instructions[i].children = roundglyphs;
//                            closure = -1;
//                        }
//                        break;
//                    case 'addGlyph':
//                        // narrow glyphs only count as half
//                        if (narrowModifiers.indexOf(instructions[j].glyph) > -1) {
//                            narrowGlyphs++;
//                        } else {
//                            regularGlyphs++;
//                        }
//                        break;
//                }
//                if (closure === -1) {
//                    break;
//                }
//            }
//        }
//    }
//    return instructions;
//}

<commit_msg>Limiting number of solutions by discarding oversized solutions.<commit_after>"use strict";

var smallModifiers = ['kon', 'lili', 'mute', 'sin'],
    narrowModifiers = ['wan', 'tu', 'anu', 'en', 'kin'];

function getSizeOf(token) {
    if (smallModifiers.indexOf(token) > -1) {
        return [1, 0.5];
    } else if (narrowModifiers.indexOf(token) > -1) {
        return [0.5, 1];
    } else {
        return [1, 1];
    }
}

var options = [], hash = {}, minSurface = 1e6;

function go(units, state, iterator) {
    console.log(state, iterator);
    var newSize, newState, newForbidden, i, j;

    if (!state) {
        var singleSize = getSizeOf(units[0]);
        newState = {
            units: [{token: units[0], size: singleSize, position: [0, 0]}],
            size: singleSize,
            forbidden: [JSON.stringify(singleSize)]
        };

        for (j = 1; j < units.length; j++) {
            go(units, newState, {goesDown: false, index: 1, length: j});
            go(units, newState, {goesDown: true, index: 1, length: j});
        }
        return;
    }

    var goesDown = iterator.goesDown,
        index = iterator.index,
        length = iterator.length;

    newState = JSON.parse(JSON.stringify(state));
    newSize = newState.size;
    newForbidden = newState.forbidden;

    var prevSize = getSizeOf(units[index]),
        glyphPosition = [!goesDown ? state.size[0] : 0, goesDown ? state.size[1] : 0];

    console.log(glyphPosition);

    var sizeSum = [0, 0], addSize;
    // determine size sum
    for (i = index; i < index + length; i++) {
        addSize = getSizeOf(units[i]);
        if ((goesDown && addSize[1] !== prevSize[1]) ||
            (!goesDown && addSize[0] !== prevSize[0])) {
            return;
        }
        sizeSum = [sizeSum[0] + addSize[0], sizeSum[1] + addSize[1]];
    }

    var actualAdded = 0;
    // now add the glyphs one by one
    for (i = index; i < index + length; i++) {
        console.log('i: ', i);
        var glyphSize = [], addX = 0, addY = 0;
        addSize = getSizeOf(units[i]);

        if (goesDown) {
            addY = addSize[1] * state.size[0] / sizeSum[0];
            glyphSize = [addSize[0] * addY / addSize[1], addY];

            if (i === index) {
                newSize[1] += addY;
            }
            if (newForbidden.indexOf(JSON.stringify(glyphPosition)) > -1) {
                return;
            }
        } else {
            addX = addSize[0] * state.size[1] / sizeSum[1];
            glyphSize = [addX, addSize[1] * addX / addSize[0]];

            if (i === index) {
                newSize[0] += addX;
            }

            console.log(addX, glyphSize, newSize, goesDown, state.size);
        }

        prevSize = addSize;
        console.log(units[i], glyphPosition);
        newState.units.push({token: units[i], size: glyphSize, position: glyphPosition});
        actualAdded++;

        // update glyph position
        glyphPosition = [glyphPosition[0] + (goesDown ? glyphSize[0] : 0),
            glyphPosition[1] + (!goesDown ? glyphSize[1] : 0)];

        console.log('update:' + glyphPosition);

        newForbidden.push(JSON.stringify([glyphPosition[0] + (!goesDown ? glyphSize[0] : 0), glyphPosition[1] + (goesDown ? glyphSize[1] : 0)]));
    }

    if (index + actualAdded === units.length) {
        var newOption = {
            state: newState,
            size: newSize,
            ratio: newSize[0] / newSize[1],
            normedRatio: newSize[0] / newSize[1] < 1 ? newSize[0] / newSize[1] : newSize[1] / newSize[0],
            surface: newSize[0] * newSize[1]
        };
        console.log('ADD OPTION ', newOption);

        newOption = normalizeOption(JSON.stringify(newOption));

        minSurface = Math.min(minSurface, newOption.surface);

        // surface can't be 3 times larger than the optimum
        if (!hash[JSON.stringify(newOption)] && newOption.surface / minSurface < 3) {
            options.push(newOption);
            hash[JSON.stringify(newOption)] = newOption;
        }
        return;
    }

    for (j = 1; j < units.length - index; j++) {
        go(units, newState, {goesDown: false, index: index + actualAdded, length: j});
        go(units, newState, {goesDown: true, index: index + actualAdded, length: j});
    }
}

function convertNounPhrase(tokens) {
    go(tokens);

    options.sort(function (a, b) {
        return a.surface - b.surface;
        //return b.normedRatio - a.normedRatio;
    });

    options.forEach(function (option) {
        renderOption(option);
    });
}

function renderOption(option) {
    var container = document.createElement('div');
    container.classList.add('toki-nounphrase');
    container.style.width = option.size[0] + 'em';
    container.style.height = option.size[1] + 'em';

    option.state.units.forEach(function (glyph) {
        var element = document.createElement('div');
        element.style.width = glyph.size[0] + 'em';
        element.style.height = glyph.size[1] + 'em';
        element.style.left = glyph.position[0] + 'em';
        element.style.top = glyph.position[1] + 'em';
        element.setAttribute('data-toki-word', glyph.token);

        container.appendChild(element);
    });
    document.getElementById('sitelen').appendChild(container);
}

function normalizeOption(option) {
    option = JSON.parse(option);

    var minSize = 1;
    option.state.units.forEach(function (glyph) {
        if (glyph.size[0] < minSize) {
            minSize = glyph.size[0];
        }
        if (glyph.size[1] < minSize) {
            minSize = glyph.size[1];
        }
    });

    option.size = [option.size[0] / minSize, option.size[1] / minSize];
    option.surface /= minSize * minSize;
    option.state.units.forEach(function (glyph) {
        glyph.size[0] /= minSize;
        glyph.size[1] /= minSize;
        glyph.position[0] /= minSize;
        glyph.position[1] /= minSize;
    });

    return option;
}

var tokens = ['jan', 'tu', 'utala', 'mute', 'pona', 'wan', 'lili', 'wan'];
//var tokens = ['jan', 'utala', 'pona', 'mi', 'wan'];
//var tokens = ['jan', 'lili', 'pona'];
//tokens = 'kili suli pona mi'.split(' ');

setTimeout(function () {
    convertNounPhrase(tokens);
}, 500);

//function convertToInstructions(structuredSentence) {
//
//    var instructions = [],
//        size;
//
//    structuredSentence.forEach(function (part) {
//
//        switch (part.part) {
//            case 'subject':
//            case 'verbPhrase':
//            case 'directObject':
//                instructions.push.apply(instructions, convertNounPhrase(part));
//                break;
//            case 'punctuation':
//                instructions.push({rule: 'addPunctuation', glyph: part.token === '.' ? 'period' : '', size: 'wide'});
//                break;
//            default:
//                console.log('ERR: unknown part');
//                break;
//        }
//    });
//
//    // determine container sizes
//    for (var i = 0; i < instructions.length; i++) {
//        if (instructions[i].rule === 'openContainer') {
//            var closure = 0, regularGlyphs = 0, narrowGlyphs = 0;
//            for (var j = i; j < instructions.length; j++) {
//                switch (instructions[j].rule) {
//                    case 'openContainer':
//                        closure++;
//                        break;
//                    case 'closeContainer':
//                        closure--;
//                        if (closure === 0) {
//                            // round narrow glyphs
//                            var roundglyphs = Math.round(regularGlyphs + narrowGlyphs / 2);
//                            // add metadata to the container
//                            instructions[i].size = roundglyphs === 1 ? 'regular' :
//                                roundglyphs > 3 || (roundglyphs === 3 && narrowGlyphs === 1) ? 'double' : 'wide';
//                            instructions[i].children = roundglyphs;
//                            closure = -1;
//                        }
//                        break;
//                    case 'addGlyph':
//                        // narrow glyphs only count as half
//                        if (narrowModifiers.indexOf(instructions[j].glyph) > -1) {
//                            narrowGlyphs++;
//                        } else {
//                            regularGlyphs++;
//                        }
//                        break;
//                }
//                if (closure === -1) {
//                    break;
//                }
//            }
//        }
//    }
//    return instructions;
//}

<|endoftext|>


<commit_before>function Arena() {}

Arena.prototype.create = function() {
    console.log('Arena');
    waiting = this.add.bitmapText(300, 200, 'carrier_command', 'WAITING FOR PLAYERS 1', 10);
    this.input.onDown.add(this.onInputDown, this);
    player1 = false;
    player2 = false;

  //  this.game.state.start('fight');
};

Arena.prototype.update = function() {
if(player1 == true)
{
waiting.setText('WAITING FOR PLAYERS 2');
if(player2 == true)
{
waiting.setText('READY');

}
}

};

Arena.prototype.onInputDown = function() {
    //this.game.state.start('fight');
};

module.exports = Arena;
<commit_msg>je sais pas<commit_after>function Arena() {}

Arena.prototype.create = function() {
    console.log('Arena');
    waiting = this.add.bitmapText(300, 200, 'carrier_command', 'WAITING FOR PLAYERS 1', 10);
    this.input.onDown.add(this.onInputDown, this);
    player1 = false;
    player2 = false;

  //  this.game.state.start('fight');
};

Arena.prototype.update = function() {
if(player1 == true)
{
waiting.setText('WAITING FOR PLAYERS 2');
if(player2 == true)
{
waiting.setText('READY');
this.game.state.start('fight');
}
}

};

Arena.prototype.onInputDown = function() {
    //this.game.state.start('fight');
};

module.exports = Arena;
<|endoftext|>


<commit_before>import { observable } from "mobx";
import update from "immutability-helper";
import shortid from "shortid";
import { findIndex } from "lodash";

import { groupTypes, physicalTypes, entitySchemas } from "../constants";
import { compactPuzzle, hasWon } from "../functions";

export const getLevelPlayStore = (initialState = {}) => {
  const {
    levelStart = [],
    moves = []
  } = initialState;

  const state = observable({
    levelStart,
    moves,

    get entities() {
      const result = state.moves.reduce(
        (levelAtMove, nextMove) => {
          return Object.entries(nextMove).reduce(
            (levelAtSubMove, [id, position]) => {
              const indexToMove = findIndex(levelAtSubMove, { id });

              if (indexToMove === -1) {
                return levelAtSubMove;
              }

              const newPos = {
                ...levelAtSubMove[indexToMove].position,
                ...nextMove[id]
              };

              return update(levelAtSubMove, {
                [indexToMove]: {
                  position: { $set: newPos }
                }
              });
            },
            levelAtMove
          );
        },
        state.levelStart
      );
      return result;
    },

    get playerIndex() {
      return state.entities.findIndex(ent => ent.isPlayer);
    },

    get player() {
      return state.entities[state.playerIndex];
    },

    get moveCount() {
      return state.moves.length;
    }
  });

  const tryMove = (axis, step) => {
    if (!state.player) {
      return;
    }

    if (hasWon(state.entities)) {
      return;
    }

    const playerPos = state.player.position;
    const positionToTry = {
      ...playerPos,
      [axis]: playerPos[axis] + step
    };

    const { entities } = state;
    const entityThereIndex = entities.findIndex(
      ent =>
        ent.physicalType &&
        ent.position.x === positionToTry.x &&
        ent.position.y === positionToTry.y
    );
    const entityThere = entities[entityThereIndex];

    if (entityThere) {
      if (entityThere.physicalType === physicalTypes.obstacle) {
        return;
      }

      if (entityThere.physicalType === physicalTypes.pushable) {
        const nextPositionOver = {
          ...playerPos,
          [axis]: playerPos[axis] + step * 2
        };
        const nextEntityOver = entities.find(
          ent =>
            ent.physicalType &&
            ent.position.x === nextPositionOver.x &&
            ent.position.y === nextPositionOver.y
        );

        if (nextEntityOver && nextEntityOver.physicalType) {
          return;
        }

        state.moves.push({
          [entityThere.id]: {
            ...entityThere.position,
            [axis]: entityThere.position[axis] + step
          },
          [state.player.id]: {
            ...playerPos,
            [axis]: playerPos[axis] + step
          }
        });
        return;
      }
    }

    state.moves.push({
      [state.player.id]: {
        ...playerPos,
        [axis]: playerPos[axis] + step
      }
    });
  };

  return {
    state,

    tryMoveLeft: () => tryMove("x", -1),
    tryMoveDown: () => tryMove("y", +1),
    tryMoveUp: () => tryMove("y", -1),
    tryMoveRight: () => tryMove("x", +1),

    undo() {
      if (state.moves.length) {
        state.moves.pop();
      }
    },

    reset() {
      state.moves = [];
    }
  };
};

export const getLevelRecordStore = (initialState = {}) => {
  const {
    attemptingLoad = true,
    records = []
  } = initialState;

  const state = observable({
    attemptingLoad,
    records
  });

  const loadRecords = recordsToLoad => {
    state.records = recordsToLoad;
    state.attemptingLoad = false;
  };

  const finishLoad = () => {
    state.attemptingLoad = false;
  };

  return { state, loadRecords, finishLoad };
};

export const getMenuStore = (initial = {}) => {
  const {
    initialState = {},
    levelRecordStore = getLevelRecordStore(),
    goBack = o => o
  } = initial;

  const state = observable({
    highlightedLevelId: -1,
    ...initialState
  });

  const selectLevel = id => {
    state.highlightedLevelId = id === state.highlightedLevelId ? -1 : id;
  };

  return { state, levelRecordStore, selectLevel, goBack };
};

export const getEditorStore = (initial = {}) => {
  const {
    initialState = {},
    goBack = o => o,
    reload = o => o,
    loadLevelRecord = o => o
  } = initial;

  const state = observable({
    level: [],
    submission: false,
    bound: 20,
    editingPos: { x: 9, y: 9 },
    ...initialState
  });

  const clearAtPos = ({ x, y }) => {
    state.level = state.level.filter(
      ent => ent.position.x !== x || ent.position.y !== y
    );
  };

  const bindPlace = (...groups) =>
    e => {
      if (e) {
        e.preventDefault();
      }

      clearAtPos(state.editingPos);

      for (const group of groups) {
        const action = entitySchemas[group].group === groupTypes.target
          ? "unshift"
          : "push";
        state.level[action]({
          id: shortid.generate(),
          ...entitySchemas[group],
          position: { ...state.editingPos }
        });
      }
    };

  const placeSpace = bindPlace();
  const placeWall = bindPlace("wall");
  const placeBox = bindPlace("box");
  const placeTarget = bindPlace("target");
  const placeBoxTarget = bindPlace("target", "box");

  const setFromClick = e => { console.log('u wot ', e)
    const x = Math.floor(
      state.bound * ((e.pageX - e.target.offsetLeft) / e.target.offsetWidth)
    );
    const y = Math.floor(
      state.bound * ((e.pageY - e.target.offsetTop) / e.target.offsetHeight)
    );
    state.editingPos = { x, y };
  };

  const setFromPress = e => {
    e.stopImmediatePropagation();
    console.log(e);
    const entsAtPos = state.level.filter(
      ent =>
        !ent.isPlayer &&
        ent.position.x === state.editingPos.x &&
        ent.position.y === state.editingPos.y
    );

    if (!entsAtPos.length) {
      // empty space
      placeWall();
    } else if (entsAtPos.length > 1) {
      // box and target most likely
      placeSpace();
    } else {
      switch (entsAtPos[0].group) {
        case groupTypes.wall:
          placeBox();
          break;
        case groupTypes.box:
          placeTarget();
          break;
        case groupTypes.target:
          placeBoxTarget();
          break;
        default:
      }
    }
    const savedPos = { ...state.editingPos };
    state.editingPos = { x: 0, y: 0 };
    //state.editingPos = savedPos;
  };

  const placePlayer = e => {
    if (e) {
      e.preventDefault();
    }
    state.level = state.level.filter(ent => ent.group !== groupTypes.player);
    state.level.push({
      id: shortid.generate(),
      ...entitySchemas.player,
      position: { ...state.editingPos }
    });
  };

  const setPlayer = e => {
    console.log(e);
    setFromClick(e.touches[0]);
    placePlayer();
  };

  const submit = captchaObj => {
    state.submission = {
      ...captchaObj,
      doc: {
        id: state.id || shortid.generate(),
        level: compactPuzzle(state.level)
      }
    };
  };

  const closeSubmit = () => {
    state.submission = false;
  };

  const bindMove = (axis, dir) =>
    e => {
      if (
        e && typeof e === "object" && typeof e.preventDefault === "function"
      ) {
        e.preventDefault();
      }

      const nextAxisPos = state.editingPos[axis] + dir;
      state.editingPos[axis] = nextAxisPos > state.bound - 1
        ? 0
        : nextAxisPos < 0 ? state.bound - 1 : nextAxisPos;
    };

  return {
    state,

    setFromPress,
    setFromClick,

    submit,
    closeSubmit,
    goBack,
    reload,
    loadLevelRecord,

    moveLeft: bindMove("x", -1),
    moveDown: bindMove("y", +1),
    moveUp: bindMove("y", -1),
    moveRight: bindMove("x", +1),

    placePlayer,
    setPlayer,

    placeSpace,
    placeWall,
    placeBox,
    placeTarget,
    placeBoxTarget
  };
};

export const getGameStore = (initial = {}) => {
  const {
    initialState,
    levelRecordStore = getLevelRecordStore(),
    menuStore = getMenuStore({ levelRecordStore }),
    levelPlayStore = getLevelPlayStore(),
    editorStore = getEditorStore({
      reload: id => {
        levelRecordStore.state.attemptingLoad = true;
        menuStore.loadLevel(id);
      },
      loadLevelRecord(record) {
        const { records } = levelRecordStore.state;
        const levelIndex = findIndex(records, { id: record.id });
        if (levelIndex === -1) {
          records.push(record);
        } else {
          records[levelIndex] = record;
        }
        menuStore.loadLevel(record.id);
      }
    })
  } = initial;

  const state = observable({
    currentView: "MENU",
    ...initialState
  });

  editorStore.goBack = o => {
    state.currentView = editorStore.state.id ? "PLAY" : "MENU";
  };

  menuStore.loadLevel = id => {
    id = id == null ? menuStore.state.highlightedLevelId : id;
    const recordToLoad = levelRecordStore.state.records.find(r => r.id === id);

    if (!recordToLoad) {
      menuStore.state.highlightedLevelId = null;
      state.currentView = "EDITOR";
      return;
    }

    levelPlayStore.state.moves = [];
    levelPlayStore.state.levelStart = recordToLoad.level;
    state.currentView = "PLAY";
    menuStore.state.highlightedLevelId = id;
  };

  menuStore.gotoCreateLevel = o => {
    editorStore.state.id = null;
    editorStore.state.level = [];
    menuStore.state.highlightedLevelId = null;
    state.currentView = "EDITOR";
  };

  levelPlayStore.goBack = o => {
    state.currentView = "MENU";
  };

  levelPlayStore.gotoEditor = () => {
    editorStore.state.id = menuStore.state.highlightedLevelId; // normalize?
    editorStore.state.level = levelPlayStore.state.levelStart;
    state.currentView = "EDITOR";
  };

  return {
    state,
    menuStore,
    levelRecordStore,
    levelPlayStore,
    editorStore
  };
};
<commit_msg>chore: cleanup<commit_after>import { observable } from "mobx";
import update from "immutability-helper";
import shortid from "shortid";
import { findIndex } from "lodash";

import { groupTypes, physicalTypes, entitySchemas } from "../constants";
import { compactPuzzle, hasWon } from "../functions";

export const getLevelPlayStore = (initialState = {}) => {
  const {
    levelStart = [],
    moves = []
  } = initialState;

  const state = observable({
    levelStart,
    moves,

    get entities() {
      const result = state.moves.reduce(
        (levelAtMove, nextMove) => {
          return Object.entries(nextMove).reduce(
            (levelAtSubMove, [id, position]) => {
              const indexToMove = findIndex(levelAtSubMove, { id });

              if (indexToMove === -1) {
                return levelAtSubMove;
              }

              const newPos = {
                ...levelAtSubMove[indexToMove].position,
                ...nextMove[id]
              };

              return update(levelAtSubMove, {
                [indexToMove]: {
                  position: { $set: newPos }
                }
              });
            },
            levelAtMove
          );
        },
        state.levelStart
      );
      return result;
    },

    get playerIndex() {
      return state.entities.findIndex(ent => ent.isPlayer);
    },

    get player() {
      return state.entities[state.playerIndex];
    },

    get moveCount() {
      return state.moves.length;
    }
  });

  const tryMove = (axis, step) => {
    if (!state.player) {
      return;
    }

    if (hasWon(state.entities)) {
      return;
    }

    const playerPos = state.player.position;
    const positionToTry = {
      ...playerPos,
      [axis]: playerPos[axis] + step
    };

    const { entities } = state;
    const entityThereIndex = entities.findIndex(
      ent =>
        ent.physicalType &&
        ent.position.x === positionToTry.x &&
        ent.position.y === positionToTry.y
    );
    const entityThere = entities[entityThereIndex];

    if (entityThere) {
      if (entityThere.physicalType === physicalTypes.obstacle) {
        return;
      }

      if (entityThere.physicalType === physicalTypes.pushable) {
        const nextPositionOver = {
          ...playerPos,
          [axis]: playerPos[axis] + step * 2
        };
        const nextEntityOver = entities.find(
          ent =>
            ent.physicalType &&
            ent.position.x === nextPositionOver.x &&
            ent.position.y === nextPositionOver.y
        );

        if (nextEntityOver && nextEntityOver.physicalType) {
          return;
        }

        state.moves.push({
          [entityThere.id]: {
            ...entityThere.position,
            [axis]: entityThere.position[axis] + step
          },
          [state.player.id]: {
            ...playerPos,
            [axis]: playerPos[axis] + step
          }
        });
        return;
      }
    }

    state.moves.push({
      [state.player.id]: {
        ...playerPos,
        [axis]: playerPos[axis] + step
      }
    });
  };

  return {
    state,

    tryMoveLeft: () => tryMove("x", -1),
    tryMoveDown: () => tryMove("y", +1),
    tryMoveUp: () => tryMove("y", -1),
    tryMoveRight: () => tryMove("x", +1),

    undo() {
      if (state.moves.length) {
        state.moves.pop();
      }
    },

    reset() {
      state.moves = [];
    }
  };
};

export const getLevelRecordStore = (initialState = {}) => {
  const {
    attemptingLoad = true,
    records = []
  } = initialState;

  const state = observable({
    attemptingLoad,
    records
  });

  const loadRecords = recordsToLoad => {
    state.records = recordsToLoad;
    state.attemptingLoad = false;
  };

  const finishLoad = () => {
    state.attemptingLoad = false;
  };

  return { state, loadRecords, finishLoad };
};

export const getMenuStore = (initial = {}) => {
  const {
    initialState = {},
    levelRecordStore = getLevelRecordStore(),
    goBack = o => o
  } = initial;

  const state = observable({
    highlightedLevelId: -1,
    ...initialState
  });

  const selectLevel = id => {
    state.highlightedLevelId = id === state.highlightedLevelId ? -1 : id;
  };

  return { state, levelRecordStore, selectLevel, goBack };
};

export const getEditorStore = (initial = {}) => {
  const {
    initialState = {},
    goBack = o => o,
    reload = o => o,
    loadLevelRecord = o => o
  } = initial;

  const state = observable({
    level: [],
    submission: false,
    bound: 20,
    editingPos: { x: 9, y: 9 },
    ...initialState
  });

  const clearAtPos = ({ x, y }) => {
    state.level = state.level.filter(
      ent => ent.position.x !== x || ent.position.y !== y
    );
  };

  const bindPlace = (...groups) =>
    e => {
      if (e) {
        e.preventDefault();
      }

      clearAtPos(state.editingPos);

      for (const group of groups) {
        const action = entitySchemas[group].group === groupTypes.target
          ? "unshift"
          : "push";
        state.level[action]({
          id: shortid.generate(),
          ...entitySchemas[group],
          position: { ...state.editingPos }
        });
      }
    };

  const placeSpace = bindPlace();
  const placeWall = bindPlace("wall");
  const placeBox = bindPlace("box");
  const placeTarget = bindPlace("target");
  const placeBoxTarget = bindPlace("target", "box");

  const setFromClick = e => { console.log('u wot ', e)
    const x = Math.floor(
      state.bound * ((e.pageX - e.target.offsetLeft) / e.target.offsetWidth)
    );
    const y = Math.floor(
      state.bound * ((e.pageY - e.target.offsetTop) / e.target.offsetHeight)
    );
    state.editingPos = { x, y };
  };

  const setFromPress = e => {
    e.stopImmediatePropagation();

    const entsAtPos = state.level.filter(
      ent =>
        !ent.isPlayer &&
        ent.position.x === state.editingPos.x &&
        ent.position.y === state.editingPos.y
    );

    if (!entsAtPos.length) {
      // empty space
      placeWall();
    } else if (entsAtPos.length > 1) {
      // box and target most likely
      placeSpace();
    } else {
      switch (entsAtPos[0].group) {
        case groupTypes.wall:
          placeBox();
          break;
        case groupTypes.box:
          placeTarget();
          break;
        case groupTypes.target:
          placeBoxTarget();
          break;
        default:
      }
    }
  };

  const placePlayer = e => {
    if (e) {
      e.preventDefault();
    }
    state.level = state.level.filter(ent => ent.group !== groupTypes.player);
    state.level.push({
      id: shortid.generate(),
      ...entitySchemas.player,
      position: { ...state.editingPos }
    });
  };

  const setPlayer = e => {
    console.log(e);
    setFromClick(e.touches[0]);
    placePlayer();
  };

  const submit = captchaObj => {
    state.submission = {
      ...captchaObj,
      doc: {
        id: state.id || shortid.generate(),
        level: compactPuzzle(state.level)
      }
    };
  };

  const closeSubmit = () => {
    state.submission = false;
  };

  const bindMove = (axis, dir) =>
    e => {
      if (
        e && typeof e === "object" && typeof e.preventDefault === "function"
      ) {
        e.preventDefault();
      }

      const nextAxisPos = state.editingPos[axis] + dir;
      state.editingPos[axis] = nextAxisPos > state.bound - 1
        ? 0
        : nextAxisPos < 0 ? state.bound - 1 : nextAxisPos;
    };

  return {
    state,

    setFromPress,
    setFromClick,

    submit,
    closeSubmit,
    goBack,
    reload,
    loadLevelRecord,

    moveLeft: bindMove("x", -1),
    moveDown: bindMove("y", +1),
    moveUp: bindMove("y", -1),
    moveRight: bindMove("x", +1),

    placePlayer,
    setPlayer,

    placeSpace,
    placeWall,
    placeBox,
    placeTarget,
    placeBoxTarget
  };
};

export const getGameStore = (initial = {}) => {
  const {
    initialState,
    levelRecordStore = getLevelRecordStore(),
    menuStore = getMenuStore({ levelRecordStore }),
    levelPlayStore = getLevelPlayStore(),
    editorStore = getEditorStore({
      reload: id => {
        levelRecordStore.state.attemptingLoad = true;
        menuStore.loadLevel(id);
      },
      loadLevelRecord(record) {
        const { records } = levelRecordStore.state;
        const levelIndex = findIndex(records, { id: record.id });
        if (levelIndex === -1) {
          records.push(record);
        } else {
          records[levelIndex] = record;
        }
        menuStore.loadLevel(record.id);
      }
    })
  } = initial;

  const state = observable({
    currentView: "MENU",
    ...initialState
  });

  editorStore.goBack = o => {
    state.currentView = editorStore.state.id ? "PLAY" : "MENU";
  };

  menuStore.loadLevel = id => {
    id = id == null ? menuStore.state.highlightedLevelId : id;
    const recordToLoad = levelRecordStore.state.records.find(r => r.id === id);

    if (!recordToLoad) {
      menuStore.state.highlightedLevelId = null;
      state.currentView = "EDITOR";
      return;
    }

    levelPlayStore.state.moves = [];
    levelPlayStore.state.levelStart = recordToLoad.level;
    state.currentView = "PLAY";
    menuStore.state.highlightedLevelId = id;
  };

  menuStore.gotoCreateLevel = o => {
    editorStore.state.id = null;
    editorStore.state.level = [];
    menuStore.state.highlightedLevelId = null;
    state.currentView = "EDITOR";
  };

  levelPlayStore.goBack = o => {
    state.currentView = "MENU";
  };

  levelPlayStore.gotoEditor = () => {
    editorStore.state.id = menuStore.state.highlightedLevelId; // normalize?
    editorStore.state.level = levelPlayStore.state.levelStart;
    state.currentView = "EDITOR";
  };

  return {
    state,
    menuStore,
    levelRecordStore,
    levelPlayStore,
    editorStore
  };
};
<|endoftext|>


<commit_before>/**
 * @file Array related streams
 */
/*#ifndef(UMD)*/
"use strict";
/*global _gpfDefine*/ // Shortcut for gpf.define
/*global _gpfStreamSecureInstallProgressFlag*/ // Install the progress flag used by _gpfStreamSecureRead and Write
/*global _gpfStreamSecureRead*/ // Generate a wrapper to secure multiple calls to stream#read
/*global _gpfStreamSecureWrite*/ // Generates a wrapper to secure multiple calls to stream#write
/*exported _GpfStreamReadableArray*/ // gpf.stream.ReadableArray
/*exported _GpfStreamWritableArray*/ // gpf.stream.WritableArray
/*#endif*/

var
    _GpfStreamReadableArray = _gpfDefine(/** @lends gpf.stream.ReadableArray.prototype */ {
        $class: "gpf.stream.ReadableArray",

        /**
         * Wraps an array inside a readable stream.
         * Each array item is written separately to the output
         *
         * @constructor gpf.stream.ReadableArray
         * @implements {gpf.interfaces.IReadableStream}
         * @param {Array} buffer Array buffer
         */
        constructor: function (buffer) {
            this._buffer = buffer;
        },

        //region gpf.interfaces.IReadableStream

        /**
         * @gpf:sameas gpf.interfaces.IReadableStream#read
         */
        read: _gpfStreamSecureRead(function (output) {
            var buffer = this._buffer, //eslint-disable-line no-invalid-this
                step = 0;
            function write () {
                if (buffer.length === step) {
                    return Promise.resolve();
                }
                return output.write(buffer[step++]);
            }
            return write();
        }),

        //endregion

        /**
         * Buffer
         */
        _buffer: []

    }),

    _GpfStreamWritableArray = _gpfDefine(/** @lends gpf.stream.WritableArray.prototype */ {
        $class: "gpf.stream.WritableArray",

        /**
         * Creates a writable stream that pushes all writes into an array
         *
         * @constructor gpf.stream.WritableArray
         * @implements {gpf.interfaces.IWritableStream}
         */
        constructor: function () {
            this._buffer = [];
        },

        //region gpf.interfaces.IReadableStream

        /**
         * @gpf:sameas gpf.interfaces.IWritableStream#write
         */
        write: _gpfStreamSecureWrite(function (buffer) {
            this._buffer.push(buffer); //eslint-disable-line no-invalid-this
            return Promise.resolve();
        }),

        //endregion

        toArray: function () {
            return this._buffer;
        },

        /**
         * Buffer
         */
        _buffer: []

    });

_gpfStreamSecureInstallProgressFlag(_GpfStreamReadableArray);
_gpfStreamSecureInstallProgressFlag(_GpfStreamWritableArray);
<commit_msg>gpf.stream.ReadableArray (#196)<commit_after>/**
 * @file Array related streams
 * @since 0.2.2
 */
/*#ifndef(UMD)*/
"use strict";
/*global _gpfDefine*/ // Shortcut for gpf.define
/*global _gpfStreamSecureInstallProgressFlag*/ // Install the progress flag used by _gpfStreamSecureRead and Write
/*global _gpfStreamSecureRead*/ // Generate a wrapper to secure multiple calls to stream#read
/*global _gpfStreamSecureWrite*/ // Generates a wrapper to secure multiple calls to stream#write
/*exported _GpfStreamReadableArray*/ // gpf.stream.ReadableArray
/*exported _GpfStreamWritableArray*/ // gpf.stream.WritableArray
/*#endif*/

var
    _GpfStreamReadableArray = _gpfDefine(/** @lends gpf.stream.ReadableArray.prototype */ {
        $class: "gpf.stream.ReadableArray",

        /**
         * Wraps an array inside a readable stream.
         * Each array item is written separately to the output
         *
         * @constructor gpf.stream.ReadableArray
         * @implements {gpf.interfaces.IReadableStream}
         * @param {Array} buffer Array buffer
         * @since 0.2.2
         */
        constructor: function (buffer) {
            this._buffer = buffer;
        },

        //region gpf.interfaces.IReadableStream

        /**
         * @gpf:sameas gpf.interfaces.IReadableStream#read
         * @since 0.2.2
         */
        read: _gpfStreamSecureRead(function (output) {
            var buffer = this._buffer, //eslint-disable-line no-invalid-this
                step = 0;
            function write () {
                if (buffer.length === step) {
                    return Promise.resolve();
                }
                return output.write(buffer[step++]).then(write);
            }
            return write();
        }),

        //endregion

        /**
         * Buffer
         * @since 0.2.2
         */
        _buffer: []

    }),

    _GpfStreamWritableArray = _gpfDefine(/** @lends gpf.stream.WritableArray.prototype */ {
        $class: "gpf.stream.WritableArray",

        /**
         * Creates a writable stream that pushes all writes into an array
         *
         * @constructor gpf.stream.WritableArray
         * @implements {gpf.interfaces.IWritableStream}
         * @since 0.2.2
         */
        constructor: function () {
            this._buffer = [];
        },

        //region gpf.interfaces.IReadableStream

        /**
         * @gpf:sameas gpf.interfaces.IWritableStream#write
         * @since 0.2.2
         */
        write: _gpfStreamSecureWrite(function (buffer) {
            this._buffer.push(buffer); //eslint-disable-line no-invalid-this
            return Promise.resolve();
        }),

        //endregion

        toArray: function () {
            return this._buffer;
        },

        /**
         * Buffer
         * @since 0.2.2
         */
        _buffer: []

    });

_gpfStreamSecureInstallProgressFlag(_GpfStreamReadableArray);
_gpfStreamSecureInstallProgressFlag(_GpfStreamWritableArray);
<|endoftext|>


<commit_before>' use strict';

const StringClass = {
  /**
   * Tests if a string contains vowels
   * @return {Boolean} True or false depending on the match
   */
  hasVowels() {
    return /[aeiou]/i.test(this);
  },
  /**
   * converts strings to uppercase
   * @return {String} string that has been converted to uppercase
   */
  toUpper() {
    return this.replace(/[a-z]/g, (character) => {
      return String.fromCharCode(character.charCodeAt() - 32);
    });
  },
  /**
   * converts strings to lowercase
   * @return {String} string that has been converted to lowercase
   */
  toLower() {
    return this.replace(/[A-Z]/g, (character) => {
      return String.fromCharCode(character.charCodeAt() + 32);
    });
  },
  /**
   * converts strings to title case
   * @return {String} string that has been converted to title case
   */
  ucFirst() {
    return `${this.slice(0, 1).toUpper()}${this.slice(1)}`;
  },
  /**
   * checks if a string is a question by looking for '?' sign
   * @return {Boolean} true or false depending on the match
   */
  isQuestion() {
    return /^[a-z0-9\s]+\?$/i.test(this.trim());
  },
 /**
   * checks for words in a string
   * @return {String} returns array of words in the string
   */
  word() {
    return this.replace(/[^\w\s]/g, '').split(/\s+/);
  },
  /**
   * checks the number of words present in a string
   * @return {Number} the number of words in the string
   */
  wordCount() {
    return this.word().length;
  },
  /**
   * converts currency representation to string
   * @return {String} currency representation of the the number in String
   */
  toCurrency() {
    let roundCurrency = Number(this).toFixed(2);
    roundCurrency = roundCurrency.indexOf('.') > -1 ? roundCurrency : `${roundCurrency}${'.00'}`;
    return roundCurrency.replace(/./g, (number, index) => {
      return index && number !== '.' && ((roundCurrency.length - index) % 3 === 0) ? `${','}${number}` : number;
    });
  },
  /**
   * converts strings representation of currency
   * @return {Number} number representation of the currency String
   */
  fromCurrency() {
    return this.replace(/(,|\.00)/g, '');
  },
  /**
   * converts each letter in the string as an inverse of its current case
   * @return {String} inverse case of each character of the String
   */
  inverseCase() {
    return this.replace(/\w/g, (character) => {
      return /[A-Z]/.test(character) ? character.toLower() : character.toUpper();
    });
  },
  /**
   * converts each character of a String to alternating case
   * @return {String} alternate case of each character of the String
   */
  alternatingCase() {
    return this.replace(/\w/g, (character, index) => {
      return index % 2 !== 0 ? character.toUpper() : character.toLower();
    });
  },
  /**
   * gets the middle character(s) of a String
   * @return {String} middle character(s) of the String
   */
  getMiddle() {
    const middle = this.length / 2;
    return (middle === Math.floor(middle)) ?
      this.substr(middle - 1, 2) : this.charAt(middle);
  },
  /**
   * converts each Number to its String name
   * @return {String} String representation of a number
   */
  numberWords() {
    const mapNumbers = {
      0: 'zero ',
      1: 'one ',
      2: 'two ',
      3: 'three ',
      4: 'four ',
      5: 'five ',
      6: 'six ',
      7: 'seven ',
      8: 'eight ',
      9: 'nine '
    };

    return this.replace(/\d/g, number => mapNumbers[number]).trim();
  },
  /**
   * Checks if a String is a digit i.e one Number
   * @return {Boolean} True of false depending on thne match
   */
  isDigit() {
    return /^[-+]?\d$/.test(this);
  },
  /**
   * checks for double characters in a string
   * @return {Boolean} True of false depending on thne match
   */
  doubleCheck() {
    return /(.)\1/.test(this);
  }
};
Object.assign(String.prototype, StringClass);
<commit_msg>refactor: edit the ucFirst method to make it clean and readable<commit_after>' use strict';

const StringClass = {
  /**
   * Tests if a string contains vowels
   * @return {Boolean} True or false depending on the match
   */
  hasVowels() {
    return /[aeiou]/i.test(this);
  },
  /**
   * converts strings to uppercase
   * @return {String} string that has been converted to uppercase
   */
  toUpper() {
    return this.replace(/[a-z]/g, (character) => {
      return String.fromCharCode(character.charCodeAt() - 32);
    });
  },
  /**
   * converts strings to lowercase
   * @return {String} string that has been converted to lowercase
   */
  toLower() {
    return this.replace(/[A-Z]/g, (character) => {
      return String.fromCharCode(character.charCodeAt() + 32);
    });
  },
  /**
   * converts strings to title case
   * @return {String} string that has been converted to title case
   */
  ucFirst() {
    return `${this[0].toUpper()}${this.slice(1)}`;
  },
  /**
   * checks if a string is a question by looking for '?' sign
   * @return {Boolean} true or false depending on the match
   */
  isQuestion() {
    return /^[a-z0-9\s]+\?$/i.test(this.trim());
  },
 /**
   * checks for words in a string
   * @return {String} returns array of words in the string
   */
  word() {
    return this.replace(/[^\w\s]/g, '').split(/\s+/);
  },
  /**
   * checks the number of words present in a string
   * @return {Number} the number of words in the string
   */
  wordCount() {
    return this.word().length;
  },
  /**
   * converts currency representation to string
   * @return {String} currency representation of the the number in String
   */
  toCurrency() {
    let roundCurrency = Number(this).toFixed(2);
    roundCurrency = roundCurrency.indexOf('.') > -1 ? roundCurrency : `${roundCurrency}${'.00'}`;
    return roundCurrency.replace(/./g, (number, index) => {
      return index && number !== '.' && ((roundCurrency.length - index) % 3 === 0) ? `${','}${number}` : number;
    });
  },
  /**
   * converts strings representation of currency
   * @return {Number} number representation of the currency String
   */
  fromCurrency() {
    return this.replace(/(,|\.00)/g, '');
  },
  /**
   * converts each letter in the string as an inverse of its current case
   * @return {String} inverse case of each character of the String
   */
  inverseCase() {
    return this.replace(/\w/g, (character) => {
      return /[A-Z]/.test(character) ? character.toLower() : character.toUpper();
    });
  },
  /**
   * converts each character of a String to alternating case
   * @return {String} alternate case of each character of the String
   */
  alternatingCase() {
    return this.replace(/\w/g, (character, index) => {
      return index % 2 !== 0 ? character.toUpper() : character.toLower();
    });
  },
  /**
   * gets the middle character(s) of a String
   * @return {String} middle character(s) of the String
   */
  getMiddle() {
    const middle = this.length / 2;
    return (middle === Math.floor(middle)) ?
      this.substr(middle - 1, 2) : this.charAt(middle);
  },
  /**
   * converts each Number to its String name
   * @return {String} String representation of a number
   */
  numberWords() {
    const mapNumbers = {
      0: 'zero ',
      1: 'one ',
      2: 'two ',
      3: 'three ',
      4: 'four ',
      5: 'five ',
      6: 'six ',
      7: 'seven ',
      8: 'eight ',
      9: 'nine '
    };

    return this.replace(/\d/g, number => mapNumbers[number]).trim();
  },
  /**
   * Checks if a String is a digit i.e one Number
   * @return {Boolean} True of false depending on thne match
   */
  isDigit() {
    return /^[-+]?\d$/.test(this);
  },
  /**
   * checks for double characters in a string
   * @return {Boolean} True of false depending on thne match
   */
  doubleCheck() {
    return /(.)\1/.test(this);
  }
};
Object.assign(String.prototype, StringClass);
<|endoftext|>