<commit_before>var to_preflop = 0;
var push = false;
var lock = false;

function socket_listens_players(socket, table) {
    var player; // Current player.
    var curseat; // Current seat.
    var channel; // Channel involved.
    //table = get_table(table.id, tables);

    /*socket.on("nb player", function(nb) {
    	nb_player = nb;
    	console.log('first '+ nb_player);
    })*/
    socket.on("is valid nickname", function(nickname, seat_idx) {
        curseat = get_seat(table.seats, seat_idx);
        channel = get_private_id(table.private_ids, seat_idx);
        if (!nickname || check_blanks(nickname) || nickname.length < 2 || nickname.length > 8) {
            console.log("Invalid nickname!");
            socket.emit("is valid nickname info", "invalid");
        } else if (table.nicknames.indexOf(nickname) != -1) {
            console.log("Nickname already taken!");
            socket.emit("is valid nickname info", "already taken");
        } else if (curseat.state != "available")
            socket.emit("is valid nickname info", "seat busy");
        else {
            console.log(nickname + " is valid!");
            socket.emit("is valid nickname info", "valid", nickname);
            table.nicknames.push(nickname); // Add the user nickname to the table nicknames array.
            if (table.players_nb < 6)
                ++table.players_nb;
            console.log("There are now " + table.players_nb + " seated at the table (imo of course)!");
            player = new Player(seat_idx, nickname, +table.start_bankroll, -1, -1, -1, -1);
            curseat.state = "busy";
            curseat.player = player;
            console.log("Seat" + seat_idx + " is now " + curseat.state);
            io.to(table.id).emit("new player", player);
            if (table.playing_seats.indexOf(seat_idx) != -1)
                return;
            if (table.game.moment == "waiting")
                table.playing_seats.push(seat_idx);
            for (var i = 0; i < table.playing_seats.length; i++)
                get_seat(table.seats, table.playing_seats[i]).state = "playing";
            if (table.playing_seats.length >= 1 && lock)
                new_cashgame(socket, table);
            else {
                if (table.playing_seats.length >= 1 && table.game.moment == "waiting") {
                    if (table.playing_seats.length > 1) {
                        return;
                    }
                    tryChrono(socket, table);
                }
            }
            return;
        }
    });
    socket.on("get seated players", function() {
        send_seats_infos(table);
    });
    socket.on("get board", function() {
        if (table.game.board.length >= 3)
            io.to(table.id).emit("send flop", table.game.board[0], table.game.board[1], table.game.board[2]);
        if (table.game.board.length >= 4)
            io.to(table.id).emit("send turn", table.game.board[3]);
        if (table.game.board.length === 5)
            io.to(table.id).emit("send river", table.game.board[4]);
    });
    socket.on("to preflop", function(init) {
        to_preflop = init;
    });
    socket.on("player decision", function(decision, channel_id, bet_amount, rc) {
        if (!decision || !channel_id)
            return;
        var seat_nb = +channel_id[channel_id.length - 1];

        if (table.playing_seats.length == 2)
            table.game.highlights_pos = seat_nb;
        if (seat_nb != table.game.highlights_pos)
            return;
        if (bet_amount && bet_amount[bet_amount.length - 1] == "$") {
            bet_amount = bet_amount.slice(0, bet_amount.length - 1);
            bet_amount = (Math.round(+bet_amount * 100)) / 100;
        }
        console.log(decision + " " + bet_amount + " has been chosen by seat n°" + seat_nb);
        treat_decision(table, get_seat(table.seats, seat_nb), decision, bet_amount, get_seat(table.seats, seat_nb).player, seat_nb, rc);
        io.to(table.id).emit("last action", decision, seat_nb, bet_amount);
        console.log(table.game.round_nb + "/" + table.playing_seats.length);
        if (table.game.round_nb >= table.playing_seats.length && check_bets(table, table.seats)) {
            if (table.playing_seats.length < 2) {
                return one_playing_player_left(table);
            }
            console.log('next_moment');
            next_moment(table, table.game);
        } else {
            if (table.playing_seats.length < 2) {
                return one_playing_player_left(table);
            }
            console.log('switch next player');
            switch_next_player(table);
        }
        ++table.game.round_nb;
    });
}

function tryChrono(socket, table) {
    var chrono = setInterval(function() {
        push = false;
        clearInterval(chrono);
    }, 45000);
    if (push == false) {
        io.to(table.id).emit("chrono", 45, "The game will begin ...");
        push = true;
    }
    var timer = setInterval(function() {
        clearInterval(timer);
        io.to(table.id).emit("chrono off");
        if (table.playing_seats.length > 1) {
            console.log("Starting a new game...");
            new_cashgame(socket, table);
			lock = true;
        } else
            tryChrono(socket, table);
    }, 45000);
}

function treat_decision(table, seat, decision, bet_amount, player, seat_nb, rc) {
    if (decision == "FOLD")
        decision = "FOLD";
    else if (rc == "undefined")
        decision = "CALL";
    else if (rc == 1)
        decision = "RAISE";
    if (decision == "CHECK" && +seat.bet === +table.game.curbet)
        return (1);
    else if (decision == "CALL") {
        player.bankroll -= (+table.game.curbet - +seat.bet) > 0 ? (+table.game.curbet - +seat.bet) : +table.game.curbet;
        if (player.bankroll < 0)
            player.bankroll = 0;
        seat.bet = +seat.bet + +bet_amount;
        seat.bet = Math.round(seat.bet * 100) / 100;
        seat.bet = +seat.bet + (+table.game.curbet - +seat.bet);
        table.game.pot_amount = +table.game.pot_amount + +bet_amount;
        io.to(table.id).emit("bet", seat_nb, +seat.bet);
        io.to(table.id).emit("bankroll modification", seat_nb, player);
        io.to(table.id).emit("pot modification", +table.game.pot_amount);
        return (1);
    } else if (decision == "RAISE" || decision == "BET") {
        if (bet_amount > player.bankroll || bet_amount <= 0)
            return (0);
        player.bankroll -= +bet_amount;
        if (player.bankroll < 0)
            player.bankroll = 0;
        table.game.curbet = +bet_amount /*+ +seat.bet*/ ;
        seat.bet = /*+seat.bet +*/ +bet_amount;
        seat.bet = Math.round(seat.bet * 100) / 100;
        table.game.pot_amount = +table.game.pot_amount + +bet_amount;
        io.to(table.id).emit("bet", seat_nb, +seat.bet);
        io.to(table.id).emit("bankroll modification", seat_nb, player);
        io.to(table.id).emit("pot modification", +table.game.pot_amount);
        return (1);
    } else if (decision == "FOLD") {
        remove_from_playing_seats(table.playing_seats, seat_nb);
        seat.state = "busy";
        io.to(table.id).emit("fold", seat_nb);
        return (1);
    }
    return (1);
}

function adjust_bets_values(table) {
    var curseat;

    for (var idx = 1; idx <= 6; ++idx) {
        if (table.playing_seats.indexOf(idx) != -1) {
            curseat = get_seat(table.seats, idx);
            curseat.bet = (Math.round(curseat.bet * 100)) / 100;
            console.log("Seat bet n°" + idx + ": " + curseat.bet);
        }
    }
}

function switch_next_player(table) {
    var player;

    if (table.game.highlights_pos == "none")
        return;
    io.to(get_private_id(table.private_ids, table.game.highlights_pos)).emit("turn wait");
    io.to(table.id).emit("highlights", table.game.highlights_pos, "off");
    table.game.highlights_pos = get_next_player(table, table.game);
    io.to(table.id).emit("highlights", table.game.highlights_pos, "on");
    send_raise_limits(table, table.game, table.game.highlights_pos, 0);
    adjust_bets_values(table);
    if (get_seat(table.seats, table.game.highlights_pos).player.bankroll) {
        if (table.game.curbet == "0") {
            send_option(table, table.game.highlights_pos, "first choice", "check", 0);
            send_option(table, table.game.highlights_pos, "second choice", "call", cfg.conf.big_blind);
            send_raise_limits(table, table.game, table.game.highlights_pos, 1);
        } else {
            if (table.game.curbet > get_seat(table.seats, table.game.highlights_pos).player.bankroll) {
                send_option(table, table.game.highlights_pos, "first choice", "call", get_seat(table.seats, table.game.highlights_pos).player.bankroll);
                send_option(table, table.game.highlights_pos, "second choice", "null", -1);
            } else {
                send_option(table, table.game.highlights_pos, "first choice", "call", table.game.curbet);
                if (table.game.curbet * 2 > get_seat(table.seats, table.game.highlights_pos).player.bankroll) {
                    send_option(table, table.game.highlights_pos, "second choice", "null", -1);
                } else {
                    /*table.game.curbet == 20 ? */
                    send_option(table, table.game.highlights_pos, "second choice", "raise", table.game.curbet * 2)
                        /*:
					send_option(table, table.game.highlights_pos, "second choice", "raise", table.game.curbet = table.game.curbet + (table.game.curbet - ));*/
                }
            }
        }
        send_option(table, table.game.highlights_pos, "third choice", "fold");
    } else {
        if (table.game.curbet == "0") {
            send_option(table, table.game.highlights_pos, "first choice", "check", 0);
            send_option(table, table.game.highlights_pos, "second choice", "null", -1);
            send_raise_limits(table, table.game, table.game.highlights_pos, 1);
        } else {
            send_option(table, table.game.highlights_pos, "first choice", "call", 0);
            send_option(table, table.game.highlights_pos, "second choice", "null", -1);
        }
        send_option(table, table.game.highlights_pos, "third choice", "fold");
    }
}

function next_moment(table, game) {
    var player;

    if (to_preflop) {
        table.game.moment = "preflop";
        to_preflop = 0;
    }
    if (table.game.moment == "preflop") {
        table.game.curbet = "0";
        table.game.moment = "flop";
        deal_flop(table, game);
        if (evalhand(table, game)) {
            console.log("PreFlop eval hand");
        } // Evaluate the current hand of all the players playing.
    } else if (table.game.moment == "flop") {
        table.game.curbet = "0";
        table.game.moment = "turn";
        deal_turn(table, game);
        if (evalhand(table, game)) {
            console.log("Flop eval hand");
        }
    } else if (table.game.moment == "turn") {
        table.game.curbet = "0";
        table.game.moment = "river";
        deal_river(table, game);
        evalhand(table, game);
    } else if (table.game.moment == "river")
        return show_down(table, game);
    table.game.round_nb = 0;
    table.game.curbet = "0";
    for (var idx = 1; idx <= 6; ++idx) {
        get_seat(table.seats, idx).bet = 0;
        io.to(table.id).emit("bet", idx, "");
    }
    io.to(get_private_id(table.private_ids, table.game.highlights_pos)).emit("turn wait");
    io.to(table.id).emit("highlights", table.game.highlights_pos, "off");
    table.game.highlights_pos = get_first_to_talk(table, game);
    io.to(table.id).emit("highlights", table.game.highlights_pos, "on");
    send_raise_limits(table, table.game, table.game.highlights_pos, 1);
    if (get_seat(table.seats, table.game.highlights_pos).player.bankroll) {
        send_option(table, table.game.highlights_pos, "first choice", "check", 0);
        if (get_seat(table.seats, table.game.highlights_pos).player.bankroll < cfg.conf.big_blind)
            send_option(table, table.game.highlights_pos, "second choice", "null", -1);
        else
            send_option(table, table.game.highlights_pos, "second choice", "call", cfg.conf.big_blind);
        send_option(table, table.game.highlights_pos, "third choice", "fold");
    } else {
        send_option(table, table.game.highlights_pos, "first choice", "check", 0);
        send_option(table, table.game.highlights_pos, "second choice", "null", -1);
        send_option(table, table.game.highlights_pos, "third choice", "fold");
    }
}

function one_playing_player_left(table) {
    var player = get_seat(table.seats, table.playing_seats[0]).player;

    player.bankroll += +table.game.pot_amount;
    io.to(table.id).emit("bankroll modification", table.playing_seats[0], player);
    return end_game(table, table.game, 42, player);
}
<commit_msg>test co<commit_after>var to_preflop = 0;
var push = false;
var lock = false;

function socket_listens_players(socket, table) {
    var player; // Current player.
    var curseat; // Current seat.
    var channel; // Channel involved.
    //table = get_table(table.id, tables);

    /*socket.on("nb player", function(nb) {
    	nb_player = nb;
    	console.log('first '+ nb_player);
    })*/
    socket.on("is valid nickname", function(nickname, seat_idx) {
        curseat = get_seat(table.seats, seat_idx);
        channel = get_private_id(table.private_ids, seat_idx);
        if (!nickname || check_blanks(nickname) || nickname.length < 2 || nickname.length > 8) {
            console.log("Invalid nickname!");
            socket.emit("is valid nickname info", "invalid");
        } else if (table.nicknames.indexOf(nickname) != -1) {
            console.log("Nickname already taken!");
            socket.emit("is valid nickname info", "already taken");
        } else if (curseat.state != "available")
            socket.emit("is valid nickname info", "seat busy");
        else {
            console.log(nickname + " is valid!");
            socket.emit("is valid nickname info", "valid", nickname);
            table.nicknames.push(nickname); // Add the user nickname to the table nicknames array.
            if (table.players_nb < 6)
                ++table.players_nb;
            console.log("There are now " + table.players_nb + " seated at the table (imo of course)!");
            player = new Player(seat_idx, nickname, +table.start_bankroll, -1, -1, -1, -1);
            curseat.state = "busy";
            curseat.player = player;
            console.log("Seat" + seat_idx + " is now " + curseat.state);
            io.to(table.id).emit("new player", player);
            if (table.playing_seats.indexOf(seat_idx) != -1)
                return;
            if (table.game.moment == "waiting")
                table.playing_seats.push(seat_idx);
            for (var i = 0; i < table.playing_seats.length; i++)
                get_seat(table.seats, table.playing_seats[i]).state = "playing";
/*            if (table.playing_seats.length >= 1 && lock)
                new_cashgame(socket, table);
            else {*/
                if (table.playing_seats.length >= 1 && table.game.moment == "waiting") {
                    if (table.playing_seats.length > 1) {
                        return;
                    }
                    tryChrono(socket, table);
//                }
            }
            return;
        }
    });
    socket.on("get seated players", function() {
        send_seats_infos(table);
    });
    socket.on("get board", function() {
        if (table.game.board.length >= 3)
            io.to(table.id).emit("send flop", table.game.board[0], table.game.board[1], table.game.board[2]);
        if (table.game.board.length >= 4)
            io.to(table.id).emit("send turn", table.game.board[3]);
        if (table.game.board.length === 5)
            io.to(table.id).emit("send river", table.game.board[4]);
    });
    socket.on("to preflop", function(init) {
        to_preflop = init;
    });
    socket.on("player decision", function(decision, channel_id, bet_amount, rc) {
        if (!decision || !channel_id)
            return;
        var seat_nb = +channel_id[channel_id.length - 1];

        if (table.playing_seats.length == 2)
            table.game.highlights_pos = seat_nb;
        if (seat_nb != table.game.highlights_pos)
            return;
        if (bet_amount && bet_amount[bet_amount.length - 1] == "$") {
            bet_amount = bet_amount.slice(0, bet_amount.length - 1);
            bet_amount = (Math.round(+bet_amount * 100)) / 100;
        }
        console.log(decision + " " + bet_amount + " has been chosen by seat n°" + seat_nb);
        treat_decision(table, get_seat(table.seats, seat_nb), decision, bet_amount, get_seat(table.seats, seat_nb).player, seat_nb, rc);
        io.to(table.id).emit("last action", decision, seat_nb, bet_amount);
        console.log(table.game.round_nb + "/" + table.playing_seats.length);
        if (table.game.round_nb >= table.playing_seats.length && check_bets(table, table.seats)) {
            if (table.playing_seats.length < 2) {
                return one_playing_player_left(table);
            }
            console.log('next_moment');
            next_moment(table, table.game);
        } else {
            if (table.playing_seats.length < 2) {
                return one_playing_player_left(table);
            }
            console.log('switch next player');
            switch_next_player(table);
        }
        ++table.game.round_nb;
    });
}

function tryChrono(socket, table) {
    var chrono = setInterval(function() {
        push = false;
        clearInterval(chrono);
    }, 45000);
    if (push == false) {
        io.to(table.id).emit("chrono", 45, "The game will begin ...");
        push = true;
    }
    var timer = setInterval(function() {
        clearInterval(timer);
        io.to(table.id).emit("chrono off");
        if (table.playing_seats.length > 1) {
            console.log("Starting a new game...");
            new_cashgame(socket, table);
			//lock = true;
        } else
            tryChrono(socket, table);
    }, 45000);
}

function treat_decision(table, seat, decision, bet_amount, player, seat_nb, rc) {
    if (decision == "FOLD")
        decision = "FOLD";
    else if (rc == "undefined")
        decision = "CALL";
    else if (rc == 1)
        decision = "RAISE";
    if (decision == "CHECK" && +seat.bet === +table.game.curbet)
        return (1);
    else if (decision == "CALL") {
        player.bankroll -= (+table.game.curbet - +seat.bet) > 0 ? (+table.game.curbet - +seat.bet) : +table.game.curbet;
        if (player.bankroll < 0)
            player.bankroll = 0;
        seat.bet = +seat.bet + +bet_amount;
        seat.bet = Math.round(seat.bet * 100) / 100;
        seat.bet = +seat.bet + (+table.game.curbet - +seat.bet);
        table.game.pot_amount = +table.game.pot_amount + +bet_amount;
        io.to(table.id).emit("bet", seat_nb, +seat.bet);
        io.to(table.id).emit("bankroll modification", seat_nb, player);
        io.to(table.id).emit("pot modification", +table.game.pot_amount);
        return (1);
    } else if (decision == "RAISE" || decision == "BET") {
        if (bet_amount > player.bankroll || bet_amount <= 0)
            return (0);
        player.bankroll -= +bet_amount;
        if (player.bankroll < 0)
            player.bankroll = 0;
        table.game.curbet = +bet_amount /*+ +seat.bet*/ ;
        seat.bet = /*+seat.bet +*/ +bet_amount;
        seat.bet = Math.round(seat.bet * 100) / 100;
        table.game.pot_amount = +table.game.pot_amount + +bet_amount;
        io.to(table.id).emit("bet", seat_nb, +seat.bet);
        io.to(table.id).emit("bankroll modification", seat_nb, player);
        io.to(table.id).emit("pot modification", +table.game.pot_amount);
        return (1);
    } else if (decision == "FOLD") {
        remove_from_playing_seats(table.playing_seats, seat_nb);
        seat.state = "busy";
        io.to(table.id).emit("fold", seat_nb);
        return (1);
    }
    return (1);
}

function adjust_bets_values(table) {
    var curseat;

    for (var idx = 1; idx <= 6; ++idx) {
        if (table.playing_seats.indexOf(idx) != -1) {
            curseat = get_seat(table.seats, idx);
            curseat.bet = (Math.round(curseat.bet * 100)) / 100;
            console.log("Seat bet n°" + idx + ": " + curseat.bet);
        }
    }
}

function switch_next_player(table) {
    var player;

    if (table.game.highlights_pos == "none")
        return;
    io.to(get_private_id(table.private_ids, table.game.highlights_pos)).emit("turn wait");
    io.to(table.id).emit("highlights", table.game.highlights_pos, "off");
    table.game.highlights_pos = get_next_player(table, table.game);
    io.to(table.id).emit("highlights", table.game.highlights_pos, "on");
    send_raise_limits(table, table.game, table.game.highlights_pos, 0);
    adjust_bets_values(table);
    if (get_seat(table.seats, table.game.highlights_pos).player.bankroll) {
        if (table.game.curbet == "0") {
            send_option(table, table.game.highlights_pos, "first choice", "check", 0);
            send_option(table, table.game.highlights_pos, "second choice", "call", cfg.conf.big_blind);
            send_raise_limits(table, table.game, table.game.highlights_pos, 1);
        } else {
            if (table.game.curbet > get_seat(table.seats, table.game.highlights_pos).player.bankroll) {
                send_option(table, table.game.highlights_pos, "first choice", "call", get_seat(table.seats, table.game.highlights_pos).player.bankroll);
                send_option(table, table.game.highlights_pos, "second choice", "null", -1);
            } else {
                send_option(table, table.game.highlights_pos, "first choice", "call", table.game.curbet);
                if (table.game.curbet * 2 > get_seat(table.seats, table.game.highlights_pos).player.bankroll) {
                    send_option(table, table.game.highlights_pos, "second choice", "null", -1);
                } else {
                    /*table.game.curbet == 20 ? */
                    send_option(table, table.game.highlights_pos, "second choice", "raise", table.game.curbet * 2)
                        /*:
					send_option(table, table.game.highlights_pos, "second choice", "raise", table.game.curbet = table.game.curbet + (table.game.curbet - ));*/
                }
            }
        }
        send_option(table, table.game.highlights_pos, "third choice", "fold");
    } else {
        if (table.game.curbet == "0") {
            send_option(table, table.game.highlights_pos, "first choice", "check", 0);
            send_option(table, table.game.highlights_pos, "second choice", "null", -1);
            send_raise_limits(table, table.game, table.game.highlights_pos, 1);
        } else {
            send_option(table, table.game.highlights_pos, "first choice", "call", 0);
            send_option(table, table.game.highlights_pos, "second choice", "null", -1);
        }
        send_option(table, table.game.highlights_pos, "third choice", "fold");
    }
}

function next_moment(table, game) {
    var player;

    if (to_preflop) {
        table.game.moment = "preflop";
        to_preflop = 0;
    }
    if (table.game.moment == "preflop") {
        table.game.curbet = "0";
        table.game.moment = "flop";
        deal_flop(table, game);
        if (evalhand(table, game)) {
            console.log("PreFlop eval hand");
        } // Evaluate the current hand of all the players playing.
    } else if (table.game.moment == "flop") {
        table.game.curbet = "0";
        table.game.moment = "turn";
        deal_turn(table, game);
        if (evalhand(table, game)) {
            console.log("Flop eval hand");
        }
    } else if (table.game.moment == "turn") {
        table.game.curbet = "0";
        table.game.moment = "river";
        deal_river(table, game);
        evalhand(table, game);
    } else if (table.game.moment == "river")
        return show_down(table, game);
    table.game.round_nb = 0;
    table.game.curbet = "0";
    for (var idx = 1; idx <= 6; ++idx) {
        get_seat(table.seats, idx).bet = 0;
        io.to(table.id).emit("bet", idx, "");
    }
    io.to(get_private_id(table.private_ids, table.game.highlights_pos)).emit("turn wait");
    io.to(table.id).emit("highlights", table.game.highlights_pos, "off");
    table.game.highlights_pos = get_first_to_talk(table, game);
    io.to(table.id).emit("highlights", table.game.highlights_pos, "on");
    send_raise_limits(table, table.game, table.game.highlights_pos, 1);
    if (get_seat(table.seats, table.game.highlights_pos).player.bankroll) {
        send_option(table, table.game.highlights_pos, "first choice", "check", 0);
        if (get_seat(table.seats, table.game.highlights_pos).player.bankroll < cfg.conf.big_blind)
            send_option(table, table.game.highlights_pos, "second choice", "null", -1);
        else
            send_option(table, table.game.highlights_pos, "second choice", "call", cfg.conf.big_blind);
        send_option(table, table.game.highlights_pos, "third choice", "fold");
    } else {
        send_option(table, table.game.highlights_pos, "first choice", "check", 0);
        send_option(table, table.game.highlights_pos, "second choice", "null", -1);
        send_option(table, table.game.highlights_pos, "third choice", "fold");
    }
}

function one_playing_player_left(table) {
    var player = get_seat(table.seats, table.playing_seats[0]).player;

    player.bankroll += +table.game.pot_amount;
    io.to(table.id).emit("bankroll modification", table.playing_seats[0], player);
    return end_game(table, table.game, 42, player);
}
<|endoftext|>


<commit_before>/*!
 * jQuery Destaque - a simple slideshow plugin with built-in parallax effect
 * https://github.com/globocom/destaque
 * version: 0.1.0
 */

(function ($, window, document, undefined) {
  $.fn.destaque = function(params) {
    var params = $.extend({}, $.fn.destaque.options, params);
    return new Destaque(this, params);
  };

  $.fn.destaque.options = {
    currentSlide: 0,
    slideSpeed: 1000,
    slideMovement: 150,
    slideDirection: "toLeft",
    elementSpeed: 1000,
    autoSlideDelay: 3000,
    resumeSlideDelay: 250,
    stopOnMouseOver: true,
    easingType: "easeInOutExpo",
    itemDefaultZIndex: 10,
    itemSelector: "div.item",
    itemLoadedClass: "loaded",
    activeItemClass: "active",
    itemForegroundElementSelector: ".foreground img",

    // Callbacks
    onInit: function (slideshow) {},
    onResize: function (slideshow) {},
    onPause: function(slideshow) {},
    onResume: function(slideshow) {},
    onSlideLoad: function(slideshow, item, idx) {},
    beforePageUpdate: function(slideshow, pageData) {},
    onPageUpdate: function(slideshow, pageData) {}
  };

  var Destaque = function (element, params) {
    this.element = $(element);
    this.params = params;

    this.params.initialized = false;
    this.params.mouseOver = false;
    this.params.animating = false;

    this.params.autoId = 0;
    this.params.autoTimeStamp = 0;

    this._initElements();
    this._initListeners();

    this.params.onInit(this);
  };

  Destaque.prototype = {
    _initListeners: function() {
      this._initPaginationListeners();
      this._initMouseListeners();
      this._initKeyboardListeners();
      this._initMobileListeners();
      this._initWindowListeners();
    },

    _initPaginationListeners: function () {
      var self = this;

      if (!this.params.controlsSelector) {
        return;
      }
      $(this.params.controlsSelector).each(function() {
        $(this).bind("click.destaque", function(e) {
          e.preventDefault();

          var direction = $(this).attr("rel") === "prev" ? "toRight" : "toLeft";
          self.slideSetAndMove(direction);
        });
      });
    },

    _initMobileListeners: function() {
      var self = this;

      this.element.bind("swipeleft.destaque", function(e) {
        self.slideSetAndMove("toLeft");
       });

      this.element.bind("swiperight.destaque", function (e) {
        self.slideSetAndMove("toRight");
      });
    },

    _initMouseListeners: function () {
      var params = this.params;
      var self = this;

      if (params.slideSum > 1) {
        if (params.stopOnMouseOver) {
          this.element.mouseover(function() {
            self.pause();
          });

          this.element.mouseleave(function() {
            self.resume();
          });
        }
      }
    },

    _initKeyboardListeners: function() {
      var self = this;

      $(window).bind("keydown.destaque", function(e) {
        if (e.keyCode === 37) {
          self.slideSetAndMove("toRight");
        } else {
          if (e.keyCode === 39) {
            self.slideSetAndMove("toLeft");
          }
        }
      });
    },

    _initWindowListeners: function() {
      var self = this;

      $(window).bind("resize.destaque", function() {
        self.params.onResize(self);
      });
    },

    _initElements: function () {
      var element = this.element;
      var params = this.params;

      if (!params.initialized) {
        params.baseSize = element.width();
        params.slideSum = element.find(this.params.itemSelector).length;
        params.elementDirection = params.slideDirection === "toLeft" ? "fromLeft" : "toLeft";
        if (params.currentSlide < 0 || params.currentSlide >= params.slideSum) {
          params.currentSlide = 0;
        }

        this._initSlide();

        params.initialized = true;
      }
    },

    _initSlide: function() {
      var self = this;
      var params = this.params;

      this.element.find(params.itemSelector).each(function() {
        $(this).data("zIndex", params.itemDefaultZIndex).css({zIndex: params.itemDefaultZIndex});
      });

      this.element.find(params.itemForegroundElementSelector).each(function (idx, e) {
        var e = $(this);

        var initialX = parseInt(e.css("left"), 10) + (self.element.width() - params.baseSize) / 2;
        var initialY = parseInt(e.css("top"), 10);

        e.css({top: initialY, left: params.baseSize});
        e.data("xPos", initialX).data("yPos", initialY).data("slidePos", 9999);
      });

      this._loadSlide();
      this._currentSlide().addClass(params.activeItemClass).show();
      this._slideElementsIn();

      params.autoTimeStamp = new Date().getTime();
    },

    pause: function() {
      var params = this.params;

      if (!params.animating) {
        params.mouseOver = true;
        clearTimeout(params.autoId);
        params.onPause(this);
      }
    },

    resume: function() {
      var self = this;
      var params = this.params;

      if (!params.animating) {
        params.mouseOver = false;

        var timeout = 0;

        if (params.autoSlideDelay - (new Date().getTime() - params.autoTimeStamp) < 0) {
          timeout = params.resumeSlideDelay;
        } else {
          timeout = params.autoSlideDelay - (new Date().getTime() - params.autoTimeStamp);
        }

        params.autoId = setTimeout(function() {
          self._slideElementsOut();
        }, timeout);

        params.onResume(this);
      }
    },

    restart: function() {

      if(this.params.currentSlide !== 1) {
        for(var i=0; i <= this.params.currentSlide; i++) {
          this.slideSetAndMove('toRight');
        }
      }
      this.params.currentSlide = 0;
    },

    slideSetAndMove: function(direction) {
      var params = this.params;

      if (!params.animating) {
        if (direction === "toLeft") {
          params.slideDirection = "toLeft";
          params.elementDirection = "fromLeft";
          this.element.removeClass("right").addClass("left");
        } else {
          params.slideDirection = "toRight";
          params.elementDirection = "fromRight";
          this.element.removeClass("left").addClass("right");
        }

        this._setElementPositions(true);
        this._slideElementsOut();
      }
    },

    _setElementPositions: function(justCalculate) {
      var params = this.params;
      var element, pos = 0;

      this._currentSlide().find(params.itemForegroundElementSelector).each(function(i) {
        element = $(this);

        if (params.elementDirection === "fromLeft") {
          pos = params.baseSize + (i * params.baseSize) - (i > 0 ? parseInt(element.data("xPos"), 10) : 0);
        } else {
          pos = -params.baseSize - (i * params.baseSize) + (i > 0 ? parseInt(element.data("xPos"), 10) : 0);
        }

        element.data("slidePos", pos);

        if (!justCalculate) {
          element.css({left: pos});
        }
      });
    },

    _moveSlide: function() {
      var self = this;
      var params = this.params;

      var outPosition = 0;
      var current = this._currentSlide();
      var next = this._nextSlide();
      params.animating = true;

      if (params.slideDirection === "toLeft") {
        outPosition = -params.slideMovement;
        next.css({left: params.baseSize, zIndex: params.itemDefaultZIndex + 1}).show();
      } else {
        outPosition = params.slideMovement;
        next.css({left: -params.baseSize, zIndex: params.itemDefaultZIndex + 1}).show();
      }

      next.stop().animate({left: current.css("left")}, params.slideSpeed, params.easingType, function() {
        next.addClass(params.activeItemClass);
      });

      current.css({zIndex: params.itemDefaultZIndex}).stop().animate({left: outPosition}, params.slideSpeed, params.easingType, function() {
        $(this).removeClass(params.activeItemClass).hide();
      });

      this._updateCurrentSlide();
    },

    _updatePagers: function(callback) {
      var params = this.params;
      var data = {
        currentSlide: params.currentSlide,
        totalSlides:  params.slideSum
      };

      return params[callback](this, data);
    },

    _currentSlide: function() {
      var params = this.params;
      return this.element.find(params.itemSelector).eq(params.currentSlide);
    },

    _previousPage: function() {
      var params = this.params;

      if (params.slideDirection === "toLeft") {
        if (params.currentSlide > 0) {
          return params.currentSlide - 1;
        } else {
          return this.element.find(params.itemSelector).length - 1;
        }
      } else {
        if (params.currentSlide < params.slideSum - 1) {
          return params.currentSlide + 1;
        } else {
          return 0;
        }
      }
    },

    _nextPage: function(idx) {
      var params = this.params;

      if (params.slideDirection === "toLeft") {
        if (params.currentSlide < this.element.find(params.itemSelector).length - 1) {
          return params.currentSlide + 1;
        } else {
          return 0;
        }
      } else {
        if (params.currentSlide > 0) {
          return params.currentSlide - 1;
        } else {
          return this.element.find(params.itemSelector).length - 1;
        }
      }
    },

    _nextSlide: function() {
      var params = this.params;
      return this.element.find(params.itemSelector).eq(this._nextPage());
    },

    _updateCurrentSlide: function() {
      this.params.currentSlide = this._nextPage();

      this._loadSlide();
      this._slideElementsIn();
    },

    _loadSlide: function() {
      var self = this;
      var params = this.params;

      var slidesIdx = [
        params.currentSlide,
        this._previousPage(),
        this._nextPage()
      ];

      var i, idx;
      for (i = 0; i < slidesIdx.length; i++) {
        idx = slidesIdx[i];

        this.element.find(params.itemSelector).eq(idx).each(function() {
          if (!$(this).hasClass(params.itemLoadedClass)) {
            $(this).addClass(params.itemLoadedClass);
            params.onSlideLoad(self, this, idx);
          }
        });
      }
    },

    _slideElementsIn: function() {
      var self = this;
      var params = this.params;

      var current = this._currentSlide();
      var elementNum = current.find(params.itemForegroundElementSelector).length;

      this._setElementPositions();

      current.each(function() {
        $(this).find(params.itemForegroundElementSelector).each(function(i) {
          if (!params.initialized) {
            $(this).css({left: $(this).data("xPos"), top: $(this).data("yPos")});

            if (elementNum - 1 === i && !params.mouseOver && params.slideSum > 1) {
              params.autoId = setTimeout(function() {
                self._slideElementsOut();
              }, params.autoSlideDelay);

              params.animating = false;
            }
          } else {
            params.animating = true;

            $(this).stop().css({left: $(this).data("slidePos"), top: $(this).data("yPos")});
            $(this).animate({left: $(this).data("xPos")}, params.elementSpeed, params.easingType, function() {
              if (elementNum - 1 === i && params.slideSum > 1) {
                if (!params.mouseOver) {
                  params.autoId = setTimeout(function() {
                    self._slideElementsOut();
                  }, params.autoSlideDelay);
                }

                params.autoTimeStamp = new Date().getTime();
                params.animating = false;
              }
            });
          }
        });
      });
    },

    _slideElementsOut: function() {
      var params = this.params;

      if (params.slideSum < 2) {
        return;
      }

      if (this._updatePagers("beforePageUpdate") === false) {
        return;
      };

      params.animating = true;
      clearTimeout(params.autoId);

      this.element.find(params.itemSelector + " " + params.itemForegroundElementSelector).removeAttr("style");
      this.element.find(params.itemSelector + "." + params.activeItemClass + " " + params.itemForegroundElementSelector).each(function() {
        var pos = params.elementDirection === "fromLeft" ? $(this).data("slidePos") * -1 + params.baseSize - $(this).width() : $(this).data("slidePos") * -1;
        $(this).stop().animate({left: pos}, params.elementSpeed, params.easingType);
      });

      this._moveSlide();
      this._updatePagers("onPageUpdate");
    }
  };
})(jQuery, window);
<commit_msg>Fixes a bug that makes the active slide to be hidden during css3 animation when the tab is inactive. Occurred mainly with firefox.<commit_after>/*!
 * jQuery Destaque - a simple slideshow plugin with built-in parallax effect
 * https://github.com/globocom/destaque
 * version: 0.1.0
 */

(function ($, window, document, undefined) {
  $.fn.destaque = function(params) {
    var params = $.extend({}, $.fn.destaque.options, params);
    return new Destaque(this, params);
  };

  $.fn.destaque.options = {
    currentSlide: 0,
    slideSpeed: 1000,
    slideMovement: 150,
    slideDirection: "toLeft",
    elementSpeed: 1000,
    autoSlideDelay: 3000,
    resumeSlideDelay: 250,
    stopOnMouseOver: true,
    easingType: "easeInOutExpo",
    itemDefaultZIndex: 10,
    itemSelector: "div.item",
    itemLoadedClass: "loaded",
    activeItemClass: "active",
    itemForegroundElementSelector: ".foreground img",

    // Callbacks
    onInit: function (slideshow) {},
    onResize: function (slideshow) {},
    onPause: function(slideshow) {},
    onResume: function(slideshow) {},
    onSlideLoad: function(slideshow, item, idx) {},
    beforePageUpdate: function(slideshow, pageData) {},
    onPageUpdate: function(slideshow, pageData) {}
  };

  var Destaque = function (element, params) {
    this.element = $(element);
    this.params = params;

    this.params.initialized = false;
    this.params.mouseOver = false;
    this.params.animating = false;

    this.params.autoId = 0;
    this.params.autoTimeStamp = 0;

    this._initElements();
    this._initListeners();

    this.params.onInit(this);
  };

  Destaque.prototype = {
    _initListeners: function() {
      this._initPaginationListeners();
      this._initMouseListeners();
      this._initKeyboardListeners();
      this._initMobileListeners();
      this._initWindowListeners();
    },

    _initPaginationListeners: function () {
      var self = this;

      if (!this.params.controlsSelector) {
        return;
      }
      $(this.params.controlsSelector).each(function() {
        $(this).bind("click.destaque", function(e) {
          e.preventDefault();

          var direction = $(this).attr("rel") === "prev" ? "toRight" : "toLeft";
          self.slideSetAndMove(direction);
        });
      });
    },

    _initMobileListeners: function() {
      var self = this;

      this.element.bind("swipeleft.destaque", function(e) {
        self.slideSetAndMove("toLeft");
       });

      this.element.bind("swiperight.destaque", function (e) {
        self.slideSetAndMove("toRight");
      });
    },

    _initMouseListeners: function () {
      var params = this.params;
      var self = this;

      if (params.slideSum > 1) {
        if (params.stopOnMouseOver) {
          this.element.mouseover(function() {
            self.pause();
          });

          this.element.mouseleave(function() {
            self.resume();
          });
        }
      }
    },

    _initKeyboardListeners: function() {
      var self = this;

      $(window).bind("keydown.destaque", function(e) {
        if (e.keyCode === 37) {
          self.slideSetAndMove("toRight");
        } else {
          if (e.keyCode === 39) {
            self.slideSetAndMove("toLeft");
          }
        }
      });
    },

    _initWindowListeners: function() {
      var self = this;

      $(window).bind("resize.destaque", function() {
        self.params.onResize(self);
      });
    },

    _initElements: function () {
      var element = this.element;
      var params = this.params;

      if (!params.initialized) {
        params.baseSize = element.width();
        params.slideSum = element.find(this.params.itemSelector).length;
        params.elementDirection = params.slideDirection === "toLeft" ? "fromLeft" : "toLeft";
        if (params.currentSlide < 0 || params.currentSlide >= params.slideSum) {
          params.currentSlide = 0;
        }

        this._initSlide();

        params.initialized = true;
      }
    },

    _initSlide: function() {
      var self = this;
      var params = this.params;

      this.element.find(params.itemSelector).each(function() {
        $(this).data("zIndex", params.itemDefaultZIndex).css({zIndex: params.itemDefaultZIndex});
      });

      this.element.find(params.itemForegroundElementSelector).each(function (idx, e) {
        var e = $(this);

        var initialX = parseInt(e.css("left"), 10) + (self.element.width() - params.baseSize) / 2;
        var initialY = parseInt(e.css("top"), 10);

        e.css({top: initialY, left: params.baseSize});
        e.data("xPos", initialX).data("yPos", initialY).data("slidePos", 9999);
      });

      this._loadSlide();
      this._currentSlide().addClass(params.activeItemClass).show();
      this._slideElementsIn();

      params.autoTimeStamp = new Date().getTime();
    },

    pause: function() {
      var params = this.params;

      if (!params.animating) {
        params.mouseOver = true;
        clearTimeout(params.autoId);
        params.onPause(this);
      }
    },

    resume: function() {
      var self = this;
      var params = this.params;

      if (!params.animating) {
        params.mouseOver = false;

        var timeout = 0;

        if (params.autoSlideDelay - (new Date().getTime() - params.autoTimeStamp) < 0) {
          timeout = params.resumeSlideDelay;
        } else {
          timeout = params.autoSlideDelay - (new Date().getTime() - params.autoTimeStamp);
        }

        params.autoId = setTimeout(function() {
          self._slideElementsOut();
        }, timeout);

        params.onResume(this);
      }
    },

    restart: function() {
      if(this.params.currentSlide !== 1) {
        for(var i=0; i <= this.params.currentSlide; i++) {
          this.slideSetAndMove('toRight');
        }
      }
      this.params.currentSlide = 0;
    },

    slideSetAndMove: function(direction) {
      var params = this.params;

      if (!params.animating) {
        if (direction === "toLeft") {
          params.slideDirection = "toLeft";
          params.elementDirection = "fromLeft";
          this.element.removeClass("right").addClass("left");
        } else {
          params.slideDirection = "toRight";
          params.elementDirection = "fromRight";
          this.element.removeClass("left").addClass("right");
        }

        this._setElementPositions(true);
        this._slideElementsOut();
      }
    },

    _setElementPositions: function(justCalculate) {
      var params = this.params;
      var element, pos = 0;

      this._currentSlide().find(params.itemForegroundElementSelector).each(function(i) {
        element = $(this);

        if (params.elementDirection === "fromLeft") {
          pos = params.baseSize + (i * params.baseSize) - (i > 0 ? parseInt(element.data("xPos"), 10) : 0);
        } else {
          pos = -params.baseSize - (i * params.baseSize) + (i > 0 ? parseInt(element.data("xPos"), 10) : 0);
        }

        element.data("slidePos", pos);

        if (!justCalculate) {
          element.css({left: pos});
        }
      });
    },

    _moveSlide: function() {
      var self = this;
      var params = this.params;

      var initialPosition = 0;
      var outPosition = 0;
      var current = this._currentSlide();
      var next = this._nextSlide();
      params.animating = true;

      if (params.slideDirection === "toLeft") {
        outPosition = -params.slideMovement;
        next.css({left: params.baseSize, zIndex: params.itemDefaultZIndex + 1}).show();
      } else {
        outPosition = params.slideMovement;
        next.css({left: -params.baseSize, zIndex: params.itemDefaultZIndex + 1}).show();
      }

      next.stop().animate({left: initialPosition}, params.slideSpeed, params.easingType, function() {
        next.addClass(params.activeItemClass);
      });

      current.css({zIndex: params.itemDefaultZIndex}).stop().animate({left: outPosition}, params.slideSpeed, params.easingType, function() {
        $(this).removeClass(params.activeItemClass).hide();
      });

      this._updateCurrentSlide();
    },

    _updatePagers: function(callback) {
      var params = this.params;
      var data = {
        currentSlide: params.currentSlide,
        totalSlides:  params.slideSum
      };

      return params[callback](this, data);
    },

    _currentSlide: function() {
      var params = this.params;
      return this.element.find(params.itemSelector).eq(params.currentSlide);
    },

    _previousPage: function() {
      var params = this.params;

      if (params.slideDirection === "toLeft") {
        if (params.currentSlide > 0) {
          return params.currentSlide - 1;
        } else {
          return this.element.find(params.itemSelector).length - 1;
        }
      } else {
        if (params.currentSlide < params.slideSum - 1) {
          return params.currentSlide + 1;
        } else {
          return 0;
        }
      }
    },

    _nextPage: function(idx) {
      var params = this.params;

      if (params.slideDirection === "toLeft") {
        if (params.currentSlide < this.element.find(params.itemSelector).length - 1) {
          return params.currentSlide + 1;
        } else {
          return 0;
        }
      } else {
        if (params.currentSlide > 0) {
          return params.currentSlide - 1;
        } else {
          return this.element.find(params.itemSelector).length - 1;
        }
      }
    },

    _nextSlide: function() {
      return this.element.find(this.params.itemSelector).eq(this._nextPage());
    },

    _updateCurrentSlide: function() {
      this.params.currentSlide = this._nextPage();

      this._loadSlide();
      this._slideElementsIn();
    },

    _loadSlide: function() {
      var self = this;
      var params = this.params;

      var slidesIdx = [
        params.currentSlide,
        this._previousPage(),
        this._nextPage()
      ];

      var i, idx;
      for (i = 0; i < slidesIdx.length; i++) {
        idx = slidesIdx[i];

        this.element.find(params.itemSelector).eq(idx).each(function() {
          if (!$(this).hasClass(params.itemLoadedClass)) {
            $(this).addClass(params.itemLoadedClass);
            params.onSlideLoad(self, this, idx);
          }
        });
      }
    },

    _slideElementsIn: function() {
      var self = this;
      var params = this.params;

      var current = this._currentSlide();
      var elementNum = current.find(params.itemForegroundElementSelector).length;

      this._setElementPositions();

      current.each(function() {
        $(this).find(params.itemForegroundElementSelector).each(function(i) {
          if (!params.initialized) {
            $(this).css({left: $(this).data("xPos"), top: $(this).data("yPos")});

            if (elementNum - 1 === i && !params.mouseOver && params.slideSum > 1) {
              params.autoId = setTimeout(function() {
                self._slideElementsOut();
              }, params.autoSlideDelay);

              params.animating = false;
            }
          } else {
            params.animating = true;

            $(this).stop().css({left: $(this).data("slidePos"), top: $(this).data("yPos")});
            $(this).animate({left: $(this).data("xPos")}, params.elementSpeed, params.easingType, function() {
              if (elementNum - 1 === i && params.slideSum > 1) {
                if (!params.mouseOver) {
                  params.autoId = setTimeout(function() {
                    self._slideElementsOut();
                  }, params.autoSlideDelay);
                }

                params.autoTimeStamp = new Date().getTime();
                params.animating = false;
              }
            });
          }
        });
      });
    },

    _slideElementsOut: function() {
      var params = this.params;

      if (params.slideSum < 2) {
        return;
      }

      if (this._updatePagers("beforePageUpdate") === false) {
        return;
      };

      params.animating = true;
      clearTimeout(params.autoId);

      this.element.find(params.itemSelector + " " + params.itemForegroundElementSelector).removeAttr("style");
      this.element.find(params.itemSelector + "." + params.activeItemClass + " " + params.itemForegroundElementSelector).each(function() {
        var pos = params.elementDirection === "fromLeft" ? $(this).data("slidePos") * -1 + params.baseSize - $(this).width() : $(this).data("slidePos") * -1;
        $(this).stop().animate({left: pos}, params.elementSpeed, params.easingType);
      });

      this._moveSlide();
      this._updatePagers("onPageUpdate");
    }
  };
})(jQuery, window);<|endoftext|>


<commit_before>import { stringify, parse } from 'jsan';
import socketCluster from 'socketcluster-client';
import { socketOptions } from './constants';

let instanceName;
let socket;
let channel;
let nextActionId = 1;
let listeners = [];

function handleMessages(message) {
  if (message.type === 'DISPATCH' && message.state) {
    const parsedState = parse(message.state);
    listeners.forEach(listener => listener(parsedState));
  }
}

function connect(options) {
  if (socket) return;
  socket = socketCluster.connect(options);
}

function watch() {
  if (channel) return;
  socket.emit('login', 'master', (err, channelName) => {
    if (err) { console.error(err); return; }
    channel = socket.subscribe(channelName);
    channel.watch(handleMessages);
    socket.on(channelName, handleMessages);
  });
}

export function start(options) {
  if (options) {
    instanceName = options.name;
  }
  connect(options && options.port ? options : socketOptions);
}

function transformAction(action) {
  if (typeof action === 'object') {
    if (!action.timestamp) action.timestamp = Date.now();
    if (!action.type) action.type = action.id || action.actionType || '';
    return action;
  }
  if (typeof action === 'string') return { type: action, timestamp: Date.now() };
  return '';
}

export function send(action, state, options) {
  start(options);
  setTimeout(() => {
    const message = {
      payload: state ? stringify(state) : '',
      action: transformAction(action),
      type: action !== undefined ? 'ACTION' : 'INIT',
      nextActionId: nextActionId || '',
      id: socket.id,
      name: instanceName
    };
    nextActionId++;
    socket.emit(socket.id ? 'log' : 'log-noid', message);
  }, 0);
}

export function subscribe(listener, options) {
  start(options);
  watch();
  listeners.push(listener);

  return function unsubscribe() {
    const index = listeners.indexOf(listener);
    listeners.splice(index, 1);
  };
}

export function init(state = {}, options) {
  nextActionId = 1;
  start(options);
  send(undefined, state, options);
}

export default { init, send, subscribe };
<commit_msg>Set default hostname if port is set<commit_after>import { stringify, parse } from 'jsan';
import socketCluster from 'socketcluster-client';
import { socketOptions } from './constants';

let instanceName;
let socket;
let channel;
let nextActionId = 1;
let listeners = [];

function handleMessages(message) {
  if (message.type === 'DISPATCH' && message.state) {
    const parsedState = parse(message.state);
    listeners.forEach(listener => listener(parsedState));
  }
}

function connect(options) {
  if (socket) return;
  socket = socketCluster.connect(options);
}

function watch() {
  if (channel) return;
  socket.emit('login', 'master', (err, channelName) => {
    if (err) { console.error(err); return; }
    channel = socket.subscribe(channelName);
    channel.watch(handleMessages);
    socket.on(channelName, handleMessages);
  });
}

export function start(options) {
  if (options) {
    instanceName = options.name;

    if (options.port && !options.hostname) {
      options.hostname = 'localhost';
    }
  }
  connect(options && options.port ? options : socketOptions);
}

function transformAction(action) {
  if (typeof action === 'object') {
    if (!action.timestamp) action.timestamp = Date.now();
    if (!action.type) action.type = action.id || action.actionType || '';
    return action;
  }
  if (typeof action === 'string') return { type: action, timestamp: Date.now() };
  return '';
}

export function send(action, state, options) {
  start(options);
  setTimeout(() => {
    const message = {
      payload: state ? stringify(state) : '',
      action: transformAction(action),
      type: action !== undefined ? 'ACTION' : 'INIT',
      nextActionId: nextActionId || '',
      id: socket.id,
      name: instanceName
    };
    nextActionId++;
    socket.emit(socket.id ? 'log' : 'log-noid', message);
  }, 0);
}

export function subscribe(listener, options) {
  start(options);
  watch();
  listeners.push(listener);

  return function unsubscribe() {
    const index = listeners.indexOf(listener);
    listeners.splice(index, 1);
  };
}

export function init(state = {}, options) {
  nextActionId = 1;
  start(options);
  send(undefined, state, options);
}

export default { init, send, subscribe };
<|endoftext|>