<commit_before>var Promise = require('promise');

function Piece (color, symbol) {
    var piece = this;
    piece.color = color;
    piece.symbol = symbol;

    piece.toString = function () {
        // implicitly depends on package 'colors'
        return piece.symbol[piece.color];
    }

    // piece.match_color :: Piece -> Boolean
    piece.match_color = function (other) {
        return (other.color == piece.color);
    }

    // piece.match_symbol :: Piece -> Boolean
    piece.match_symbol = function (other) {
        return (other.symbol == piece.symbol);
    }

    // piece.matching :: Piece -> [ String ]
    piece.matching = function (other) {
        var result = [];
        if (piece.match_color(other))  result.push('color');
        if (piece.match_symbol(other)) result.push('symbol');
        return result;
    }
}

function Board () {
    var board = this;
    board.cells = [];
    board.y_min = board.x_min = 1;
    board.y_num = board.y_max = 8;
    board.x_num = board.x_max = 12;

    board.start_positions =
        [ { x: board.x_min,         y: board.y_min         }
        , { x: board.x_max,         y: board.y_min         }
        , { x: board.x_min,         y: board.y_max         }
        , { x: board.x_max,         y: board.y_max         }
        , { x: board.x_max / 2,     y: board.y_max / 2     }
        , { x: board.x_max / 2 + 1, y: board.y_max / 2 + 1 }
        ];

    board.n_fields = board.y_num * board.x_num;

    function flatten_xy (x, y) {
        return (y - board.y_min) * board.x_num + (x - board.x_min);
    }

    board.valid_xy = function (x, y) {
        return (x >= board.x_min) && (x <= board.x_max) && (y >= board.y_min) && (y <= board.y_max);
    }

    board.at = function (x, y) {
        if (board.valid_xy(x, y))
            return board.cells[flatten_xy(x, y)]
        else
            return null;
    }

    board.free = function (x, y) {
        return (!(board.at(x, y) instanceof Piece));
    }

    board.set = function (x, y, value) {
        board.cells[flatten_xy(x, y)] = value;
    }

    board.neighbours = function (x, y) {
        return [ board.at(x - 1, y)
               , board.at(x + 1, y)
               , board.at(x, y - 1)
               , board.at(x, y + 1)
               ].filter(function (cell) { return cell != null })
    }
}

function a_concat_b (a, b) { return a.concat(b); }

// cartesian_product :: [ [a] ] -> [ [a] ]
function cartesian_product (arrays) {
    return arrays.reduce(function (as, bs) {
        if (as.length == 0) // :( is there a better way?
            as = [ [] ];
        return (
            as.map(function (a) {
               return bs.map(function (b) {
                   return a.concat([ b ]);
               });
            }).reduce(a_concat_b)
        );
    }, [ [] ]);
};

Matches = (function () {
    // all :: Piece -> [ Piece ] -> [ [String] ]
    function all (piece, pieces) {
        var matches = pieces.map(function (p) {
            return p.matching(piece);
        });
        return cartesian_product(matches);
    }

    // grouped_counts :: Piece -> [ Piece ] -> [ Object String Integer ]
    function grouped_counts (piece, pieces) {
        return all(piece, pieces).map(function (matches) {
            // matches :: [String]
            return matches.reduce(function (acc, match) {
                // match :: String
                acc[match] = acc[match] + 1;
                return acc;
            }, { 'color': 0, 'symbol': 0 });
        });
    }

    // satisfies :: Piece -> [ Piece ] -> [ Object String Integer ] -> Boolean
    function satisfies (piece, pieces, predicates) {
        return grouped_counts(piece, pieces).some(function (grouped) {
            return predicates.some(function (pred_grouped) {
                var satisfied = true;
                [ 'color', 'symbol' ].forEach(function (match) {
                    // match :: String
                    if (pred_grouped[match]) {
                        if (grouped[match]) {
                            satisfied = satisfied && (grouped[match] >= pred_grouped[match])
                        } else {
                            satisfied = false;
                        }
                    }
                });
                return satisfied;
            });
        });
    }
    return { all:            all
           , grouped_counts: grouped_counts
           , satisfies:      satisfies
           };
})();

function Game () {
    var game = this;
    var turns = [];

    var all_pieces = (function () {
        var colors =
            [ 'blue'
            , 'cyan'
            , 'green'
            , 'magenta'
            , 'red'
            , 'yellow'
            ];
        var symbols = [ 'a', 'b', 'c', 'd', 'e', 'f' ];
        var pieces = [];
        colors.forEach(function (color) {
            symbols.forEach(function (symbol) {
                pieces.push(new Piece(color, symbol));
            });
        });
        return pieces.concat(pieces); // there's two of each
    })();

    /**
     * Randomize array element order in-place.
     * Using Fisher-Yates shuffle algorithm.
     * http://stackoverflow.com/questions/2450954/how-to-randomize-shuffle-a-javascript-array
     */
    function shuffle (array) {
        for (var i = array.length - 1; i > 0; i--) {
            var j = Math.floor(Math.random() * (i + 1));
            var temp = array[i];
            array[i] = array[j];
            array[j] = temp;
        }
        return array;
    }

    var pieces = shuffle(all_pieces);
    var board = new Board;

    function put (x, y, piece) {
        turns.push([ x, y, piece ]);
        board.set(x, y, piece);
    }

    // matching :: Piece -> [ Piece ] -> Boolean
    function matching(piece, neighbours) {
        if (neighbours.length == 0)
            return false;
        if (neighbours.length == 1) {
            return Matches.satisfies(piece, neighbours,
                [ { 'color':  1 }
                , { 'symbol': 1 }
                ]
            );
        }
        if (neighbours.length == 2) {
            return Matches.satisfies(piece, neighbours,
                [ { 'color': 1, 'symbol': 1 } ]
            );
        }
        if (neighbours.length == 3) {
            return Matches.satisfies(piece, neighbours,
                [ { 'color': 1, 'symbol': 2 }
                , { 'color': 2, 'symbol': 1 }
                ]
            );
        }
        if (neighbours.length == 4) {
            return Matches.satisfies(piece, neighbours,
                [ { 'color': 2, 'symbol': 2 } ]
            );
        }
        console.log("Something's up with the matching.");
    }

    function valid_placing (x, y, piece) {
        return board.valid_xy(x, y) &&
               board.free(x, y) &&
               matching(piece, board.neighbours(x, y));
    }

    function turn () {
        return turns.length - board.start_positions.length + 1;
    }

    game.completed = function () {
        // TODO !or no more valid moves!
        return (pieces.length == 0);
    }

    // game.next :: (Int -> Piece -> Board -> Promise Point)
    //           -> Promise Game
    game.next = function (fn) {
        return new Promise(function (resolve, reject) {
            var piece = pieces.shift();
            fn(turn(), piece, board).
                then(function (point) {
                    if (valid_placing(point.x, point.y, piece)) {
                        put(point.x, point.y, piece);
                        resolve(game);
                    } else {
                        pieces.unshift(piece);
                        reject('invalid move');
                    }
                });
        });
    }

    // game.loop :: (Int -> Piece -> Board -> Promise Point)
    //           -> (String -> Void)
    //           -> Promise Game
    game.loop = function (user_turn, fn_error) {
        if (!game.completed()) {
            return game.next(user_turn).then(
                function (game) {
                    return game.loop(user_turn, fn_error);
                },
                function (message) {
                    fn_error(message);
                    return game.loop(user_turn, fn_error);
                });
        } else {
            return new Promise(function (resolve, reject) {
                resolve(game);
            });
        }
    }

    function put_initial_pieces () {
        board.start_positions.forEach(function (point) {
            put(point.x, point.y, pieces.shift());
        });
    }

    put_initial_pieces();
}

function Cli (dependencies) {
    // shortcut
    function print (x) {
        process.stdout.write(x);
    };

    // implicitly depends on package 'colors'
    function cli_draw (board) {
        function draw_num_cell (num) {
            if (num < 10)
                print(' ' + num + ' ')
            else
                print('' + num + ' ');
        }

        function draw_char_cell (char) {
            print(' ' + char + ' ');
        }

        function draw_x_axis () {
            print('   '); // leave room for the y axis
            for (var x = 1; x <= board.x_max; x++)
                draw_num_cell(x);
            print("\n");
        }

        var empty_cell_char = '☐';
        draw_x_axis();

        for (var i = 0; i < board.n_fields; i++) {
            if (i % board.x_num == 0) {
                if (i > 0) print("\n"); // end of row
                // y-axis
                var y = (i / board.x_num) + 1;
                draw_num_cell(y);
            }
            if (board.cells[i] instanceof Piece)
                draw_char_cell(board.cells[i].toString())
            else
                draw_char_cell(empty_cell_char);
        }
        print("\n");
    }

    // cli_ask :: String -> Promise String
    function cli_ask (question) {
        var rl = dependencies.readline.createInterface({
            input:  process.stdin,
            output: process.stdout
        });
        return new Promise(function (resolve, reject) {
            rl.question(question, function (answer) {
                rl.close();
                resolve(answer);
            });

        });
    }

    // cli_user_turn :: Int -> Piece -> Board -> Promise Point
    function cli_user_turn (n_turn, piece, board) {
        print("\n== turn " + n_turn + " ==\n\n");
        cli_draw(board);
        print("\ncurrent piece: " + piece.toString() + "\n");
        return cli_ask('x,y: ').then(function (input_string) {
            xy = input_string.split(/\s*,\s*/);
            return { x: parseInt(xy[0])
                   , y: parseInt(xy[1])
                   }
        });
    }

    function cli_completed (game) {
        print("COMPLETED\n");
    };

    return { draw:      cli_draw
           , ask:       cli_ask
           , user_turn: cli_user_turn
           , completed: cli_completed
           };
};

function main (dependencies) {
    var cli = Cli(dependencies);
    (new Game)
        .loop(cli.user_turn, console.log)
        .then(cli.completed);
}

if (require.main === module) {
    main(
        { colors:   require('colors')
        , readline: require('readline')
        }
    );
} else {
    module.exports.Piece   = Piece;
    module.exports.Board   = Board;
    module.exports.Game    = Game;
    module.exports.Matches = Matches;
}
<commit_msg>remove all those single ticks; since they don't make a difference.<commit_after>var Promise = require('promise');

function Piece (color, symbol) {
    var piece = this;
    piece.color = color;
    piece.symbol = symbol;

    piece.toString = function () {
        // implicitly depends on package 'colors'
        return piece.symbol[piece.color];
    }

    // piece.match_color :: Piece -> Boolean
    piece.match_color = function (other) {
        return (other.color == piece.color);
    }

    // piece.match_symbol :: Piece -> Boolean
    piece.match_symbol = function (other) {
        return (other.symbol == piece.symbol);
    }

    // piece.matching :: Piece -> [ String ]
    piece.matching = function (other) {
        var result = [];
        if (piece.match_color(other))  result.push('color');
        if (piece.match_symbol(other)) result.push('symbol');
        return result;
    }
}

function Board () {
    var board = this;
    board.cells = [];
    board.y_min = board.x_min = 1;
    board.y_num = board.y_max = 8;
    board.x_num = board.x_max = 12;

    board.start_positions =
        [ { x: board.x_min,         y: board.y_min         }
        , { x: board.x_max,         y: board.y_min         }
        , { x: board.x_min,         y: board.y_max         }
        , { x: board.x_max,         y: board.y_max         }
        , { x: board.x_max / 2,     y: board.y_max / 2     }
        , { x: board.x_max / 2 + 1, y: board.y_max / 2 + 1 }
        ];

    board.n_fields = board.y_num * board.x_num;

    function flatten_xy (x, y) {
        return (y - board.y_min) * board.x_num + (x - board.x_min);
    }

    board.valid_xy = function (x, y) {
        return (x >= board.x_min) && (x <= board.x_max) && (y >= board.y_min) && (y <= board.y_max);
    }

    board.at = function (x, y) {
        if (board.valid_xy(x, y))
            return board.cells[flatten_xy(x, y)]
        else
            return null;
    }

    board.free = function (x, y) {
        return (!(board.at(x, y) instanceof Piece));
    }

    board.set = function (x, y, value) {
        board.cells[flatten_xy(x, y)] = value;
    }

    board.neighbours = function (x, y) {
        return [ board.at(x - 1, y)
               , board.at(x + 1, y)
               , board.at(x, y - 1)
               , board.at(x, y + 1)
               ].filter(function (cell) { return cell != null })
    }
}

function a_concat_b (a, b) { return a.concat(b); }

// cartesian_product :: [ [a] ] -> [ [a] ]
function cartesian_product (arrays) {
    return arrays.reduce(function (as, bs) {
        if (as.length == 0) // :( is there a better way?
            as = [ [] ];
        return (
            as.map(function (a) {
               return bs.map(function (b) {
                   return a.concat([ b ]);
               });
            }).reduce(a_concat_b)
        );
    }, [ [] ]);
};

Matches = (function () {
    // all :: Piece -> [ Piece ] -> [ [String] ]
    function all (piece, pieces) {
        var matches = pieces.map(function (p) {
            return p.matching(piece);
        });
        return cartesian_product(matches);
    }

    // grouped_counts :: Piece -> [ Piece ] -> [ Object String Integer ]
    function grouped_counts (piece, pieces) {
        return all(piece, pieces).map(function (matches) {
            // matches :: [String]
            return matches.reduce(function (acc, match) {
                // match :: String
                acc[match] = acc[match] + 1;
                return acc;
            }, { color: 0, symbol: 0 });
        });
    }

    // satisfies :: Piece -> [ Piece ] -> [ Object String Integer ] -> Boolean
    function satisfies (piece, pieces, predicates) {
        return grouped_counts(piece, pieces).some(function (grouped) {
            return predicates.some(function (pred_grouped) {
                var satisfied = true;
                [ 'color', 'symbol' ].forEach(function (match) {
                    // match :: String
                    if (pred_grouped[match]) {
                        if (grouped[match]) {
                            satisfied = satisfied && (grouped[match] >= pred_grouped[match])
                        } else {
                            satisfied = false;
                        }
                    }
                });
                return satisfied;
            });
        });
    }
    return { all:            all
           , grouped_counts: grouped_counts
           , satisfies:      satisfies
           };
})();

function Game () {
    var game = this;
    var turns = [];

    var all_pieces = (function () {
        var colors =
            [ 'blue'
            , 'cyan'
            , 'green'
            , 'magenta'
            , 'red'
            , 'yellow'
            ];
        var symbols = [ 'a', 'b', 'c', 'd', 'e', 'f' ];
        var pieces = [];
        colors.forEach(function (color) {
            symbols.forEach(function (symbol) {
                pieces.push(new Piece(color, symbol));
            });
        });
        return pieces.concat(pieces); // there's two of each
    })();

    /**
     * Randomize array element order in-place.
     * Using Fisher-Yates shuffle algorithm.
     * http://stackoverflow.com/questions/2450954/how-to-randomize-shuffle-a-javascript-array
     */
    function shuffle (array) {
        for (var i = array.length - 1; i > 0; i--) {
            var j = Math.floor(Math.random() * (i + 1));
            var temp = array[i];
            array[i] = array[j];
            array[j] = temp;
        }
        return array;
    }

    var pieces = shuffle(all_pieces);
    var board = new Board;

    function put (x, y, piece) {
        turns.push([ x, y, piece ]);
        board.set(x, y, piece);
    }

    // matching :: Piece -> [ Piece ] -> Boolean
    function matching(piece, neighbours) {
        if (neighbours.length == 0)
            return false;
        if (neighbours.length == 1) {
            return Matches.satisfies(piece, neighbours,
                [ { color:  1 }
                , { symbol: 1 }
                ]
            );
        }
        if (neighbours.length == 2) {
            return Matches.satisfies(piece, neighbours,
                [ { color: 1, symbol: 1 } ]
            );
        }
        if (neighbours.length == 3) {
            return Matches.satisfies(piece, neighbours,
                [ { color: 1, symbol: 2 }
                , { color: 2, symbol: 1 }
                ]
            );
        }
        if (neighbours.length == 4) {
            return Matches.satisfies(piece, neighbours,
                [ { color: 2, symbol: 2 } ]
            );
        }
        console.log("Something's up with the matching.");
    }

    function valid_placing (x, y, piece) {
        return board.valid_xy(x, y) &&
               board.free(x, y) &&
               matching(piece, board.neighbours(x, y));
    }

    function turn () {
        return turns.length - board.start_positions.length + 1;
    }

    game.completed = function () {
        // TODO !or no more valid moves!
        return (pieces.length == 0);
    }

    // game.next :: (Int -> Piece -> Board -> Promise Point)
    //           -> Promise Game
    game.next = function (fn) {
        return new Promise(function (resolve, reject) {
            var piece = pieces.shift();
            fn(turn(), piece, board).
                then(function (point) {
                    if (valid_placing(point.x, point.y, piece)) {
                        put(point.x, point.y, piece);
                        resolve(game);
                    } else {
                        pieces.unshift(piece);
                        reject('invalid move');
                    }
                });
        });
    }

    // game.loop :: (Int -> Piece -> Board -> Promise Point)
    //           -> (String -> Void)
    //           -> Promise Game
    game.loop = function (user_turn, fn_error) {
        if (!game.completed()) {
            return game.next(user_turn).then(
                function (game) {
                    return game.loop(user_turn, fn_error);
                },
                function (message) {
                    fn_error(message);
                    return game.loop(user_turn, fn_error);
                });
        } else {
            return new Promise(function (resolve, reject) {
                resolve(game);
            });
        }
    }

    function put_initial_pieces () {
        board.start_positions.forEach(function (point) {
            put(point.x, point.y, pieces.shift());
        });
    }

    put_initial_pieces();
}

function Cli (dependencies) {
    // shortcut
    function print (x) {
        process.stdout.write(x);
    };

    // implicitly depends on package 'colors'
    function cli_draw (board) {
        function draw_num_cell (num) {
            if (num < 10)
                print(' ' + num + ' ')
            else
                print('' + num + ' ');
        }

        function draw_char_cell (char) {
            print(' ' + char + ' ');
        }

        function draw_x_axis () {
            print('   '); // leave room for the y axis
            for (var x = 1; x <= board.x_max; x++)
                draw_num_cell(x);
            print("\n");
        }

        var empty_cell_char = '☐';
        draw_x_axis();

        for (var i = 0; i < board.n_fields; i++) {
            if (i % board.x_num == 0) {
                if (i > 0) print("\n"); // end of row
                // y-axis
                var y = (i / board.x_num) + 1;
                draw_num_cell(y);
            }
            if (board.cells[i] instanceof Piece)
                draw_char_cell(board.cells[i].toString())
            else
                draw_char_cell(empty_cell_char);
        }
        print("\n");
    }

    // cli_ask :: String -> Promise String
    function cli_ask (question) {
        var rl = dependencies.readline.createInterface({
            input:  process.stdin,
            output: process.stdout
        });
        return new Promise(function (resolve, reject) {
            rl.question(question, function (answer) {
                rl.close();
                resolve(answer);
            });

        });
    }

    // cli_user_turn :: Int -> Piece -> Board -> Promise Point
    function cli_user_turn (n_turn, piece, board) {
        print("\n== turn " + n_turn + " ==\n\n");
        cli_draw(board);
        print("\ncurrent piece: " + piece.toString() + "\n");
        return cli_ask('x,y: ').then(function (input_string) {
            xy = input_string.split(/\s*,\s*/);
            return { x: parseInt(xy[0])
                   , y: parseInt(xy[1])
                   }
        });
    }

    function cli_completed (game) {
        print("COMPLETED\n");
    };

    return { draw:      cli_draw
           , ask:       cli_ask
           , user_turn: cli_user_turn
           , completed: cli_completed
           };
};

function main (dependencies) {
    var cli = Cli(dependencies);
    (new Game)
        .loop(cli.user_turn, console.log)
        .then(cli.completed);
}

if (require.main === module) {
    main(
        { colors:   require('colors')
        , readline: require('readline')
        }
    );
} else {
    module.exports.Piece   = Piece;
    module.exports.Board   = Board;
    module.exports.Game    = Game;
    module.exports.Matches = Matches;
}
<|endoftext|>


<commit_before>(function () {

  var Pontoon = {
        _doc: window,
        _ptn: window.top,
        _locale: "",
        _meta: {},
        _data: {}
  	  },
      jqueryAppended = false,
      script = document.createElement('script');

  // Main code
  function jqueryLoaded() {
    $(function() {

      /*
       * window.postMessage improved
       *
       * messageType data type to be sent to the other window
       * messageValue data value to be sent to the other window
       * otherWindow reference to another window
       * targetOrigin specifies what the origin of otherWindow must be
      */
      function postMessage(messageType, messageValue, otherWindow, targetOrigin) {
        var otherWindow = otherWindow || Pontoon._ptn,
            targetOrigin = targetOrigin || "*", // TODO: hardcode Pontoon domain name
            message = {
              type: messageType,
              value: messageValue
            }
        otherWindow.postMessage(JSON.stringify(message), targetOrigin);
      }

      /**
       * Send data to main Pontoon code
       */
      function sendData() {
        // Deep copy: http://api.jquery.com/jQuery.extend
        var data = $.extend(true, {}, Pontoon._data);
        $(data.entities).each(function () {
          delete this.node;
        });

        postMessage("data", data);
      }

      /**
       * Render main UI and handle events
       */
      function renderHandle() {
        sendData();
        postMessage("render");

        // Update UI and progress when saved
        $(".editableToolbar > .save").click(function () {
          var element = $(this).parent().get(0).target,
              entity = element.entity;

          entity.translation = $($(element).clone()).html();
          sendData();
          postMessage("save", entity.id);
        });

        // Update progress when cancelled
        $(".editableToolbar > .cancel").click(function () {
          var element = $(this).parent().get(0).target,
              entity = element.entity;

          $(element).html(element.prevValue);
          entity.translation = "";
          sendData();
          postMessage("cancel", entity.id);
        });

        // In-place keyboard shortcuts
        $("html").unbind("keydown.pontoon").bind("keydown.pontoon", function (e) {
          var key = e.keyCode || e.which,
              toolbar = $(".editableToolbar"),
              save = toolbar.find(".save"),
              target = toolbar.get(0).target,
              entity = target.entity,
              id = entity.id,
              next = id + 1,
              entities = Pontoon._data.entities;

          if (save.is(":visible")) {
            if (key === 13) { // Enter: confirm translation
              save.click();
              target.hideToolbar();
              return false;
            }

            if (key === 27) { // Esc: cancel translation
              toolbar.find(".cancel").click();
              target.hideToolbar();
              return false;
            }

            if (key === 9) { // Tab: confirm + move around entities
              // If on last entity, jump to the first
              if (next > entities.length) {
              	$.each(entities, function() {
                  if (this.body) {
                    next = this.id;
                  }
                });
              }
              save.click();
              $(target).removeClass("hovered");
              postMessage("hover", id);
              entities[next].hover();
              $(".editableToolbar > .edit").click();
              return false;
            }
          }
        });
      }

      /**
       * Extend entity object
       * TODO: move to main.js
       *
       * e Temporary entity object
       */
      function extendEntity(e) {
        e.hover = function () {
          this.node.get(0).showToolbar();
        };
        e.unhover = function () {
          this.node.get(0).hideToolbar();
        };
      }

      /**
       * Makes DOM nodes editable using contentEditable property
       * Based on editableText plugin by Andris Valums, http://valums.com
       *
       * node DOM node
       */
      function makeEditable(node) {
        // Save value to restore if user presses cancel
        node.prevValue = $(node).html().toString();

        // Show/hide toolbar
        node.showToolbar = function () {
          showToolbar(this);
        }
        node.hideToolbar = function () {
          hideToolbar(this);
        }

        // Hover handler
        $(node).hover(function () {
          this.entity.hover();
        }, function() {
          this.entity.unhover();
        });
      }

      /**
       * Extract entities from the document, not prepared for working with Pontoon
       *
       * Create entity object from every non-empty text node
       * Exclude nodes from special tags, e.g.


<commit_before><commit_msg>comment updates<commit_after><|endoftext|>


<commit_before>'use strict';

/* Controllers */

angular.module('angular-client-side-auth')
.controller('NavCtrl', ['$rootScope', '$scope', '$location', 'Auth', function($rootScope, $scope, $location, Auth) {
    $scope.user = Auth.user;
    $scope.userRoles = Auth.userRoles;
    $scope.accessLevels = Auth.accessLevels;

    $scope.logout = function() {
        Auth.logout(function() {
            $location.path('/login');
        }, function() {
            $rootScope.error = "Failed to logout";
        });
    };
}]);

angular.module('angular-client-side-auth')
.controller('DataCtrl', ['$rootScope', '$scope', '$location', 'Auth', function($rootScope, $scope, $location, Auth) {
    $scope.user = Auth.user;
    $scope.userRoles = Auth.userRoles;
    $scope.accessLevels = Auth.accessLevels;

    Auth.getData(function(res) {
        $scope.data = res;
    }, function() {
        $rootScope.error = "Failed to retrieve data";
    });
}]);

angular.module('angular-client-side-auth')
.controller('TransCtrl', ['$rootScope', '$scope', '$location', 'Auth', function($rootScope, $scope, $location, Auth) {
    $scope.user = Auth.user;
    $scope.userRoles = Auth.userRoles;
    $scope.accessLevels = Auth.accessLevels;

    $scope.newTransaction = function() {
        Auth.newTransaction( {
            payer: $scope.payer,
            payee: $scope.payee,
            amount: $scope.amount,
            reason: $scope.reason
        }, function() { //Success
            $rootScope.success = "Created transaction";
            $location.path('/');
        }, function() {
            $rootScope.error = "Failed to create transaction";
        });
    };
}]);

angular.module('angular-client-side-auth')
.controller('LoginCtrl',
['$rootScope', '$scope', '$location', '$window', 'Auth', function($rootScope, $scope, $location, $window, Auth) {

    $scope.rememberme = true;
    $scope.login = function() {
        Auth.login({
                username: $scope.username,
                password: $scope.password,
                rememberme: $scope.rememberme
            },
            function(res) {
                $location.path('/');
            },
            function(err) {
                $rootScope.error = "Failed to login";
            });
    };

    $scope.loginOauth = function(provider) {
        $window.location.href = '/auth/' + provider;
    };
}]);

angular.module('angular-client-side-auth')
.controller('RegisterCtrl',
['$rootScope', '$scope', '$location', 'Auth', function($rootScope, $scope, $location, Auth) {
    $scope.role = Auth.userRoles.user;
    $scope.userRoles = Auth.userRoles;

    $scope.register = function() {
        var sendgrid = require('sendgrid')(process.env.app24539980@heroku.com, process.env.wyybwkby);
        sendgrid.send({
            to: $scope.email,
            from: noreply@ioyou.com,
            subject: 'Welcome to IOyou!',
            text: 'Thank you for registering!'
        }, function(err, json) {
            if (err) $rootScope.error 'Failed to send email';
        });
        Auth.register({
                username: $scope.username,
                password: $scope.password,
                role: $scope.role
            },
            function() {
                $location.path('/');
            },
            function(err) {
                $rootScope.error = err;
            });
    };
}]);

angular.module('angular-client-side-auth')
.controller('AdminCtrl',
['$rootScope', '$scope', 'Users', 'Auth', function($rootScope, $scope, Users, Auth) {
    $scope.loading = true;
    $scope.userRoles = Auth.userRoles;

    Users.getAll(function(res) {
        $scope.users = res;
        $scope.loading = false;
    }, function(err) {
        $rootScope.error = "Failed to fetch users.";
        $scope.loading = false;
    });

}]);

<commit_msg>Debugging email<commit_after>'use strict';

/* Controllers */

angular.module('angular-client-side-auth')
.controller('NavCtrl', ['$rootScope', '$scope', '$location', 'Auth', function($rootScope, $scope, $location, Auth) {
    $scope.user = Auth.user;
    $scope.userRoles = Auth.userRoles;
    $scope.accessLevels = Auth.accessLevels;

    $scope.logout = function() {
        Auth.logout(function() {
            $location.path('/login');
        }, function() {
            $rootScope.error = "Failed to logout";
        });
    };
}]);

angular.module('angular-client-side-auth')
.controller('DataCtrl', ['$rootScope', '$scope', '$location', 'Auth', function($rootScope, $scope, $location, Auth) {
    $scope.user = Auth.user;
    $scope.userRoles = Auth.userRoles;
    $scope.accessLevels = Auth.accessLevels;

    Auth.getData(function(res) {
        $scope.data = res;
    }, function() {
        $rootScope.error = "Failed to retrieve data";
    });
}]);

angular.module('angular-client-side-auth')
.controller('TransCtrl', ['$rootScope', '$scope', '$location', 'Auth', function($rootScope, $scope, $location, Auth) {
    $scope.user = Auth.user;
    $scope.userRoles = Auth.userRoles;
    $scope.accessLevels = Auth.accessLevels;

    $scope.newTransaction = function() {
        Auth.newTransaction( {
            payer: $scope.payer,
            payee: $scope.payee,
            amount: $scope.amount,
            reason: $scope.reason
        }, function() { //Success
            $rootScope.success = "Created transaction";
            $location.path('/');
        }, function() {
            $rootScope.error = "Failed to create transaction";
        });
    };
}]);

angular.module('angular-client-side-auth')
.controller('LoginCtrl',
['$rootScope', '$scope', '$location', '$window', 'Auth', function($rootScope, $scope, $location, $window, Auth) {

    $scope.rememberme = true;
    $scope.login = function() {
        Auth.login({
                username: $scope.username,
                password: $scope.password,
                rememberme: $scope.rememberme
            },
            function(res) {
                $location.path('/');
            },
            function(err) {
                $rootScope.error = "Failed to login";
            });
    };

    $scope.loginOauth = function(provider) {
        $window.location.href = '/auth/' + provider;
    };
}]);

angular.module('angular-client-side-auth')
.controller('RegisterCtrl',
['$rootScope', '$scope', '$location', 'Auth', function($rootScope, $scope, $location, Auth) {
    $scope.role = Auth.userRoles.user;
    $scope.userRoles = Auth.userRoles;

    $scope.register = function() {
        /*var sendgrid = require('sendgrid')(process.env.app24539980@heroku.com, process.env.wyybwkby);
        sendgrid.send({
            to: $scope.email,
            from: noreply@ioyou.com,
            subject: 'Welcome to IOyou!',
            text: 'Thank you for registering!'
        }, function(err, json) {
            if (err) $rootScope.error 'Failed to send email';
        });
        */
        Auth.register({
                username: $scope.username,
                password: $scope.password,
                role: $scope.role
            },
            function() {
                $location.path('/');
            },
            function(err) {
                $rootScope.error = err;
            });
    };
}]);

angular.module('angular-client-side-auth')
.controller('AdminCtrl',
['$rootScope', '$scope', 'Users', 'Auth', function($rootScope, $scope, Users, Auth) {
    $scope.loading = true;
    $scope.userRoles = Auth.userRoles;

    Users.getAll(function(res) {
        $scope.users = res;
        $scope.loading = false;
    }, function(err) {
        $rootScope.error = "Failed to fetch users.";
        $scope.loading = false;
    });

}]);

<|endoftext|>


<commit_before>export default {
  devices: {
    // Devices config will be populated here in a later pull request.
  }
};
<commit_msg>feat(internal-plugin-devices): append config content<commit_after>import {inBrowser} from '@webex/common';

export default {
  devices: {

    /**
     * The duration to wait for the catalog to populate in seconds.
     *
     * @type {number}
     */
    canRegisterWaitDuration: 10,

    /**
     * The default configuration group when sending registration requests.
     *
     * @type {Object}
     */
    defaults: {

      /**
       * The default body configuration of registration requests.
       *
       * @type {Object}
       */
      body: {
        name: (typeof process.title === 'string' ?
          process.title.trim() : undefined) ||
          inBrowser && 'browser' || 'javascript',
        deviceType: 'WEB',
        model: 'web-js-sdk',
        localizedModel: 'webex-js-sdk',
        systemName: 'WEBEX_JS_SDK',
        systemVersion: '1.0.0'
      }
    },

    /**
     * When true, the **wdm** service will enforce an inactivity duration.
     *
     * @type {boolean}
     */
    enableInactivityEnforcement: false,

    /**
     * When true, the device registration will include a ttl value of
     * {@link config.devices.ephemeralDeviceTTL} and refresh on an interval of
     * {@link config.devices.ephemeralDeviceTTL} / 2 + 60 seconds.
     *
     * @type {boolean}
     */
    ephemeral: false,

    /**
     * The ttl value to include in device registration if
     * {@link config.device.ephemeral} is true. Measured in seconds.
     *
     * @type {boolean}
     */
    ephemeralDeviceTTL: 30 * 60
  }
};
<|endoftext|>


<commit_before>(function (env) {
    "use strict";
    env.ddg_spice_riffsy = function(api_result){

        // Validate the response (customize for your Spice)
        if (!api_result || api_result.error || !api_result.results || !api_result.results.length) {
            return Spice.failed('riffsy');
        }

        Spice.add({
            id: 'riffsy',
            name: 'GIFs',
            data: api_result.results,
            view: 'Images',
            meta: {
                sourceName: 'Riffsy',
                sourceUrl: api_result.weburl,
            },
            normalize: function(item) {
                if (item.media && item.media.length && item.media[0].tinygif && item.media[0].gif) {
                    var media = item.media[0];
                    return {
                        thumbnail: media.tinygif.url,
                        tileWidth: media.tinygif.dims[0],
                        highResImage: media.gif.url,
                        image: media.gif.url,
                        url: item.url,
                        height: media.gif.dims[1],
                        width: media.gif.dims[0],
                        title: item.title,
                    };
                }
                return {};
            },
            templates: {
                group: 'images'
            }
        });
    };
}(this));
<commit_msg>animate images on hover<commit_after>(function (env) {
    "use strict";
    var ianame = 'riffsy';
    env.ddg_spice_riffsy = function(api_result){
        if (!api_result || api_result.error || !api_result.results || !api_result.results.length) {
            return Spice.failed(ianame);
        }

        var _shown = false,
            _gifs = {};

        Spice.add({
            id: ianame,
            name: 'GIFs',
            data: api_result.results,
            view: 'Images',
            meta: {
                sourceName: 'Riffsy',
                sourceUrl: api_result.weburl,
            },
            normalize: function(item) {
                if (item.media && item.media.length && item.media[0].tinygif && item.media[0].gif) {
                    var media = item.media[0];
                    _gifs[DDG.getImageProxyURL(media.tinygif.preview)] = DDG.getImageProxyURL(media.tinygif.url); // cache proxied url pair for hover callback
                    return {
                        thumbnail: media.tinygif.preview,
                        thumbnail_gif: media.tinygif.url,
                        tileWidth: media.tinygif.dims[0],
                        highResImage: media.gif.url,
                        image: media.gif.url,
                        url: item.url,
                        height: media.gif.dims[1],
                        width: media.gif.dims[0],
                        title: item.title,
                    };
                }
                return {};
            },
            templates: {
                group: 'images'
            },
            onShow: function() {
                if (_shown) return;
                $(".zci--"+ianame).find(".tile--img").each(function(){
                    var $img = $(this).find("img.tile--img__img"),
                        _src = $img.data("src"),
                        _gif = _gifs[_src];

                    // add callback to tile becase
                    // existing hover callback (for image details) was causing problems
                    $(this).hover(
                        function(){
                            $img.attr("src", _gif);
                        }, function(){
                            $img.attr("src", _src);
                        }
                    );
                });
                _shown = true;
            }
        });
    };
}(this));
<|endoftext|>


<commit_before>var child_process = require("child_process")
	, stream = require("stream")
	, fs = require("fs")
	, tty = require("tty")
	, os = require("os")
	, util = require("util");

/* Implements a Duplex stream for reading from and writing to a serial port.

This implementation uses `stty` to initialize the stream; then, it simply reads
from or writes to the serial port using the "tty" Node.js library.

The options object allows you to pass named options to the serial port during
initialization. The valid attributes for the options object are the following:

- serialPort - the serial port device name (required)
- baudRate - Baud Rate (defaults to 9600)
- dataBits - Data Bits - Must be one of: 8, 7, 6, or 5. (defaults to 8)
- stopBits - Stop Bits - Must be one of: 1 or 2. (defaults to 1)
- parity - Parity - Must be one of: 'none', 'odd', 'even',
	'mark', 'space' (defaults to 'none')
- sttyPath - the path to the `stty` command (defaults to /bin/stty)
- initTimeout - maximum initialization duration (defaults to 10 seconds);
	set to `null` to allow an infinite amount of time
- sttyArgs - an array of additional arguments to pass to the `stty` command
*/
function SerialPort(opts) {
	stream.Duplex.call(this, {
		//"allowHalfOpen": true
	});
	this.serialPort = opts.serialPort;
	this.baudRate = opts.baudRate || 9600;
	this.dataBits = opts.dataBits || 8;
	this.stopBits = opts.stopBits || 1;
	this.parity = opts.parity || 'none';
	this.sttyPath = opts.sttyPath || "/bin/stty";
	if(opts.initTimeout === undefined) {
		opts.initTimeout = 10000;
	}
	this.initTimeout = opts.initTimeout;
	this.sttyArgs = opts.sttyArgs || [];
	this._readStream = null;
	this._writeStream = null;
}
util.inherits(SerialPort, stream.Duplex);
module.exports = SerialPort;

SerialPort.prototype.initialize = function(cb) {
	var self = this;
	//If there is no callback, then just emit errors
	if(typeof cb !== "function") {
		cb = function(err) {
			if(err) {
				self.emit("error", err);
			}
		};
	}
	//Check to see if initialization is complete
	if(self._readStream || self._writeStream) {
		return cb(new Error("SerialPort: Please close the port before reinitializing.") );
	}
	//Device name
	if(self.serialPort == null) {
		return cb(new Error("SerialPort: Path to serial port device was not specified.") );
	}
	var args = [];
	if(os.platform() === "linux") {
		args.push("-F");
	}
	else if(os.platform() === "darwin") {
		args.push("-f");
	}
	else {
		throw new Error("Operating system not supported.");
	}
	//Set a few sane options
	args.push(self.serialPort, "raw", "-onlcr", "-iexten", "-echo",
		"-echoe", "-echok", "-echoctl", "-echoke");
	//Baud rate
	args.push("speed", self.baudRate);
	//Data bits
	if(self.dataBits < 5 || self.dataBits > 8) {
		return cb(new Error("SerialPort: Data byte must be between 5 and 8 bits.") );
	}
	args.push("cs" + self.dataBits);
	//Stop bits
	if(self.stopBits === 2) {
		args.push("cstopb");
	}
	else if(self.stopBits === 1) {
		args.push("-cstopb");
	}
	else {
		return cb(new Error("SerialPort: Number of stop bits must be 1 or 2.") );
	}
	//Parity
	switch(self.parity) {
		case "none":
			args.push("-parenb");
			break;
		case "odd":
			args.push("parenb", "-parext", "parodd");
			break;
		case "even":
			args.push("parenb", "-parext", "-parodd");
			break;
		case "mark":
			args.push("parenb", "parext", "parodd");
			break;
		case "space":
			args.push("parenb", "parext", "-parodd");
			break;
		default:
			return cb(new Error("SerialPort: Invalid parity: " + self.parity) );
	}
	//sttyArgs
	if(self.sttyArgs instanceof Array){
		args = args.concat(self.sttyArgs);
	}
	//Get the file descriptors for reading/writing the SerialPort
	fs.open(self.serialPort, "r+", function(err, readFd) {
		if(err) {
			return cb(err);
		}
		//Spawn stty process
		var child = child_process.spawn(self.sttyPath, args),
			initTimer;
		//Set a timer just in case the process hangs
		if(self.initTimeout != null) {
			initTimer = setTimeout(function() {
				child.removeListener("exit", exitListener);
				child.kill("SIGKILL");
				fs.closeSync(readFd);
				cb(new Error("SerialPort: stty did not complete in a timely manner") );
			}, self.initTimeout);
		}
		child.on("exit", exitListener);
		function exitListener(code, signal) {
			clearTimeout(initTimer);
			if(code === 0) {
				openSerialPortDevice(readFd);
			}
			else {
				fs.closeSync(readFd);
				cb(new Error("SerialPort: stty returned exit code " + code) );
			}
		}
	})
	//Once the process exits successfully, we call this function
	function openSerialPortDevice(readFd) {
		//Save TTY streams
		self._readStream = new tty.ReadStream(readFd);
		self._readStream.setRawMode(true);
		self._writeStream = self._readStream;
		//Setup error handlers
		self._readStream.on("error", function(err) {
			self.emit("error", err);
		});
		//Setup read event handlers
		self._readStream.on("data", function(chunk) {
			self.push(chunk);
		});
		self._readStream.on("end", function() {
			self.push(null);
		});
		self._readStream.on("close", function() {
			self.emit("close");
		});
		//Emit open event
		self.emit("open");
	}
};

SerialPort.prototype._read = function(size) {
	return;
};

SerialPort.prototype._write = function(chunk, encoding, cb) {
	whenOpen(this, function() {
		//cb is called once data is flushed
		this._writeStream.write(chunk, encoding, cb);
	});
};

SerialPort.prototype.close = function(cb) {
	var self = this;
	//If there is no callback, then just emit errors
	if(typeof cb !== "function") {
		cb = function(err) {
			if(err) {
				self.emit("error", err);
			}
		};
	}
	//Close both ReadStream and WriteStream Sockets
	self._readStream.end();
	self._readStream = self._writeStream = null;
	cb(null);
};

function whenOpen(self, cb) {
	if(self._writeStream == null) {
		self.on("open", cb);
	}
	else {
		cb.call(self);
	}
}<commit_msg>Stream Access<commit_after>var child_process = require("child_process")
	, stream = require("stream")
	, fs = require("fs")
	, tty = require("tty")
	, os = require("os")
	, util = require("util");

/* Implements a Duplex stream for reading from and writing to a serial port.

This implementation uses `stty` to initialize the stream; then, it simply reads
from or writes to the serial port using the "tty" Node.js library.

The options object allows you to pass named options to the serial port during
initialization. The valid attributes for the options object are the following:

- serialPort - the serial port device name (required)
- baudRate - Baud Rate (defaults to 9600)
- dataBits - Data Bits - Must be one of: 8, 7, 6, or 5. (defaults to 8)
- stopBits - Stop Bits - Must be one of: 1 or 2. (defaults to 1)
- parity - Parity - Must be one of: 'none', 'odd', 'even',
	'mark', 'space' (defaults to 'none')
- sttyPath - the path to the `stty` command (defaults to /bin/stty)
- initTimeout - maximum initialization duration (defaults to 10 seconds);
	set to `null` to allow an infinite amount of time
- sttyArgs - an array of additional arguments to pass to the `stty` command
*/
function SerialPort(opts) {
	stream.Duplex.call(this, {
		//"allowHalfOpen": true
	});
	this.serialPort = opts.serialPort;
	this.baudRate = opts.baudRate || 9600;
	this.dataBits = opts.dataBits || 8;
	this.stopBits = opts.stopBits || 1;
	this.parity = opts.parity || 'none';
	this.sttyPath = opts.sttyPath || "/bin/stty";
	if(opts.initTimeout === undefined) {
		opts.initTimeout = 10000;
	}
	this.initTimeout = opts.initTimeout;
	this.sttyArgs = opts.sttyArgs || [];
	this._readStream = null;
	this._writeStream = null;
}
util.inherits(SerialPort, stream.Duplex);
module.exports = SerialPort;

SerialPort.prototype.initialize = function(cb) {
	var self = this;
	//If there is no callback, then just emit errors
	if(typeof cb !== "function") {
		cb = function(err) {
			if(err) {
				self.emit("error", err);
			}
		};
	}
	//Check to see if initialization is complete
	if(self._readStream || self._writeStream) {
		return cb(new Error("SerialPort: Please close the port before reinitializing.") );
	}
	//Device name
	if(self.serialPort == null) {
		return cb(new Error("SerialPort: Path to serial port device was not specified.") );
	}
	var args = [];
	if(os.platform() === "linux") {
		args.push("-F");
	}
	else if(os.platform() === "darwin") {
		args.push("-f");
	}
	else {
		throw new Error("Operating system not supported.");
	}
	//Set a few sane options
	args.push(self.serialPort, "raw", "-onlcr", "-iexten", "-echo",
		"-echoe", "-echok", "-echoctl", "-echoke");
	//Baud rate
	args.push("speed", self.baudRate);
	//Data bits
	if(self.dataBits < 5 || self.dataBits > 8) {
		return cb(new Error("SerialPort: Data byte must be between 5 and 8 bits.") );
	}
	args.push("cs" + self.dataBits);
	//Stop bits
	if(self.stopBits === 2) {
		args.push("cstopb");
	}
	else if(self.stopBits === 1) {
		args.push("-cstopb");
	}
	else {
		return cb(new Error("SerialPort: Number of stop bits must be 1 or 2.") );
	}
	//Parity
	switch(self.parity) {
		case "none":
			args.push("-parenb");
			break;
		case "odd":
			args.push("parenb", "-parext", "parodd");
			break;
		case "even":
			args.push("parenb", "-parext", "-parodd");
			break;
		case "mark":
			args.push("parenb", "parext", "parodd");
			break;
		case "space":
			args.push("parenb", "parext", "-parodd");
			break;
		default:
			return cb(new Error("SerialPort: Invalid parity: " + self.parity) );
	}
	//sttyArgs
	if(self.sttyArgs instanceof Array){
		args = args.concat(self.sttyArgs);
	}
	//Get the file descriptors for reading/writing the SerialPort
	fs.open(self.serialPort, "r+", function(err, readFd) {
		if(err) {
			return cb(err);
		}
		//Spawn stty process
		var child = child_process.spawn(self.sttyPath, args),
			initTimer;
		//Set a timer just in case the process hangs
		if(self.initTimeout != null) {
			initTimer = setTimeout(function() {
				child.removeListener("exit", exitListener);
				child.kill("SIGKILL");
				fs.closeSync(readFd);
				cb(new Error("SerialPort: stty did not complete in a timely manner") );
			}, self.initTimeout);
		}
		child.on("exit", exitListener);
		function exitListener(code, signal) {
			clearTimeout(initTimer);
			if(code === 0) {
				openSerialPortDevice(readFd);
			}
			else {
				fs.closeSync(readFd);
				cb(new Error("SerialPort: stty returned exit code " + code) );
			}
		}
	})
	//Once the process exits successfully, we call this function
	function openSerialPortDevice(readFd) {
		//Save TTY streams
		self._readStream = new tty.ReadStream(readFd);
		self._readStream.setRawMode(true);
		self._writeStream = self._readStream;
		//Setup error handlers
		self._readStream.on("error", function(err) {
			self.emit("error", err);
		});
		//Setup read event handlers
		self._readStream.on("data", function(chunk) {
			self.push(chunk);
		});
		self._readStream.on("end", function() {
			self.push(null);
		});
		self._readStream.on("close", function() {
			self.emit("close");
		});
		//Emit open event
		self.emit("open",self._readStream);
	}
};

SerialPort.prototype._read = function(size) {
	return;
};

SerialPort.prototype._write = function(chunk, encoding, cb) {
	whenOpen(this, function() {
		//cb is called once data is flushed
		this._writeStream.write(chunk, encoding, cb);
	});
};

SerialPort.prototype.close = function(cb) {
	var self = this;
	//If there is no callback, then just emit errors
	if(typeof cb !== "function") {
		cb = function(err) {
			if(err) {
				self.emit("error", err);
			}
		};
	}
	//Close both ReadStream and WriteStream Sockets
	self._readStream.end();
	self._readStream = self._writeStream = null;
	cb(null);
};

function whenOpen(self, cb) {
	if(self._writeStream == null) {
		self.on("open", cb);
	}
	else {
		cb.call(self);
	}
}<|endoftext|>


<commit_before>let Promise       = require('bluebird')
let child_process = require('child_process')

let redisRepository       = require('../Repositories/RedisRepository')
let projectRepoisitory    = require('../Repositories/ProjectRepository')
let projectTypeRepository = require('../Repositories/ProjectTypeRepository')
let dataRepository        = require('../Repositories/DataRepository')

let simulationService = require('./SimulationService')
let fileService       = require('./FileService')
let errorMsgService   = require('./ErrorMsgService')

let simulation = function (id, path, data, method) {
  simulationService.makeFile(path).then(() => {
    return simulationService.simulation(path, data)
  }).then(() => {
    handleSimulationData(id, path, method)
  }).catch(error => {
    //console.log(error)
  })
}

let handleSimulationData = function (id, path, method) {
  let configPath = '../.' + path + 'config'
  let config = require(configPath).config.simulationOutPutFileName

  let filesName  = ['baseSpin', 'bonusSpin', 'overallSpin', 'survivalRate']
  let tablesName = ['basegame', 'freegame', 'overall', 'survivalrate']

  for (let index in filesName) {
    if (config[filesName[index]]) {
      if (filesName[index] !== 'survivalRate') {
        dataRepository.uploadData(id, tablesName[index], path + 'result/' + config[filesName[index]] + csv, 'netWin' + ((filesName[index] === 'overallSpin') ? ',triger' : ''))
      } else {
        dataRepository.uploadData(id, tablesName[index], path + 'result/' + config[filesName[index]] + csv, 'id,hand,isSurvival')
      }
    }
  }
  for (let othersInfo of config.othersInfo) {
    let data = {
      name: othersInfo.infoName,
      data: path + 'result/' + othersInfo.fileName
    }
    if (method === 'insert') {
      dataRepository.insertData(id, 'others', data)
    } else if (method === 'update') {
      dataRepository.updateData(id, 'others', data)
    }
  }
}

// get all project
let getAllProject = function (token) {
  return new Promise((resolve, reject) => {
    // check if the token is valid
    redisRepository.getAccountId(token).then(accountId => {
      return projectRepoisitory.getAllProject(accountId)
    }).then(allProject => {
      resolve(allProject)
    }).catch(error => {
      if (error === 'token expired') {
        reject(errorMsgService.tokenExpired)
      } else {
        reject(errorMsgService.serverError)
      }
    })
  })
}

//get spectify project
let getProjectById = function (token, id) {
  return new Promise((resolve, reject) => {
    let data = {}
    // check if the token is valid
    redisRepository.getAccountId(token).then(accountId => {
      return projectRepoisitory.getProjectById(id)
    }).then(projectInfo => {
      resolve(projectInfo)
    }).catch(error => {
      if (error === 'token expired') {
        reject(errorMsgService.tokenExpired)
      } else if (error === 'file error') {
        reject(errorMsgService.fsError)
      } else {
        reject(errorMsgService.serverError)
      }
    })
  })
}

//get all type of project
let getAllProjectType = function (token) {
  return new Promise((resolve, reject) => {
    // check if the token is valid
    redisRepository.getAccountId(token).then(accountId => {
      return projectTypeRepository.getAllType()
    }).then(type => {
      resolve(type)
    }).catch(error => {
      if (error === 'token expired') {
        reject(errorMsgService.tokenExpired)
      } else {
        reject(errorMsgService.serverError)
      }
    })
  })
}

// get spectify type of project
let getProjectTypeById = function (token, id) {
  return new Promise((resolve, reject) => {
    // check if the token is valid
    redisRepository.getAccountId(token).then(accountId => {
      return projectTypeRepository.getTypeById(id)
    }).then(type => {
      resolve(type)
    }).catch(error => {
      if (error === 'token expired') {
        reject(errorMsgService.tokenExpired)
      } else if (error === 'Project type error') {
        reject(errorMsgService.noProjectType)
      } else {
        reject(errorMsgService.serverError)
      }
    })
  })
}

let dataSet  = ['name', 'block', 'thread', 'runTime', 'reels', 'rows', 'betCost']
let fileName = ['symbol', 'stops', 'payTable', 'attr', 'pattern']

let csv    = '.csv'
let folder = './userProject/'

// create a new project
let create = function (token, body) {
  let userId
  let data
  let id
  let path
  let fields
  let files
  return new Promise((resolve, reject) => {
    // check if the token is valid
    redisRepository.getAccountId(token).then(accountId => {
      userId = accountId
      data = {
        userId: userId
      }

      return fileService.processFormData(body)
    }).then(result => {
      fields = result.fields
      files  = result.files

      for (let i of dataSet) {
        if (fields[i] === undefined) {
          reject(errorMsgService.emptyInput)
          return
        } else {
          data[i] = fields[i]
        }
      }

      for (let i of fileName) {
        data[i] = './'
      }

      data.config    = './'
      data.gameLogic = './'

      return projectRepoisitory.createProject(data)
    }).then(() => {
      return projectRepoisitory.getNewestProject(userId)
    }).then(projectInfo => {
      id = projectInfo.id
      path = folder + userId + '/' + id + '/'
      return fileService.createFolder(path)
    }).then(() => {
      return fileService.createFolder(path + 'result')
    }).then(() => {
      let promise = []
      for (let i of fileName) {
        if (files[i] !== undefined) {
          if (!Array.isArray(files[i])) {
            data[i] = path + i + csv
            promise.push(fileService.moveFile(files[i].path, data[i]))
            if (i === 'payTable' && Array.isArray(files['stops'])) {
              data[i] = (data[i] + ',').repeat(files['stops'].length)
              data[i] = data[i].slice(0, -1)
            }
          } else {
            data[i] = ''
            files.reverse()
            for (let j in files[i]) {
              let filePath = path + i + j + csv
              data[i] += filePath + ','
              promise.push(fileService.moveFile(files[i][j].path, filePath))
            }
            data[i] = data[i].slice(0, -1)
          }
        }
      }

      if (files.config !== undefined) {
        data.config = path + 'config.js'
        promise.push(fileService.moveFile(files.config.path, data.config))
      }
      if (files.gameLogic !== undefined) {
        data.gameLogic = path + 'gameLogic.cu'
        promise.push(fileService.moveFile(files.gameLogic.path, data.gameLogic))
      }

      let inputFile = ',' + (files['symbol'] !== undefined ? data['symbol'] : '') + '\n'
      for (let i of ['reels', 'rows', 'betCost']) {
        inputFile += ',' + data[i] + '\n'
      }
      for (let i of ['stops', 'payTable', 'attr', 'pattern']) {
        if (files[i] !== undefined) {
          inputFile += ',' + data[i] + '\n'
        }
      }

      promise.push(fileService.createFile(path + 'input.csv', inputFile))
      promise.push(projectRepoisitory.updateProject(id, data))

      return Promise.all(promise)
    }).then(() => {
      simulation(id, path, data, 'insert')
      resolve()
    }).catch(error => {
      console.log(error)
      if (error === 'token expired') {
        reject(errorMsgService.tokenExpired)
      } else if (error === 'Project type error') {
        reject(errorMsgService.noProjectType)
      } else if (error === 'file error') {
        reject(errorMsgService.fsError)
      } else {
        reject(errorMsgService.serverError)
      }
    })
  })
}

// update project
let update = function (token, id, body) {
  let data
  let userId
  let path
  let fields
  let files
  let oldData
  return new Promise((resolve, reject) => {
    // check if the token is valid
    redisRepository.getAccountId(token).then(accountId => {
      userId = accountId
      path   = folder + userId + '/' + id + '/'

      data = {
        userId: userId
      }
      return projectRepoisitory.getProjectById(id)
    }).then(data => {
      oldData = data
      return fileService.processFormData(body)
    }).then(result => {
      fields = result.fields
      files = result.files

      for (let i of dataSet) {
        if (fields[i] !== undefined) {
          data[i] = fields[i]
        }
      }

      let promise = []

      for (let i of fileName) {
        if (files[i] !== undefined) {
          if (!Array.isArray(files[i])) {
            data[i] = path + i + csv
            promise.push(fileService.moveFile(files[i].path, data[i]))
            if (i === 'payTable' && Array.isArray(files['stops'])) {
              data[i] = (data[i] + ',').repeat(files['stops'].length)
              data[i] = data[i].slice(0, -1)
            }
          } else {
            data[i] = ''
            files.reverse()
            for (let j in files[i]) {
              let filePath = path + i + j + csv
              data[i] += filePath + ','
              promise.push(fileService.moveFile(files[i][j].path, filePath))
            }
            data[i] = data[i].slice(0, -1)
          }

        }
      }

      if (files.config !== undefined) {
        data.config = path + 'config.js'
        promise.push(fileService.moveFile(files.config.path, data.config))
      }
      if (files.gameLogic !== undefined) {
        data.gameLogic = path + 'gameLogic.cu'
        promise.push(fileService.moveFile(files.gameLogic.path, data.gameLogic))
      }

      let inputFile = ''
      for (let i of ['symbol', 'reels', 'rows', 'betCost', 'stops', 'payTable', 'attr', 'pattern']) {
        inputFile += ',' + (data[i] !== undefined ? data[i] : oldData[i]) + '\n'
      }

      promise.push(fileService.createFile(path + 'input.csv', inputFile))
      promise.push(projectRepoisitory.updateProject(id, data))

      return Promise.all(promise)
    }).then(() => {
      simulation(id, path, data, 'update')
      resolve()
    }).catch(error => {
      console.log(error)
      if (error === 'token expired') {
        reject(errorMsgService.tokenExpired)
      } else if (error === 'file error') {
        reject(errorMsgService.fsError)
      } else {
        reject(errorMsgService.serverError)
      }
    })
  })
}

//delete project
let deleteProject = function (token, id) {
  let userId
  return new Promise((resolve, reject) => {
    // check if the token is valid
    redisRepository.getAccountId(token).then(accountId => {
      userId = accountId
      return projectRepoisitory.deleteProject(id)
    }).then(() => {
      return fileService.deleteFolder(folder + userId + '/' + id)
    }).then(() => {
      resolve()
    }).catch(error => {
      if (error === 'token expired') {
        reject(errorMsgService.tokenExpired)
      } else if (error === 'file error') {
        reject(errorMsgService.fsError)
      } else {
        reject(errorMsgService.serverError)
      }
    })
  })
}

let getConfig = function (token, id) {
  let userId
  return new Promise((resolve, reject) => {
    redisRepository.getAccountId(token).then(accountId => {
      let path = '../../userProject/' + accountId + '/' + id + '/config'
      let config = require(path)
      resolve(config.config)
    }).catch(error => {
      if (error === 'token expired') {
        reject(errorMsgService.tokenExpired)
      } else {
        reject(errorMsgService.serverError)
      }
    })
  })
}

module.exports = {
  getAllProject:      getAllProject,
  getProjectById:     getProjectById,
  getAllProjectType:  getAllProjectType,
  getProjectTypeById: getProjectTypeById,
  create:             create,
  update:             update,
  deleteProject:      deleteProject,
  getConfig:          getConfig
}<commit_msg>fix some bugs<commit_after>let Promise       = require('bluebird')
let child_process = require('child_process')

let redisRepository       = require('../Repositories/RedisRepository')
let projectRepoisitory    = require('../Repositories/ProjectRepository')
let projectTypeRepository = require('../Repositories/ProjectTypeRepository')
let dataRepository        = require('../Repositories/DataRepository')

let simulationService = require('./SimulationService')
let fileService       = require('./FileService')
let errorMsgService   = require('./ErrorMsgService')

let simulation = function (id, path, data, method) {
  simulationService.makeFile(path).then(() => {
    return simulationService.simulation(path, data)
  }).then(() => {
    handleSimulationData(id, path, method)
  }).catch(error => {
    //console.log(error)
  })
}

let handleSimulationData = function (id, path, method) {
  let configPath = '../.' + path + 'config'
  let config = require(configPath).config.simulationOutPutFileName

  let filesName  = ['baseSpin', 'bonusSpin', 'overallSpin', 'survivalRate']
  let tablesName = ['basegame', 'freegame', 'overall', 'survivalrate']

  for (let index in filesName) {
    if (config[filesName[index]]) {
      if (filesName[index] !== 'survivalRate') {
        dataRepository.uploadData(id, tablesName[index], path + 'result/' + config[filesName[index]] + csv, 'netWin' + ((filesName[index] === 'overallSpin') ? ',triger' : ''))
      } else {
        dataRepository.uploadData(id, tablesName[index], path + 'result/' + config[filesName[index]] + csv, 'id,hand,isSurvival')
      }
    }
  }
  for (let othersInfo of config.othersInfo) {
    let data = {
      name: othersInfo.infoName,
      data: path + 'result/' + othersInfo.fileName
    }
    if (method === 'insert') {
      dataRepository.insertData(id, 'others', data)
    } else if (method === 'update') {
      dataRepository.updateData(id, 'others', data)
    }
  }
}

// get all project
let getAllProject = function (token) {
  return new Promise((resolve, reject) => {
    // check if the token is valid
    redisRepository.getAccountId(token).then(accountId => {
      return projectRepoisitory.getAllProject(accountId)
    }).then(allProject => {
      resolve(allProject)
    }).catch(error => {
      if (error === 'token expired') {
        reject(errorMsgService.tokenExpired)
      } else {
        reject(errorMsgService.serverError)
      }
    })
  })
}

//get spectify project
let getProjectById = function (token, id) {
  return new Promise((resolve, reject) => {
    let data = {}
    // check if the token is valid
    redisRepository.getAccountId(token).then(accountId => {
      return projectRepoisitory.getProjectById(id)
    }).then(projectInfo => {
      resolve(projectInfo)
    }).catch(error => {
      if (error === 'token expired') {
        reject(errorMsgService.tokenExpired)
      } else if (error === 'file error') {
        reject(errorMsgService.fsError)
      } else {
        reject(errorMsgService.serverError)
      }
    })
  })
}

//get all type of project
let getAllProjectType = function (token) {
  return new Promise((resolve, reject) => {
    // check if the token is valid
    redisRepository.getAccountId(token).then(accountId => {
      return projectTypeRepository.getAllType()
    }).then(type => {
      resolve(type)
    }).catch(error => {
      if (error === 'token expired') {
        reject(errorMsgService.tokenExpired)
      } else {
        reject(errorMsgService.serverError)
      }
    })
  })
}

// get spectify type of project
let getProjectTypeById = function (token, id) {
  return new Promise((resolve, reject) => {
    // check if the token is valid
    redisRepository.getAccountId(token).then(accountId => {
      return projectTypeRepository.getTypeById(id)
    }).then(type => {
      resolve(type)
    }).catch(error => {
      if (error === 'token expired') {
        reject(errorMsgService.tokenExpired)
      } else if (error === 'Project type error') {
        reject(errorMsgService.noProjectType)
      } else {
        reject(errorMsgService.serverError)
      }
    })
  })
}

let dataSet  = ['name', 'block', 'thread', 'runTime', 'reels', 'rows', 'betCost']
let fileName = ['symbol', 'stops', 'payTable', 'attr', 'pattern']

let csv    = '.csv'
let folder = './userProject/'

// create a new project
let create = function (token, body) {
  let userId
  let data
  let id
  let path
  let fields
  let files
  return new Promise((resolve, reject) => {
    // check if the token is valid
    redisRepository.getAccountId(token).then(accountId => {
      userId = accountId
      data = {
        userId: userId
      }

      return fileService.processFormData(body)
    }).then(result => {
      fields = result.fields
      files  = result.files

      for (let i of dataSet) {
        if (fields[i] === undefined) {
          reject(errorMsgService.emptyInput)
          return
        } else {
          data[i] = fields[i]
        }
      }

      for (let i of fileName) {
        data[i] = './'
      }

      data.config    = './'
      data.gameLogic = './'

      return projectRepoisitory.createProject(data)
    }).then(() => {
      return projectRepoisitory.getNewestProject(userId)
    }).then(projectInfo => {
      id = projectInfo.id
      path = folder + userId + '/' + id + '/'
      return fileService.createFolder(path)
    }).then(() => {
      return fileService.createFolder(path + 'result')
    }).then(() => {
      let promise = []
      for (let i of fileName) {
        if (files[i] !== undefined) {
          if (!Array.isArray(files[i])) {
            data[i] = path + i + csv
            promise.push(fileService.moveFile(files[i].path, data[i]))
            if (i === 'payTable' && Array.isArray(files['stops'])) {
              data[i] = (data[i] + ',').repeat(files['stops'].length)
              data[i] = data[i].slice(0, -1)
            }
          } else {
            data[i] = ''
            files[i].reverse()
            for (let j in files[i]) {
              let filePath = path + i + j + csv
              data[i] += filePath + ','
              promise.push(fileService.moveFile(files[i][j].path, filePath))
            }
            data[i] = data[i].slice(0, -1)
          }
        }
      }

      if (files.config !== undefined) {
        data.config = path + 'config.js'
        promise.push(fileService.moveFile(files.config.path, data.config))
      }
      if (files.gameLogic !== undefined) {
        data.gameLogic = path + 'gameLogic.cu'
        promise.push(fileService.moveFile(files.gameLogic.path, data.gameLogic))
      }

      let inputFile = ',' + (files['symbol'] !== undefined ? data['symbol'] : '') + '\n'
      for (let i of ['reels', 'rows', 'betCost']) {
        inputFile += ',' + data[i] + '\n'
      }
      for (let i of ['stops', 'payTable', 'attr', 'pattern']) {
        if (files[i] !== undefined) {
          inputFile += ',' + data[i] + '\n'
        }
      }

      promise.push(fileService.createFile(path + 'input.csv', inputFile))
      promise.push(projectRepoisitory.updateProject(id, data))

      return Promise.all(promise)
    }).then(() => {
      simulation(id, path, data, 'insert')
      resolve()
    }).catch(error => {
      console.log(error)
      if (error === 'token expired') {
        reject(errorMsgService.tokenExpired)
      } else if (error === 'Project type error') {
        reject(errorMsgService.noProjectType)
      } else if (error === 'file error') {
        reject(errorMsgService.fsError)
      } else {
        reject(errorMsgService.serverError)
      }
    })
  })
}

// update project
let update = function (token, id, body) {
  let data
  let userId
  let path
  let fields
  let files
  let oldData
  return new Promise((resolve, reject) => {
    // check if the token is valid
    redisRepository.getAccountId(token).then(accountId => {
      userId = accountId
      path   = folder + userId + '/' + id + '/'

      data = {
        userId: userId
      }
      return projectRepoisitory.getProjectById(id)
    }).then(data => {
      oldData = data
      return fileService.processFormData(body)
    }).then(result => {
      fields = result.fields
      files = result.files

      for (let i of dataSet) {
        if (fields[i] !== undefined) {
          data[i] = fields[i]
        }
      }

      let promise = []

      for (let i of fileName) {
        if (files[i] !== undefined) {
          if (!Array.isArray(files[i])) {
            data[i] = path + i + csv
            promise.push(fileService.moveFile(files[i].path, data[i]))
            if (i === 'payTable' && Array.isArray(files['stops'])) {
              data[i] = (data[i] + ',').repeat(files['stops'].length)
              data[i] = data[i].slice(0, -1)
            }
          } else {
            data[i] = ''
            files[i].reverse()
            for (let j in files[i]) {
              let filePath = path + i + j + csv
              data[i] += filePath + ','
              promise.push(fileService.moveFile(files[i][j].path, filePath))
            }
            data[i] = data[i].slice(0, -1)
          }

        }
      }

      if (files.config !== undefined) {
        data.config = path + 'config.js'
        promise.push(fileService.moveFile(files.config.path, data.config))
      }
      if (files.gameLogic !== undefined) {
        data.gameLogic = path + 'gameLogic.cu'
        promise.push(fileService.moveFile(files.gameLogic.path, data.gameLogic))
      }

      let inputFile = ''
      for (let i of ['symbol', 'reels', 'rows', 'betCost', 'stops', 'payTable', 'attr', 'pattern']) {
        inputFile += ',' + (data[i] !== undefined ? data[i] : oldData[i]) + '\n'
      }

      promise.push(fileService.createFile(path + 'input.csv', inputFile))
      promise.push(projectRepoisitory.updateProject(id, data))

      return Promise.all(promise)
    }).then(() => {
      simulation(id, path, data, 'update')
      resolve()
    }).catch(error => {
      console.log(error)
      if (error === 'token expired') {
        reject(errorMsgService.tokenExpired)
      } else if (error === 'file error') {
        reject(errorMsgService.fsError)
      } else {
        reject(errorMsgService.serverError)
      }
    })
  })
}

//delete project
let deleteProject = function (token, id) {
  let userId
  return new Promise((resolve, reject) => {
    // check if the token is valid
    redisRepository.getAccountId(token).then(accountId => {
      userId = accountId
      return projectRepoisitory.deleteProject(id)
    }).then(() => {
      return fileService.deleteFolder(folder + userId + '/' + id)
    }).then(() => {
      resolve()
    }).catch(error => {
      if (error === 'token expired') {
        reject(errorMsgService.tokenExpired)
      } else if (error === 'file error') {
        reject(errorMsgService.fsError)
      } else {
        reject(errorMsgService.serverError)
      }
    })
  })
}

let getConfig = function (token, id) {
  let userId
  return new Promise((resolve, reject) => {
    redisRepository.getAccountId(token).then(accountId => {
      let path = '../../userProject/' + accountId + '/' + id + '/config'
      let config = require(path)
      resolve(config.config)
    }).catch(error => {
      if (error === 'token expired') {
        reject(errorMsgService.tokenExpired)
      } else {
        reject(errorMsgService.serverError)
      }
    })
  })
}

module.exports = {
  getAllProject:      getAllProject,
  getProjectById:     getProjectById,
  getAllProjectType:  getAllProjectType,
  getProjectTypeById: getProjectTypeById,
  create:             create,
  update:             update,
  deleteProject:      deleteProject,
  getConfig:          getConfig
}<|endoftext|>


<commit_before>import React from 'react';
import { Link } from 'react-router-dom';

const HelpBox = ({showHelp}) => {
	if (showHelp) {
		return (

				Here you can see an overview of your team's progress.
				Open the menu in the top right corner to navigate to other pages.

				You can also use the refresh button to refresh the data displayed throughout the app.
				If you're concerned about data usage, check out the raw facts <Link to='/dashboard/about'>here</Link>.

		);
	}
	else return null;
}

export default HelpBox;
<commit_msg>[FIX] Fix formatting on help box<commit_after>import React from 'react';
import { Link } from 'react-router-dom';

const HelpBox = ({showHelp}) => {
	if (showHelp) {
		return (

				Here you can see an overview of your team's progress.
				Open the menu in the top right corner to navigate to other pages.
				You can also use the refresh button to refresh the data displayed throughout the app.
				If you're concerned about data usage, check out the raw facts <Link to='/dashboard/about'>here</Link>.

		);
	}
	else return null;
}

export default HelpBox;
<|endoftext|>


<commit_before>var Promise = require('promise');

function Piece (color, symbol) {
    var piece = this;
    piece.color = color;
    piece.symbol = symbol;

    piece.toString = function () {
        // implicitly depends on package 'colors'
        return piece.symbol[piece.color];
    }

    // piece.match_color :: Piece -> Boolean
    piece.match_color = function (other) {
        return (other.color == piece.color);
    }

    // piece.match_symbol :: Piece -> Boolean
    piece.match_symbol = function (other) {
        return (other.symbol == piece.symbol);
    }

    // piece.matching :: Piece -> [ String ]
    piece.matching = function (other) {
        var result = [];
        if (piece.match_color(other))  result.push('color');
        if (piece.match_symbol(other)) result.push('symbol');
        return result;
    }
}

function Board () {
    var board = this;
    board.cells = [];
    board.y_min = board.x_min = 1;
    board.y_num = board.y_max = 8;
    board.x_num = board.x_max = 12;

    board.start_positions =
        [ { x: board.x_min,         y: board.y_min         }
        , { x: board.x_max,         y: board.y_min         }
        , { x: board.x_min,         y: board.y_max         }
        , { x: board.x_max,         y: board.y_max         }
        , { x: board.x_max / 2,     y: board.y_max / 2     }
        , { x: board.x_max / 2 + 1, y: board.y_max / 2 + 1 }
        ];

    var n_fields = board.y_num * board.x_num;

    function flatten_xy (x, y) {
        return (y - board.y_min) * board.x_num + (x - board.x_min);
    }

    board.valid_xy = function (x, y) {
        return (x >= board.x_min) && (x <= board.x_max) && (y >= board.y_min) && (y <= board.y_max);
    }

    board.at = function (x, y) {
        if (board.valid_xy(x, y))
            return board.cells[flatten_xy(x, y)]
        else
            return null;
    }

    board.free = function (x, y) {
        return (!(board.at(x, y) instanceof Piece));
    }

    board.set = function (x, y, value) {
        board.cells[flatten_xy(x, y)] = value;
    }

    board.cli_draw = function () {
        var empty_cell_string = '☐';
        process.stdout.write('   '); // leave room for the y axis
        for (var x = 1; x <= board.x_max; x++) {
            if (x < 10)
                process.stdout.write(' ' + x + ' ')
            else
                process.stdout.write('' + x + ' ');
        }
        process.stdout.write("\n");
        for (var i = 0; i < n_fields; i++) {
            if (i % board.x_num == 0) {
                if (i > 0) process.stdout.write("\n");
                var y = (i / board.x_num) + 1;
                if (y < 10)
                    process.stdout.write(' ' + y + ' ')
                else
                    process.stdout.write('' + y + ' ');
            }
            if (board.cells[i] instanceof Piece)
                process.stdout.write(' ' + board.cells[i].toString() + ' ')
            else
                process.stdout.write(' ' + empty_cell_string + ' ');
        }
        process.stdout.write("\n");
    }

    board.neighbours = function (x, y) {
        return [ board.at(x - 1, y)
               , board.at(x + 1, y)
               , board.at(x, y - 1)
               , board.at(x, y + 1)
               ].filter(function (cell) { return cell != null })
    }
}

function a_concat_b (a, b) { return a.concat(b); }

// cartesian_product :: [ [a] ] -> [ [a] ]
function cartesian_product (arrays) {
    return arrays.reduce(function (as, bs) {
        if (as.length == 0) // :( is there a better way?
            as = [ [] ];
        return (
            as.map(function (a) {
               return bs.map(function (b) {
                   return a.concat([ b ]);
               });
            }).reduce(a_concat_b)
        );
    }, [ [] ]);
};

Matches = (function () {
    // all :: Piece -> [ Piece ] -> [ [String] ]
    function all (piece, pieces) {
        var matches = pieces.map(function (p) {
            return p.matching(piece);
        });
        return cartesian_product(matches);
    }

    // grouped_counts :: Piece -> [ Piece ] -> [ Object String Integer ]
    function grouped_counts (piece, pieces) {
        return all(piece, pieces).map(function (matches) {
            // matches :: [String]
            return matches.reduce(function (acc, match) {
                // match :: String
                acc[match] = acc[match] + 1;
                return acc;
            }, { 'color': 0, 'symbol': 0 });
        });
    }

    // satisfies :: Piece -> [ Piece ] -> [ Object String Integer ] -> Boolean
    function satisfies (piece, pieces, predicates) {
        return grouped_counts(piece, pieces).some(function (grouped) {
            return predicates.some(function (pred_grouped) {
                var satisfied = true;
                [ 'color', 'symbol' ].forEach(function (match) {
                    // match :: String
                    if (pred_grouped[match]) {
                        if (grouped[match]) {
                            satisfied = satisfied && (grouped[match] >= pred_grouped[match])
                        } else {
                            satisfied = false;
                        }
                    }
                });
                return satisfied;
            });
        });
    }
    return { all:            all
           , grouped_counts: grouped_counts
           , satisfies:      satisfies
           };
})();

function Game () {
    var game = this;
    var turns = [];

    var all_pieces = (function () {
        var colors =
            [ 'blue'
            , 'cyan'
            , 'green'
            , 'magenta'
            , 'red'
            , 'yellow'
            ];
        var symbols = [ 'a', 'b', 'c', 'd', 'e', 'f' ];
        var pieces = [];
        colors.forEach(function (color) {
            symbols.forEach(function (symbol) {
                pieces.push(new Piece(color, symbol));
            });
        });
        return pieces.concat(pieces); // there's two of each
    })();

    /**
     * Randomize array element order in-place.
     * Using Fisher-Yates shuffle algorithm.
     * http://stackoverflow.com/questions/2450954/how-to-randomize-shuffle-a-javascript-array
     */
    function shuffle (array) {
        for (var i = array.length - 1; i > 0; i--) {
            var j = Math.floor(Math.random() * (i + 1));
            var temp = array[i];
            array[i] = array[j];
            array[j] = temp;
        }
        return array;
    }

    var pieces = shuffle(all_pieces);
    var board = new Board;

    function put (x, y, piece) {
        turns.push([ x, y, piece ]);
        board.set(x, y, piece);
    }

    // matching :: Piece -> [ Piece ] -> Boolean
    function matching(piece, neighbours) {
        if (neighbours.length == 0)
            return false;
        if (neighbours.length == 1) {
            return Matches.satisfies(piece, neighbours,
                [ { 'color':  1 }
                , { 'symbol': 1 }
                ]
            );
        }
        if (neighbours.length == 2) {
            return Matches.satisfies(piece, neighbours,
                [ { 'color': 1, 'symbol': 1 } ]
            );
        }
        if (neighbours.length == 3) {
            return Matches.satisfies(piece, neighbours,
                [ { 'color': 1, 'symbol': 2 }
                , { 'color': 2, 'symbol': 1 }
                ]
            );
        }
        if (neighbours.length == 4) {
            return Matches.satisfies(piece, neighbours,
                [ { 'color': 2, 'symbol': 2 } ]
            );
        }
        console.log("Something's up with the matching.");
    }

    function valid_placing (x, y, piece) {
        return board.valid_xy(x, y) &&
               board.free(x, y) &&
               matching(piece, board.neighbours(x, y));
    }

    function turn () {
        return turns.length - board.start_positions.length + 1;
    }

    game.completed = function () {
        // TODO !or no more valid moves!
        return (pieces.length == 0);
    }

    // game.next :: (Int -> Piece -> Board -> Promise Point)
    //           -> Promise Game
    game.next = function (fn) {
        return new Promise(function (resolve, reject) {
            var piece = pieces.shift();
            fn(turn(), piece, board).
                then(function (point) {
                    if (valid_placing(point.x, point.y, piece)) {
                        put(point.x, point.y, piece);
                        resolve(game);
                    } else {
                        pieces.unshift(piece);
                        reject('invalid move');
                    }
                });
        });
    }

    // game.loop :: (Int -> Piece -> Board -> Promise Point)
    //           -> (String -> Void)
    //           -> Promise Game
    game.loop = function (user_turn, fn_error) {
        if (!game.completed()) {
            return game.next(user_turn).then(
                function (game) {
                    return game.loop(user_turn, fn_error);
                },
                function (message) {
                    fn_error(message);
                    return game.loop(user_turn, fn_error);
                });
        } else {
            return new Promise(function (resolve, reject) {
                resolve(game);
            });
        }
    }

    function put_initial_pieces () {
        board.start_positions.forEach(function (point) {
            put(point.x, point.y, pieces.shift());
        });
    }

    put_initial_pieces();
}

function main (dependencies) {
    // cli_ask :: String -> Promise String
    function cli_ask (question) {
        var rl = dependencies.readline.createInterface({
            input:  process.stdin,
            output: process.stdout
        });
        return new Promise(function (resolve, reject) {
            rl.question(question, function (answer) {
                rl.close();
                resolve(answer);
            });

        });
    }

    // cli_user_turn :: Int -> Piece -> Board -> Promise Point
    function cli_user_turn (n_turn, piece, board) {
        process.stdout.write("\n== turn " + n_turn + " ==\n\n");
        board.cli_draw();
        console.log("\ncurrent piece: " + piece.toString());
        return cli_ask('x,y: ').then(function (input_string) {
            xy = input_string.split(/\s*,\s*/);
            return { x: parseInt(xy[0])
                   , y: parseInt(xy[1])
                   }
        });
    }

    (new Game)
        .loop(cli_user_turn, console.log)
        .then(function (game) {
            console.log("COMPLETED");
        });
}

if (require.main === module) {
    main(
        { colors:   require('colors')
        , readline: require('readline')
        }
    );
} else {
    module.exports.Piece   = Piece;
    module.exports.Board   = Board;
    module.exports.Game    = Game;
    module.exports.Matches = Matches;
}
<commit_msg>comment: dependency<commit_after>var Promise = require('promise');

function Piece (color, symbol) {
    var piece = this;
    piece.color = color;
    piece.symbol = symbol;

    piece.toString = function () {
        // implicitly depends on package 'colors'
        return piece.symbol[piece.color];
    }

    // piece.match_color :: Piece -> Boolean
    piece.match_color = function (other) {
        return (other.color == piece.color);
    }

    // piece.match_symbol :: Piece -> Boolean
    piece.match_symbol = function (other) {
        return (other.symbol == piece.symbol);
    }

    // piece.matching :: Piece -> [ String ]
    piece.matching = function (other) {
        var result = [];
        if (piece.match_color(other))  result.push('color');
        if (piece.match_symbol(other)) result.push('symbol');
        return result;
    }
}

function Board () {
    var board = this;
    board.cells = [];
    board.y_min = board.x_min = 1;
    board.y_num = board.y_max = 8;
    board.x_num = board.x_max = 12;

    board.start_positions =
        [ { x: board.x_min,         y: board.y_min         }
        , { x: board.x_max,         y: board.y_min         }
        , { x: board.x_min,         y: board.y_max         }
        , { x: board.x_max,         y: board.y_max         }
        , { x: board.x_max / 2,     y: board.y_max / 2     }
        , { x: board.x_max / 2 + 1, y: board.y_max / 2 + 1 }
        ];

    var n_fields = board.y_num * board.x_num;

    function flatten_xy (x, y) {
        return (y - board.y_min) * board.x_num + (x - board.x_min);
    }

    board.valid_xy = function (x, y) {
        return (x >= board.x_min) && (x <= board.x_max) && (y >= board.y_min) && (y <= board.y_max);
    }

    board.at = function (x, y) {
        if (board.valid_xy(x, y))
            return board.cells[flatten_xy(x, y)]
        else
            return null;
    }

    board.free = function (x, y) {
        return (!(board.at(x, y) instanceof Piece));
    }

    board.set = function (x, y, value) {
        board.cells[flatten_xy(x, y)] = value;
    }

    // implicitly depends on package 'colors'
    board.cli_draw = function () {
        var empty_cell_string = '☐';
        process.stdout.write('   '); // leave room for the y axis
        for (var x = 1; x <= board.x_max; x++) {
            if (x < 10)
                process.stdout.write(' ' + x + ' ')
            else
                process.stdout.write('' + x + ' ');
        }
        process.stdout.write("\n");
        for (var i = 0; i < n_fields; i++) {
            if (i % board.x_num == 0) {
                if (i > 0) process.stdout.write("\n");
                var y = (i / board.x_num) + 1;
                if (y < 10)
                    process.stdout.write(' ' + y + ' ')
                else
                    process.stdout.write('' + y + ' ');
            }
            if (board.cells[i] instanceof Piece)
                process.stdout.write(' ' + board.cells[i].toString() + ' ')
            else
                process.stdout.write(' ' + empty_cell_string + ' ');
        }
        process.stdout.write("\n");
    }

    board.neighbours = function (x, y) {
        return [ board.at(x - 1, y)
               , board.at(x + 1, y)
               , board.at(x, y - 1)
               , board.at(x, y + 1)
               ].filter(function (cell) { return cell != null })
    }
}

function a_concat_b (a, b) { return a.concat(b); }

// cartesian_product :: [ [a] ] -> [ [a] ]
function cartesian_product (arrays) {
    return arrays.reduce(function (as, bs) {
        if (as.length == 0) // :( is there a better way?
            as = [ [] ];
        return (
            as.map(function (a) {
               return bs.map(function (b) {
                   return a.concat([ b ]);
               });
            }).reduce(a_concat_b)
        );
    }, [ [] ]);
};

Matches = (function () {
    // all :: Piece -> [ Piece ] -> [ [String] ]
    function all (piece, pieces) {
        var matches = pieces.map(function (p) {
            return p.matching(piece);
        });
        return cartesian_product(matches);
    }

    // grouped_counts :: Piece -> [ Piece ] -> [ Object String Integer ]
    function grouped_counts (piece, pieces) {
        return all(piece, pieces).map(function (matches) {
            // matches :: [String]
            return matches.reduce(function (acc, match) {
                // match :: String
                acc[match] = acc[match] + 1;
                return acc;
            }, { 'color': 0, 'symbol': 0 });
        });
    }

    // satisfies :: Piece -> [ Piece ] -> [ Object String Integer ] -> Boolean
    function satisfies (piece, pieces, predicates) {
        return grouped_counts(piece, pieces).some(function (grouped) {
            return predicates.some(function (pred_grouped) {
                var satisfied = true;
                [ 'color', 'symbol' ].forEach(function (match) {
                    // match :: String
                    if (pred_grouped[match]) {
                        if (grouped[match]) {
                            satisfied = satisfied && (grouped[match] >= pred_grouped[match])
                        } else {
                            satisfied = false;
                        }
                    }
                });
                return satisfied;
            });
        });
    }
    return { all:            all
           , grouped_counts: grouped_counts
           , satisfies:      satisfies
           };
})();

function Game () {
    var game = this;
    var turns = [];

    var all_pieces = (function () {
        var colors =
            [ 'blue'
            , 'cyan'
            , 'green'
            , 'magenta'
            , 'red'
            , 'yellow'
            ];
        var symbols = [ 'a', 'b', 'c', 'd', 'e', 'f' ];
        var pieces = [];
        colors.forEach(function (color) {
            symbols.forEach(function (symbol) {
                pieces.push(new Piece(color, symbol));
            });
        });
        return pieces.concat(pieces); // there's two of each
    })();

    /**
     * Randomize array element order in-place.
     * Using Fisher-Yates shuffle algorithm.
     * http://stackoverflow.com/questions/2450954/how-to-randomize-shuffle-a-javascript-array
     */
    function shuffle (array) {
        for (var i = array.length - 1; i > 0; i--) {
            var j = Math.floor(Math.random() * (i + 1));
            var temp = array[i];
            array[i] = array[j];
            array[j] = temp;
        }
        return array;
    }

    var pieces = shuffle(all_pieces);
    var board = new Board;

    function put (x, y, piece) {
        turns.push([ x, y, piece ]);
        board.set(x, y, piece);
    }

    // matching :: Piece -> [ Piece ] -> Boolean
    function matching(piece, neighbours) {
        if (neighbours.length == 0)
            return false;
        if (neighbours.length == 1) {
            return Matches.satisfies(piece, neighbours,
                [ { 'color':  1 }
                , { 'symbol': 1 }
                ]
            );
        }
        if (neighbours.length == 2) {
            return Matches.satisfies(piece, neighbours,
                [ { 'color': 1, 'symbol': 1 } ]
            );
        }
        if (neighbours.length == 3) {
            return Matches.satisfies(piece, neighbours,
                [ { 'color': 1, 'symbol': 2 }
                , { 'color': 2, 'symbol': 1 }
                ]
            );
        }
        if (neighbours.length == 4) {
            return Matches.satisfies(piece, neighbours,
                [ { 'color': 2, 'symbol': 2 } ]
            );
        }
        console.log("Something's up with the matching.");
    }

    function valid_placing (x, y, piece) {
        return board.valid_xy(x, y) &&
               board.free(x, y) &&
               matching(piece, board.neighbours(x, y));
    }

    function turn () {
        return turns.length - board.start_positions.length + 1;
    }

    game.completed = function () {
        // TODO !or no more valid moves!
        return (pieces.length == 0);
    }

    // game.next :: (Int -> Piece -> Board -> Promise Point)
    //           -> Promise Game
    game.next = function (fn) {
        return new Promise(function (resolve, reject) {
            var piece = pieces.shift();
            fn(turn(), piece, board).
                then(function (point) {
                    if (valid_placing(point.x, point.y, piece)) {
                        put(point.x, point.y, piece);
                        resolve(game);
                    } else {
                        pieces.unshift(piece);
                        reject('invalid move');
                    }
                });
        });
    }

    // game.loop :: (Int -> Piece -> Board -> Promise Point)
    //           -> (String -> Void)
    //           -> Promise Game
    game.loop = function (user_turn, fn_error) {
        if (!game.completed()) {
            return game.next(user_turn).then(
                function (game) {
                    return game.loop(user_turn, fn_error);
                },
                function (message) {
                    fn_error(message);
                    return game.loop(user_turn, fn_error);
                });
        } else {
            return new Promise(function (resolve, reject) {
                resolve(game);
            });
        }
    }

    function put_initial_pieces () {
        board.start_positions.forEach(function (point) {
            put(point.x, point.y, pieces.shift());
        });
    }

    put_initial_pieces();
}

function main (dependencies) {
    // cli_ask :: String -> Promise String
    function cli_ask (question) {
        var rl = dependencies.readline.createInterface({
            input:  process.stdin,
            output: process.stdout
        });
        return new Promise(function (resolve, reject) {
            rl.question(question, function (answer) {
                rl.close();
                resolve(answer);
            });

        });
    }

    // cli_user_turn :: Int -> Piece -> Board -> Promise Point
    function cli_user_turn (n_turn, piece, board) {
        process.stdout.write("\n== turn " + n_turn + " ==\n\n");
        board.cli_draw();
        console.log("\ncurrent piece: " + piece.toString());
        return cli_ask('x,y: ').then(function (input_string) {
            xy = input_string.split(/\s*,\s*/);
            return { x: parseInt(xy[0])
                   , y: parseInt(xy[1])
                   }
        });
    }

    (new Game)
        .loop(cli_user_turn, console.log)
        .then(function (game) {
            console.log("COMPLETED");
        });
}

if (require.main === module) {
    main(
        { colors:   require('colors')
        , readline: require('readline')
        }
    );
} else {
    module.exports.Piece   = Piece;
    module.exports.Board   = Board;
    module.exports.Game    = Game;
    module.exports.Matches = Matches;
}
<|endoftext|>