<commit_before>mf.include("block_finder.js");
mf.include("chat_commands.js");
mf.include("player_tracker.js");
mf.include("location_manager.js");
mf.include("items.js");
mf.include("inventory.js");
mf.include("navigator.js");
mf.include("task_manager.js");

(function() {
    var findChestNearestPoint = function(point) {
        var chests = block_finder.findNearest(point, mf.ItemType.Chest, 128, 1);
        if (chests.length === 0) {
            return undefined;
        } else {
            return chests.shift();
        }
    };

    var useChest = function(speaker, args, responder_fun, command) {
        /*
        Parsing:
        case 1: Dump everything into nearest chest
            "dump"
            "dump all/inventory/ * /everything"

        case 2: Dump everything into chest nearest entity(speaker)
            "dump here"
            "dump all/inventory/ * /everything here"

        case 3: Dump everything into chest nearest location
            "dump into location"
            "dump all/inventory/ * /everything into location"

        case 4: Dump all items of type X into nearest chest
            "dump X"

        case 5: Dump all items of type X into chest nearest entity(speaker)
            "dump X here"

        case 6: Dump all items of type X into chest nearest location
            "dump X into location"

        case 7: Dump # items of type X into nearest chest
            "dump # X"

        case 8: Dump # items of type X into chest nearest entity(speaker)
            "dump # X here"

        case 9: Dump # items of type X into chest nearest location
            "dump # X into location"
        */
        var chest_position;
        var item_type;
        var item_count;
        var location_string;
        if (args.length > 0) {
            if (! isNaN(args[0])) {
                item_count = Math.ceil(args.shift());
                if (item_count <= 0) {
                    responder_fun("I can't " + command + " " + item_count + " of ANY item!");
                    return;
                }
            }
        }
        if (args.length > 0) {
            var arg = args[0];
            if (arg === "everything" || arg === "all" || arg === "*") {
                args.shift();
                item_type = undefined;
            }
        }
        if (args.length > 0) {
            if (args[args.length-1] === "here") {
                args.pop();
                var player = player_tracker.entityForPlayer(speaker);
                if (player === undefined) {
                    responder_fun("I can't see you, " + speaker + ".");
                    return;
                }
                var target_block_position;
                var cursor = player.position.offset(0, 0, player.height);
                var yaw = player.yaw, pitch = player.pitch;
                var vector_length = 0.03125;
                var x = Math.cos(yaw) * Math.cos(pitch);
                var y = Math.sin(yaw) * Math.cos(pitch);
                var z = Math.sin(pitch);
                var step_delta = new mf.Point(x * vector_length, y * vector_length, z * vector_length);
                for (var i = 0; i < 192; i++) {
                    cursor = cursor.plus(step_delta);
                    if (mf.isPhysical(mf.blockAt(cursor).type)) {
                        target_block_position = cursor.floored();
                        break;
                    }
                }
                if (target_block_position === undefined) {
                    chest_position = player.position;
                } else {
                    chest_position = target_block_position;
                }
                location_string = "you";
            }
        }
        if (args.length > 0) {
            var flag = false;
            for (var i = 0; i < args.length; i++) {
                if (args[i] === "near") {
                    location_string = (args.slice(i+1,args.length)).join(" ");
                    args = args.slice(0,i);
                    flag = true;
                    break;
                }
            }
            if (args.length === 0) {
                item_type = undefined;
            } else {
                if (command === "loot") {
                    item_type = items.findItemTypeUnambiguously(args.join(" "),responder_fun);
                    if (item_type === undefined) {
                        return;
                    }
                } else {
                    item_type = items.findUnambiguouslyInDatabase(args.join(" "),responder_fun,inventory.getDatabase());
                    if (item_type === undefined) {
                        return;
                    }
                }
                item_type = item_type.id;
            }
            if (flag) {
                chest_position = location_manager.findUnambiguousLocation(location_string,responder_fun);
                if (chest_position === undefined) {
                    return;
                }
                location_string = chest_position.name;
                chest_position = chest_position.point;
            }
        }
        if (chest_position === undefined) {
            chest_position = block_finder.findNearest(mf.self().position,mf.ItemType.Chest,128,1);
            if (chest_position.length !== 1) {
                responder_fun("I couldn't find any nearby chests.");
                return;
            }
            chest_position = chest_position.shift();
            location_string = "me";
        }
        if (item_count !== undefined) {
            if (item_type === undefined) {
                responder_fun("I can't " + command + " " + item_count + " of all block types!");
                return;
            }
        }
        chest_position = chest_position.floored();
        var task = new task_manager.Task(function useChestData() {
            function cant_navto_func() {
                responder_fun("I can't find a path to the chest at " + chest_position.floored() + ".");
                task_manager.done();
            }
            if (mf.blockAt(chest_position).type !== mf.ItemType.Chest) {
                if (mf.self().position.floored().distanceTo(chest_position) <= 120) {
                    var new_chest_position = findChestNearestPoint(chest_position);
                    if (new_chest_position === undefined) {
                        responder_fun("Unable to find any chest near " + chest_position.floored() + ".");
                        task_manager.done();
                        return;
                    }
                    chest_position = new_chest_position;
                    if (item_type !== undefined) {
                        if (item_count !== undefined) {
                            if (command === "loot") {
                                responder_fun("Going to go " + command + " " + item_count + " " + items.nameForId(item_type) + " from chest at " + chest_position.floored() + ".");
                            } else {
                                responder_fun("Going to go " + command + " " + item_count + " " + items.nameForId(item_type) + " into chest at " + chest_position.floored() + ".");
                            }
                        } else {
                            if (command === "loot") {
                                responder_fun("Going to go " + command + " all of the " + items.nameForId(item_type) + " from the chest at " + chest_position.floored() + ".");
                            } else {
                                responder_fun("Going to go " + command + " all of my " + items.nameForId(item_type) + " into the chest at " + chest_position.floored() + ".");
                            }
                        }
                    } else {
                        if (command === "loot") {
                            responder_fun("Going to go " + command + " everything from the chest at " + chest_position.floored() + ".");
                        } else {
                            responder_fun("Going to go " + command + " everything into the chest at " + chest_position.floored() + ".");
                        }
                    }
                    navigator.navigateTo(chest_position.floored(),{
                        end_radius : 3,
                        timeout_milliseconds: 6 * 1000,
                        cant_find_func : cant_navto_func,
                        arrived_func : useChestData
                    });
                } else {
                    responder_fun("Going to go near that location and see the nearest chests.");
                    navigator.navigateTo(chest_position.floored(),{
                        end_radius: 32,
                        timeout_milliseconds: 6 * 1000,
                        cant_find_func: cant_navto_func,
                        arrived_func: useChestData
                    });
                }
            } else {
                if (mf.self().position.floored().distanceTo(chest_position.floored()) <= 3) {
                    mf.onWindowOpened(function on_chest_opened(window_type) {
                        if (window_type !== mf.WindowType.Chest) {
                            return;
                        }
                        mf.removeHandler(mf.onWindowOpened, on_chest_opened);
                        if (item_type === undefined) {
                            if (command === "loot") {
                                var success = inventory.moveAll(inventory.ChestFull,inventory.InventoryFull);
                            } else {
                                var success = inventory.moveAll(inventory.InventoryFull,inventory.ChestFull);
                            }

                            if (success) {
                                responder_fun("Done!");
                            } else {
                                if (command === "loot") {
                                    responder_fun("My inventory is full!");
                                } else {
                                    responder_fun("The chest is too full to hold anything else!");
                                }
                            }
                        } else {
                            if (item_count === undefined) {
                                if (command === "loot") {
                                    var success = inventory.moveAllType(item_type, inventory.ChestFull, inventory.InventoryFull);
                                } else {
                                    var success = inventory.moveAllType(item_type,inventory.InventoryFull,inventory.ChestFull);
                                }
                                if (success) {
                                    responder_fun("Done!");
                                } else {
                                    if (command === "loot") {
                                        respond_fun("My inventory is too full to hold any more " + items.nameForId(item_type) + ".");
                                    } else {
                                        responder_fun("The chest is too full to hold any more " + items.nameForId(item_type) + ".");
                                    }
                                }
                            } else {
                                if (command === "loot") {
                                    var success = inventory.moveCountType(item_count, item_type, inventory.ChestFull, inventory.InventoryFull);
                                } else {
                                    var success = inventory.moveCountType(item_count, item_type, inventory.InventoryFull, inventory.ChestFull);
                                }
                                if (success) {
                                    responder_fun("Done!");
                                } else {
                                    if (command === "loot") {
                                        responder_fun("My inventory is too full to hold any more " + items.nameForId(item_type) + ".");
                                    } else {
                                        responder_fun("The chest is too full to hold any more " + items.nameForId(item_type) + ".");
                                    }
                                }
                            }
                        }
                        mf.closeWindow();
                        task_manager.done();
                    });
                    mf.hax.activateBlock(chest_position);
                } else {
                    if (item_type !== undefined) {
                        if (item_count !== undefined) {
                            if (command === "loot") {
                                responder_fun("Going to go " + command + " " + item_count + " " + items.nameForId(item_type) + " from the chest at " + chest_position.floored() + ".");
                            } else {
                                responder_fun("Going to go " + command + " " + item_count + " " + items.nameForId(item_type) + " into the chest at " + chest_position.floored() + ".");
                            }
                        } else {
                            if (command === "loot") {
                                responder_fun("Going to go " + command + " all of the " + items.nameForId(item_type) + " from the chest at " + chest_position.floored() + ".");
                            } else {
                                responder_fun("Going to go " + command + " all of my " + items.nameForId(item_type) + " into the chest at " + chest_position.floored() + ".");
                            }
                        }
                    } else {
                        if (command === "loot") {
                            responder_fun("Going to go " + command + " everything from the chest at " + chest_position.floored() + ".");
                        } else {
                            responder_fun("Going to go " + command + " everything into the chest at " + chest_position.floored() + ".");
                        }
                    }
                    navigator.navigateTo(chest_position,{
                        end_radius : 3,
                        timeout_milliseconds: 6 * 1000,
                        cant_find_func : cant_navto_func,
                        arrived_func : useChestData
                    });
                }
            }
        }, function stop() {
            if (inventory.currentlyOpenWindow !== undefined) {
                mf.closeWindow();
            }
        }, function toString() {
            if (item_type === undefined) {
                if (command === "loot") {
                    if (mf.blockAt(chest_position).type !== mf.ItemType.Chest) {
                        return "loot everything near " + location_string;
                    } else {
                        return "loot everything from chest at " + chest_position;
                    }
                } else {
                    if (mf.blockAt(chest_position).type !== mf.ItemType.Chest) {
                        return "dump everything near " + location_string;
                    } else {
                        return "dump everything into chest at " + chest_position;
                    }
                }
            } else if (item_count === undefined) {
                if (command === "loot") {
                    if (mf.blockAt(chest_position).type !== mf.ItemType.Chest) {
                        return "loot all " + items.nameForId(item_type) + " from chest near " + location_string;
                    } else {
                        return "loot all " + items.nameForId(item_type) + " from chest at " + chest_position;
                    }
                } else {
                    if (mf.blockAt(chest_position).type !== mf.ItemType.Chest) {
                        return "dump all " + items.nameForId(item_type) + " into chest near " + location_string;
                    } else {
                        return "dump all " + items.nameForId(item_type) + " into chest at " + chest_position;
                    }
                }
            }
        });
        task_manager.doLater(task);
    };

    chat_commands.registerCommand("loot", function(speaker, args, responder_fun) {
       useChest(speaker, args, responder_fun, "loot");
    }, 0, Infinity);

    chat_commands.registerCommand("dump", function(speaker, args, responder_fun) {
        useChest(speaker,args,responder_fun,"dump");
    }, 0, Infinity);
})();
<commit_msg>Fixed typo bug in chests<commit_after>mf.include("block_finder.js");
mf.include("chat_commands.js");
mf.include("player_tracker.js");
mf.include("location_manager.js");
mf.include("items.js");
mf.include("inventory.js");
mf.include("navigator.js");
mf.include("task_manager.js");

(function() {
    var findChestNearestPoint = function(point) {
        var chests = block_finder.findNearest(point, mf.ItemType.Chest, 128, 1);
        if (chests.length === 0) {
            return undefined;
        } else {
            return chests.shift();
        }
    };

    var useChest = function(speaker, args, responder_fun, command) {
        /*
        Parsing:
        case 1: Dump everything into nearest chest
            "dump"
            "dump all/inventory/ * /everything"

        case 2: Dump everything into chest nearest entity(speaker)
            "dump here"
            "dump all/inventory/ * /everything here"

        case 3: Dump everything into chest nearest location
            "dump into location"
            "dump all/inventory/ * /everything into location"

        case 4: Dump all items of type X into nearest chest
            "dump X"

        case 5: Dump all items of type X into chest nearest entity(speaker)
            "dump X here"

        case 6: Dump all items of type X into chest nearest location
            "dump X into location"

        case 7: Dump # items of type X into nearest chest
            "dump # X"

        case 8: Dump # items of type X into chest nearest entity(speaker)
            "dump # X here"

        case 9: Dump # items of type X into chest nearest location
            "dump # X into location"
        */
        var chest_position;
        var item_type;
        var item_count;
        var location_string;
        if (args.length > 0) {
            if (! isNaN(args[0])) {
                item_count = Math.ceil(args.shift());
                if (item_count <= 0) {
                    responder_fun("I can't " + command + " " + item_count + " of ANY item!");
                    return;
                }
            }
        }
        if (args.length > 0) {
            var arg = args[0];
            if (arg === "everything" || arg === "all" || arg === "*") {
                args.shift();
                item_type = undefined;
            }
        }
        if (args.length > 0) {
            if (args[args.length-1] === "here") {
                args.pop();
                var player = player_tracker.entityForPlayer(speaker);
                if (player === undefined) {
                    responder_fun("I can't see you, " + speaker + ".");
                    return;
                }
                var target_block_position;
                var cursor = player.position.offset(0, 0, player.height);
                var yaw = player.yaw, pitch = player.pitch;
                var vector_length = 0.03125;
                var x = Math.cos(yaw) * Math.cos(pitch);
                var y = Math.sin(yaw) * Math.cos(pitch);
                var z = Math.sin(pitch);
                var step_delta = new mf.Point(x * vector_length, y * vector_length, z * vector_length);
                for (var i = 0; i < 192; i++) {
                    cursor = cursor.plus(step_delta);
                    if (mf.isPhysical(mf.blockAt(cursor).type)) {
                        target_block_position = cursor.floored();
                        break;
                    }
                }
                if (target_block_position === undefined) {
                    chest_position = player.position;
                } else {
                    chest_position = target_block_position;
                }
                location_string = "you";
            }
        }
        if (args.length > 0) {
            var flag = false;
            for (var i = 0; i < args.length; i++) {
                if (args[i] === "near") {
                    location_string = (args.slice(i+1,args.length)).join(" ");
                    args = args.slice(0,i);
                    flag = true;
                    break;
                }
            }
            if (args.length === 0) {
                item_type = undefined;
            } else {
                if (command === "loot") {
                    item_type = items.findItemTypeUnambiguously(args.join(" "),responder_fun);
                    if (item_type === undefined) {
                        return;
                    }
                } else {
                    item_type = items.findUnambiguouslyInDatabase(args.join(" "),responder_fun,inventory.getDatabase());
                    if (item_type === undefined) {
                        return;
                    }
                }
                item_type = item_type.id;
            }
            if (flag) {
                chest_position = location_manager.findUnambiguousLocation(location_string,responder_fun);
                if (chest_position === undefined) {
                    return;
                }
                location_string = chest_position.name;
                chest_position = chest_position.point;
            }
        }
        if (chest_position === undefined) {
            chest_position = block_finder.findNearest(mf.self().position,mf.ItemType.Chest,128,1);
            if (chest_position.length !== 1) {
                responder_fun("I couldn't find any nearby chests.");
                return;
            }
            chest_position = chest_position.shift();
            location_string = "me";
        }
        if (item_count !== undefined) {
            if (item_type === undefined) {
                responder_fun("I can't " + command + " " + item_count + " of all block types!");
                return;
            }
        }
        chest_position = chest_position.floored();
        var task = new task_manager.Task(function useChestData() {
            function cant_navto_func() {
                responder_fun("I can't find a path to the chest at " + chest_position.floored() + ".");
                task_manager.done();
            }
            if (mf.blockAt(chest_position).type !== mf.ItemType.Chest) {
                if (mf.self().position.floored().distanceTo(chest_position) <= 120) {
                    var new_chest_position = findChestNearestPoint(chest_position);
                    if (new_chest_position === undefined) {
                        responder_fun("Unable to find any chest near " + chest_position.floored() + ".");
                        task_manager.done();
                        return;
                    }
                    chest_position = new_chest_position;
                    if (item_type !== undefined) {
                        if (item_count !== undefined) {
                            if (command === "loot") {
                                responder_fun("Going to go " + command + " " + item_count + " " + items.nameForId(item_type) + " from chest at " + chest_position.floored() + ".");
                            } else {
                                responder_fun("Going to go " + command + " " + item_count + " " + items.nameForId(item_type) + " into chest at " + chest_position.floored() + ".");
                            }
                        } else {
                            if (command === "loot") {
                                responder_fun("Going to go " + command + " all of the " + items.nameForId(item_type) + " from the chest at " + chest_position.floored() + ".");
                            } else {
                                responder_fun("Going to go " + command + " all of my " + items.nameForId(item_type) + " into the chest at " + chest_position.floored() + ".");
                            }
                        }
                    } else {
                        if (command === "loot") {
                            responder_fun("Going to go " + command + " everything from the chest at " + chest_position.floored() + ".");
                        } else {
                            responder_fun("Going to go " + command + " everything into the chest at " + chest_position.floored() + ".");
                        }
                    }
                    navigator.navigateTo(chest_position.floored(),{
                        end_radius : 3,
                        timeout_milliseconds: 6 * 1000,
                        cant_find_func : cant_navto_func,
                        arrived_func : useChestData
                    });
                } else {
                    responder_fun("Going to go near that location and see the nearest chests.");
                    navigator.navigateTo(chest_position.floored(),{
                        end_radius: 32,
                        timeout_milliseconds: 6 * 1000,
                        cant_find_func: cant_navto_func,
                        arrived_func: useChestData
                    });
                }
            } else {
                if (mf.self().position.floored().distanceTo(chest_position.floored()) <= 3) {
                    mf.onWindowOpened(function on_chest_opened(window_type) {
                        if (window_type !== mf.WindowType.Chest) {
                            return;
                        }
                        mf.removeHandler(mf.onWindowOpened, on_chest_opened);
                        if (item_type === undefined) {
                            if (command === "loot") {
                                var success = inventory.moveAll(inventory.ChestFull,inventory.InventoryFull);
                            } else {
                                var success = inventory.moveAll(inventory.InventoryFull,inventory.ChestFull);
                            }

                            if (success) {
                                responder_fun("Done!");
                            } else {
                                if (command === "loot") {
                                    responder_fun("My inventory is full!");
                                } else {
                                    responder_fun("The chest is too full to hold anything else!");
                                }
                            }
                        } else {
                            if (item_count === undefined) {
                                if (command === "loot") {
                                    var success = inventory.moveAllType(item_type, inventory.ChestFull, inventory.InventoryFull);
                                } else {
                                    var success = inventory.moveAllType(item_type,inventory.InventoryFull,inventory.ChestFull);
                                }
                                if (success) {
                                    responder_fun("Done!");
                                } else {
                                    if (command === "loot") {
                                        responder_fun("My inventory is too full to hold any more " + items.nameForId(item_type) + ".");
                                    } else {
                                        responder_fun("The chest is too full to hold any more " + items.nameForId(item_type) + ".");
                                    }
                                }
                            } else {
                                if (command === "loot") {
                                    var success = inventory.moveCountType(item_count, item_type, inventory.ChestFull, inventory.InventoryFull);
                                } else {
                                    var success = inventory.moveCountType(item_count, item_type, inventory.InventoryFull, inventory.ChestFull);
                                }
                                if (success) {
                                    responder_fun("Done!");
                                } else {
                                    if (command === "loot") {
                                        responder_fun("My inventory is too full to hold any more " + items.nameForId(item_type) + ".");
                                    } else {
                                        responder_fun("The chest is too full to hold any more " + items.nameForId(item_type) + ".");
                                    }
                                }
                            }
                        }
                        mf.closeWindow();
                        task_manager.done();
                    });
                    mf.hax.activateBlock(chest_position);
                } else {
                    if (item_type !== undefined) {
                        if (item_count !== undefined) {
                            if (command === "loot") {
                                responder_fun("Going to go " + command + " " + item_count + " " + items.nameForId(item_type) + " from the chest at " + chest_position.floored() + ".");
                            } else {
                                responder_fun("Going to go " + command + " " + item_count + " " + items.nameForId(item_type) + " into the chest at " + chest_position.floored() + ".");
                            }
                        } else {
                            if (command === "loot") {
                                responder_fun("Going to go " + command + " all of the " + items.nameForId(item_type) + " from the chest at " + chest_position.floored() + ".");
                            } else {
                                responder_fun("Going to go " + command + " all of my " + items.nameForId(item_type) + " into the chest at " + chest_position.floored() + ".");
                            }
                        }
                    } else {
                        if (command === "loot") {
                            responder_fun("Going to go " + command + " everything from the chest at " + chest_position.floored() + ".");
                        } else {
                            responder_fun("Going to go " + command + " everything into the chest at " + chest_position.floored() + ".");
                        }
                    }
                    navigator.navigateTo(chest_position,{
                        end_radius : 3,
                        timeout_milliseconds: 6 * 1000,
                        cant_find_func : cant_navto_func,
                        arrived_func : useChestData
                    });
                }
            }
        }, function stop() {
            if (inventory.currentlyOpenWindow !== undefined) {
                mf.closeWindow();
            }
        }, function toString() {
            if (item_type === undefined) {
                if (command === "loot") {
                    if (mf.blockAt(chest_position).type !== mf.ItemType.Chest) {
                        return "loot everything near " + location_string;
                    } else {
                        return "loot everything from chest at " + chest_position;
                    }
                } else {
                    if (mf.blockAt(chest_position).type !== mf.ItemType.Chest) {
                        return "dump everything near " + location_string;
                    } else {
                        return "dump everything into chest at " + chest_position;
                    }
                }
            } else if (item_count === undefined) {
                if (command === "loot") {
                    if (mf.blockAt(chest_position).type !== mf.ItemType.Chest) {
                        return "loot all " + items.nameForId(item_type) + " from chest near " + location_string;
                    } else {
                        return "loot all " + items.nameForId(item_type) + " from chest at " + chest_position;
                    }
                } else {
                    if (mf.blockAt(chest_position).type !== mf.ItemType.Chest) {
                        return "dump all " + items.nameForId(item_type) + " into chest near " + location_string;
                    } else {
                        return "dump all " + items.nameForId(item_type) + " into chest at " + chest_position;
                    }
                }
            }
        });
        task_manager.doLater(task);
    };

    chat_commands.registerCommand("loot", function(speaker, args, responder_fun) {
       useChest(speaker, args, responder_fun, "loot");
    }, 0, Infinity);

    chat_commands.registerCommand("dump", function(speaker, args, responder_fun) {
        useChest(speaker,args,responder_fun,"dump");
    }, 0, Infinity);
})();
<|endoftext|>


<commit_before>// Examples of commonly used models
import { BasicModel } from "../src/basic-model"

export const Primitive = BasicModel([Boolean, Number, String, Symbol]).as("Primitive");

// Booleans-like
export const Falsy = BasicModel([Primitive, null, undefined]).assert(function isFalsy(x){ return !x }).as("Falsy");
export const Truthy = BasicModel([Primitive, Object]).assert(function isTruthy(x){ return !!x }).as("Truthy");

// Numbers
export const Integer = BasicModel(Number).assert(Number.isInteger).as("Integer");
export const SafeInteger = BasicModel(Number).assert(Number.isSafeInteger).as("SafeInteger");
export const FiniteNumber = BasicModel(Number).assert(Number.isFinite).as("FiniteNumber");
export const PositiveNumber = BasicModel(Number).assert(function isPositive(n){ return n >= 0 }).as("PositiveNumber");
export const NegativeNumber = BasicModel(Number).assert(function isNegative(n){ return n <= 0 }).as("NegativeNumber");
export const PositiveInteger = PositiveNumber.extend().assert(Number.isInteger).as("PositiveInteger");
export const NegativeInteger = NegativeNumber.extend().assert(Number.isInteger).as("NegativeInteger");

// Strings
export const StringNotBlank = BasicModel(String).assert(function isNotBlank(str){
	return str.trim().length > 0
}).as("StringNotBlank");
export const NormalizedString = BasicModel(String).assert(function isNormalized(str){
	return str.normalize() === str
}).as("NormalizedString");
export const TrimmedString = BasicModel(String).assert(function isTrimmed(str){
	return str.trim() === str
}).as("TrimmedString");

// Dates
export const PastDate = BasicModel(Date).assert(function isInThePast(date){
	return date.getTime() < Date.now()
}).as("PastDate");
export const FutureDate = BasicModel(Date).assert(function isInTheFuture(date){
	return date.getTime() > Date.now()
}).as("FutureDate");

// Arrays
export const ArrayNotEmpty = BasicModel(Array).assert(function isNotEmpty(arr){
	return arr.length > 0
}).as("ArrayNotEmpty");
export const ArrayUnique = BasicModel(Array).assert(function hasNoDuplicates(arr){
	return arr.every((val, idx) => arr.indexOf(val) === idx)
}).as("ArrayUnique");
export const ArrayDense = BasicModel(Array).assert(function hasNoHoles(arr){
	return arr.filter(() => true).length === arr.length
}).as("ArrayDense");<commit_msg>updated common models to es6<commit_after>// Examples of commonly used models
import {BasicModel} from "objectmodel"

export const Primitive = BasicModel([Boolean, Number, String, Symbol]).as("Primitive");

// Booleans-like
export const Falsy = BasicModel([Primitive, null, undefined]).assert(function isFalsy(x){ return !x }).as("Falsy");
export const Truthy = BasicModel([Primitive, Object]).assert(function isTruthy(x){ return !!x }).as("Truthy");

// Numbers
export const Integer = BasicModel(Number).assert(Number.isInteger).as("Integer");
export const SafeInteger = BasicModel(Number).assert(Number.isSafeInteger).as("SafeInteger");
export const FiniteNumber = BasicModel(Number).assert(Number.isFinite).as("FiniteNumber");
export const PositiveNumber = BasicModel(Number).assert(function isPositive(n){ return n >= 0 }).as("PositiveNumber");
export const NegativeNumber = BasicModel(Number).assert(function isNegative(n){ return n <= 0 }).as("NegativeNumber");
export const PositiveInteger = PositiveNumber.extend().assert(Number.isInteger).as("PositiveInteger");
export const NegativeInteger = NegativeNumber.extend().assert(Number.isInteger).as("NegativeInteger");

// Strings
export const StringNotBlank   = BasicModel(String).assert(function isNotBlank(str) {
	return str.trim().length > 0
}).as("StringNotBlank");
export const NormalizedString = BasicModel(String).assert(function isNormalized(str) {
	return str.normalize() === str
}).as("NormalizedString");
export const TrimmedString    = BasicModel(String).assert(function isTrimmed(str) {
	return str.trim() === str
}).as("TrimmedString");

// Dates
export const PastDate   = BasicModel(Date).assert(function isInThePast(date) {
	return date.getTime() < Date.now()
}).as("PastDate");
export const FutureDate = BasicModel(Date).assert(function isInTheFuture(date) {
	return date.getTime() > Date.now()
}).as("FutureDate");

// Arrays
export const ArrayNotEmpty = BasicModel(Array).assert(function isNotEmpty(arr) {
	return arr.length > 0
}).as("ArrayNotEmpty");
export const ArrayUnique   = BasicModel(Array).assert(function hasNoDuplicates(arr) {
	return arr.every((x, i) => arr.indexOf(x) === i)
}).as("ArrayUnique");
export const ArrayDense    = BasicModel(Array).assert(function hasNoHoles(arr) {
	return arr.filter(() => true).length === arr.length
}).as("ArrayDense");<|endoftext|>


<commit_before>'use strict';

describe('EmojiUtil', function() {
    describe('getCountOfAllMatches', function() {
        it('returns zero for string with no matches', function() {
            var r = /s/g;
            var str = 'no match';
            var actual = emoji.getCountOfAllMatches(str, r);
            assert.equal(actual, 0);
        });
        it('returns 1 for one match', function() {
            var r = /s/g;
            var str = 'just one match';
            var actual = emoji.getCountOfAllMatches(str, r);
            assert.equal(actual, 1);
        });
        it('returns 2 for two matches', function() {
            var r = /s/g;
            var str = 's + s';
            var actual = emoji.getCountOfAllMatches(str, r);
            assert.equal(actual, 2);
        });
        it('returns zero for no match with non-global regular expression', function() {
            var r = /s/g;
            var str = 'no match';
            var actual = emoji.getCountOfAllMatches(str, r);
            assert.equal(actual, 0);
        });
        it('returns 1 for match with non-global regular expression', function() {
            var r = /s/;
            var str = 's + s';
            var actual = emoji.getCountOfAllMatches(str, r);
            assert.equal(actual, 1);
        });
    });

    describe('hasNormalCharacters', function() {
        it('returns true for all normal text', function() {
            var str = 'normal';
            var actual = emoji.hasNormalCharacters(str);
            assert.equal(actual, true);
        });
        it('returns false for all emoji text', function() {
            var str = '🔥🔥🔥🔥';
            var actual = emoji.hasNormalCharacters(str);
            assert.equal(actual, false);
        });
        it('returns false for emojis mixed with spaces', function() {
            var str = '🔥 🔥 🔥 🔥';
            var actual = emoji.hasNormalCharacters(str);
            assert.equal(actual, false);
        });
        it('returns true for emojis and text', function() {
            var str = '🔥 normal 🔥 🔥 🔥';
            var actual = emoji.hasNormalCharacters(str);
            assert.equal(actual, true);
        });
    });

    describe('getSizeClass', function() {
        it('returns nothing for non-emoji text', function() {
            assert.equal(emoji.getSizeClass('normal text'), '');
        });
        it('returns nothing for emojis mixed with text', function() {
            assert.equal(emoji.getSizeClass('🔥 normal 🔥'), '');
        });
        it('returns nothing for more than 8 emojis', function() {
            assert.equal(emoji.getSizeClass('🔥🔥 🔥🔥 🔥🔥 🔥🔥 🔥'), '');
        });
        it('returns "small" for 7-8 emojis', function() {
            assert.equal(emoji.getSizeClass('🔥🔥 🔥🔥 🔥🔥 🔥🔥'), 'small');
            assert.equal(emoji.getSizeClass('🔥🔥 🔥🔥 🔥🔥 🔥'), 'small');
        });
        it('returns "medium" for 5-6 emojis', function() {
            assert.equal(emoji.getSizeClass('🔥🔥 🔥🔥 🔥🔥'), 'medium');
            assert.equal(emoji.getSizeClass('🔥🔥 🔥🔥 🔥'), 'medium');
        });
        it('returns "large" for 3-4 emojis', function() {
            assert.equal(emoji.getSizeClass('🔥🔥 🔥🔥'), 'large');
            assert.equal(emoji.getSizeClass('🔥🔥 🔥'), 'large');
        });
        it('returns "jumbo" for 1-2 emojis', function() {
            assert.equal(emoji.getSizeClass('🔥🔥'), 'jumbo');
            assert.equal(emoji.getSizeClass('🔥'), 'jumbo');
        });
    });

    describe('replacement', function() {
        it('returns an  tag', function() {
            var actual = emoji.replacement('1f525');
            assert.equal(actual, '');
        });
        it('returns an  tag with provided sizeClass', function() {
            var actual = emoji.replacement('1f525', 'large');
            assert.equal(actual, '');
        });
    });

    describe('replace_unified', function() {
        it('returns images for every emoji', function() {
            var actual = emoji.replace_unified('🏠 🔥');
            var expected = ''
                + ' ';

            assert.equal(expected, actual);
        });
        it('properly hyphenates a variation', function() {
            var actual = emoji.replace_unified('💪🏿'); // muscle with dark skin tone modifier
            var expected = '';

            assert.equal(expected, actual);
        });
    });
});
<commit_msg>Fix emoji tests - image paths are no longer absolute<commit_after>'use strict';

describe('EmojiUtil', function() {
    describe('getCountOfAllMatches', function() {
        it('returns zero for string with no matches', function() {
            var r = /s/g;
            var str = 'no match';
            var actual = emoji.getCountOfAllMatches(str, r);
            assert.equal(actual, 0);
        });
        it('returns 1 for one match', function() {
            var r = /s/g;
            var str = 'just one match';
            var actual = emoji.getCountOfAllMatches(str, r);
            assert.equal(actual, 1);
        });
        it('returns 2 for two matches', function() {
            var r = /s/g;
            var str = 's + s';
            var actual = emoji.getCountOfAllMatches(str, r);
            assert.equal(actual, 2);
        });
        it('returns zero for no match with non-global regular expression', function() {
            var r = /s/g;
            var str = 'no match';
            var actual = emoji.getCountOfAllMatches(str, r);
            assert.equal(actual, 0);
        });
        it('returns 1 for match with non-global regular expression', function() {
            var r = /s/;
            var str = 's + s';
            var actual = emoji.getCountOfAllMatches(str, r);
            assert.equal(actual, 1);
        });
    });

    describe('hasNormalCharacters', function() {
        it('returns true for all normal text', function() {
            var str = 'normal';
            var actual = emoji.hasNormalCharacters(str);
            assert.equal(actual, true);
        });
        it('returns false for all emoji text', function() {
            var str = '🔥🔥🔥🔥';
            var actual = emoji.hasNormalCharacters(str);
            assert.equal(actual, false);
        });
        it('returns false for emojis mixed with spaces', function() {
            var str = '🔥 🔥 🔥 🔥';
            var actual = emoji.hasNormalCharacters(str);
            assert.equal(actual, false);
        });
        it('returns true for emojis and text', function() {
            var str = '🔥 normal 🔥 🔥 🔥';
            var actual = emoji.hasNormalCharacters(str);
            assert.equal(actual, true);
        });
    });

    describe('getSizeClass', function() {
        it('returns nothing for non-emoji text', function() {
            assert.equal(emoji.getSizeClass('normal text'), '');
        });
        it('returns nothing for emojis mixed with text', function() {
            assert.equal(emoji.getSizeClass('🔥 normal 🔥'), '');
        });
        it('returns nothing for more than 8 emojis', function() {
            assert.equal(emoji.getSizeClass('🔥🔥 🔥🔥 🔥🔥 🔥🔥 🔥'), '');
        });
        it('returns "small" for 7-8 emojis', function() {
            assert.equal(emoji.getSizeClass('🔥🔥 🔥🔥 🔥🔥 🔥🔥'), 'small');
            assert.equal(emoji.getSizeClass('🔥🔥 🔥🔥 🔥🔥 🔥'), 'small');
        });
        it('returns "medium" for 5-6 emojis', function() {
            assert.equal(emoji.getSizeClass('🔥🔥 🔥🔥 🔥🔥'), 'medium');
            assert.equal(emoji.getSizeClass('🔥🔥 🔥🔥 🔥'), 'medium');
        });
        it('returns "large" for 3-4 emojis', function() {
            assert.equal(emoji.getSizeClass('🔥🔥 🔥🔥'), 'large');
            assert.equal(emoji.getSizeClass('🔥🔥 🔥'), 'large');
        });
        it('returns "jumbo" for 1-2 emojis', function() {
            assert.equal(emoji.getSizeClass('🔥🔥'), 'jumbo');
            assert.equal(emoji.getSizeClass('🔥'), 'jumbo');
        });
    });

    describe('replacement', function() {
        it('returns an  tag', function() {
            var actual = emoji.replacement('1f525');
            assert.equal(actual, '');
        });
        it('returns an  tag with provided sizeClass', function() {
            var actual = emoji.replacement('1f525', 'large');
            assert.equal(actual, '');
        });
    });

    describe('replace_unified', function() {
        it('returns images for every emoji', function() {
            var actual = emoji.replace_unified('🏠 🔥');
            var expected = ''
                + ' ';

            assert.equal(expected, actual);
        });
        it('properly hyphenates a variation', function() {
            var actual = emoji.replace_unified('💪🏿'); // muscle with dark skin tone modifier
            var expected = '';

            assert.equal(expected, actual);
        });
    });
});
<|endoftext|>


<commit_before>import {
  getQueryStringParam, Component, DefaultDOMElement, parseKeyEvent
} from 'substance'
import {
  Texture, JATSImportDialog, TextureArchive,
  VfsClient, HttpStorageClient, InMemoryBuffer
} from 'substance-texture'

window.addEventListener('load', () => {
  MyTextureEditor.mount({}, window.document.body)
})

/* Sample integration of Texture */
class MyTextureEditor extends Component {

  didMount() {
    this._init()
    DefaultDOMElement.getBrowserWindow().on('keydown', this._keyDown, this)
  }

  dispose() {
    DefaultDOMElement.getBrowserWindow().off(this)
  }

  getInitialState() {
    return {
      archive: undefined,
      error: undefined
    }
  }

  render($$) {
    let el = $$('div').addClass('sc-app')
    let archive = this.state.archive
    let err = this.state.error

    if (archive) {
      el.append(
        $$(Texture, {archive})
      )
    } else if (err) {
      if (err.type === 'jats-import-error') {
        el.append(
          $$(JATSImportDialog, { errors: err.detail })
        )
      } else {
        el.append(
          'ERROR:',
          err.message
        )
      }
    } else {
      // LOADING...
    }
    return el
  }

  _init() {
    let archiveId = getQueryStringParam('archive')
    let storageType = getQueryStringParam('storage')
    let storageUrl = getQueryStringParam('storageUrl') || '/archives'
    let storage
    if (storageType==='vfs') {
      storage = new VfsClient(window.vfs, '/data/')
    } else {
      storage = new HttpStorageClient(storageUrl)
    }
    let buffer = new InMemoryBuffer()
    let archive = new TextureArchive(storage, buffer)
    archive.load(archiveId)
    .then(() => {
      this.setState({archive})
    }).catch(error => {
      console.error(error)
      this.setState({error})
    })
  }

  /*
    We may want an explicit save button, that can be configured on app level,
    but passed down to editor toolbars.
  */
  _save() {
    this.state.archive.save().then(() => {
      console.info('successfully saved')
    }).catch(err => {
      console.error(err)
    })
  }

  _keyDown(e) {
    let key = parseKeyEvent(e)
    if (key === 'META+83') {
      this._save()
      e.preventDefault()
    }
  }
}
<commit_msg>Use some defaults for the boot.<commit_after>import {
  getQueryStringParam, Component, DefaultDOMElement, parseKeyEvent
} from 'substance'
import {
  Texture, JATSImportDialog, TextureArchive,
  VfsClient, HttpStorageClient, InMemoryBuffer
} from 'substance-texture'

window.addEventListener('load', () => {
  MyTextureEditor.mount({}, window.document.body)
})

/* Sample integration of Texture */
class MyTextureEditor extends Component {

  didMount() {
    this._init()
    DefaultDOMElement.getBrowserWindow().on('keydown', this._keyDown, this)
  }

  dispose() {
    DefaultDOMElement.getBrowserWindow().off(this)
  }

  getInitialState() {
    return {
      archive: undefined,
      error: undefined
    }
  }

  render($$) {
    let el = $$('div').addClass('sc-app')
    let archive = this.state.archive
    let err = this.state.error

    if (archive) {
      el.append(
        $$(Texture, {archive})
      )
    } else if (err) {
      if (err.type === 'jats-import-error') {
        el.append(
          $$(JATSImportDialog, { errors: err.detail })
        )
      } else {
        el.append(
          'ERROR:',
          err.message
        )
      }
    } else {
      // LOADING...
    }
    return el
  }

  _init() {
    let archiveId = getQueryStringParam('archive') || 'kitchen-sink'
    let storageType = getQueryStringParam('storage') || 'vfs'
    let storageUrl = getQueryStringParam('storageUrl') || '/archives'
    let storage
    if (storageType==='vfs') {
      storage = new VfsClient(window.vfs, './data/')
    } else {
      storage = new HttpStorageClient(storageUrl)
    }
    let buffer = new InMemoryBuffer()
    let archive = new TextureArchive(storage, buffer)
    archive.load(archiveId)
    .then(() => {
      this.setState({archive})
    }).catch(error => {
      console.error(error)
      this.setState({error})
    })
  }

  /*
    We may want an explicit save button, that can be configured on app level,
    but passed down to editor toolbars.
  */
  _save() {
    this.state.archive.save().then(() => {
      console.info('successfully saved')
    }).catch(err => {
      console.error(err)
    })
  }

  _keyDown(e) {
    let key = parseKeyEvent(e)
    if (key === 'META+83') {
      this._save()
      e.preventDefault()
    }
  }
}
<|endoftext|>


<commit_before>function setup() {
  createCanvas(720, 560);

}

function draw() {
	background('AntiqueWhite');

	fill('MistyRose');

  	//arc(350, 200, 200, 225, -PI, 0);
  	arc(350, 200, 200, 225, -PI, 0);

  	fill('#4d2600');

    //ellipse(310, 200, 5, map(second(), 59, 0, 0, 59));
    //ellipse(310, 100, 5, map(second(), 0, 59, 300, 5));

  	fill('Wheat');
  	triangle(350-200 / 2, 200 + 5, 350 + 200 / 2, 200 + 5, 350, 200 + 200 * 1.3);

}

// reference aid: http://alpha.editor.p5js.org/ellacyt/sketches/ByaJx92j-<commit_msg>add mapping for sec,min,hour and translation<commit_after>function setup() {
  createCanvas(720, 560);
}

function draw() {

  // canvas color
	background('AntiqueWhite');

  // ice cream color
	fill('MistyRose');

  // ice cream shape
  // arc shifts according to seconds
  arc(350, 200, 200, 225, map(minute(), 59, 0, 30, 60), 0);

  // chocolate cherry color
  fill('#4d2600');

  // chocolate cherry grows according to hours
  ellipse(350, 80, map(hour(), 0, 59, 10, 150), map(hour(), 0, 59, 10, 150));

  // cone color
  fill('Wheat');

  triangle(240, 205, 460, 205, 350, 460);

  // text color
  fill('Black');

  // translate text according to seconds
  translate(10, map(second(), 0, 59, 10, 150));

  // print text
  textSize(20);
  text("Now " + hour() + ":" + minute() + ":" + second(), 10, 150);

}

// reference aid (for cone): http://alpha.editor.p5js.org/ellacyt/sketches/ByaJx92j-<|endoftext|>


<commit_before>/*
* DolStatistics plugin
*/
mw.DolStatistics = function( embedPlayer, callback ){
	this.init( embedPlayer, callback );
};

mw.DolStatistics.prototype = {

	pluginVersion: "1.1",
	bindPostFix: '.DolStatistics',
	appName: 'KDP',

	// Number of seconds between playhead event dispatches
	playheadFrequency: 5,
	playheadInterval: 0,

	// Entry duration
	duration: 0,

	// hold list of cue points per 10% of video duration
	percentCuePoints: {},

	init: function( embedPlayer, callback ){
		var _this = this;
		this.embedPlayer = embedPlayer;

		// List of all attributes we need from plugin configuration (flashVars/uiConf)
		var attributes = [
			'listenTo',
			'playheadFrequency',
			'jsFunctionName',
			'protocol',
			'host',
			'ASSETNAME',
			'GENURL',
			'GENTITLE',
			'DEVID',
			'USRAGNT',
			'ASSETID'
		];
		this.playheadFrequency = this.getConfig( 'playheadFrequency' ) || 5;

		// List of events we need to track
		var eventList = this.getConfig( 'listenTo' );
		this.eventsList = eventList.split(",");

		mw.log( 'DolStatistics:: eventList:' + this.eventsList );

		// Setup player counter, ( used global, because on change media we re-initialize the plugin and reset all vars )
		if( typeof $( embedPlayer ).data('DolStatisticsCounter') == 'undefined' ) {
			if( embedPlayer['data-playerError'] ){
				$( embedPlayer ).data('DolStatisticsCounter', 0 )
			} else {
				$( embedPlayer ).data('DolStatisticsCounter', 1 );
			}
		}
		// also increment counter during replays:
		embedPlayer.bindHelper('replayEvent', function(){
			// reset the percentage reached counter:
			_this.calcCuePoints();
			var curVal = $( embedPlayer ).data('DolStatisticsCounter' );
			 $( embedPlayer ).data('DolStatisticsCounter', curVal+1 );
		});

		mw.log('DolStatistics:: Init plugin :: Plugin config: ', this.embedPlayer.getKalturaConfig( 'dolStatistics') );

		// Add player binding
		this.addPlayerBindings( callback );
	},
	getConfig: function( attr ){
		return this.embedPlayer.getKalturaConfig( 'dolStatistics', attr );
	},
	addPlayerBindings: function( callback ) {
		var _this = this;
		var embedPlayer = this.embedPlayer;
		var $embedPlayer = $( embedPlayer );

		// Unbind any existing bindings
		this.destroy();

		// On change media remove any existing ads:
		embedPlayer.bindHelper( 'onChangeMediaDone' + _this.bindPostFix, function(){
			if( ! embedPlayer['data-playerError'] ){
				$embedPlayer.data('DolStatisticsCounter', $embedPlayer.data('DolStatisticsCounter') + 1 );
			}
			_this.destroy();
		});
		// Register to our events
		$.each(this.eventsList, function(k, eventName) {
			switch( eventName ) {
				// Special event
				case 'percentReached':
					_this.calcCuePoints();
					embedPlayer.bindHelper( 'monitorEvent' + _this.bindPostFix, function() {
						_this.monitorPercentage();
					});
				break;
				case 'volumeChanged':
					embedPlayer.addJsListener(eventName + _this.bindPostFix, function( eventData ) {
						_this.sendStatsData( 'volumeChanged', eventData.newVolume );
					});
				break;
				// Change playerUpdatePlayhead event to send events on playheadFrequency
				case 'playerUpdatePlayhead':
					_this.addMonitorBindings();
				break;
				// Use addJsListener for all other events
				default:
					embedPlayer.addJsListener(eventName + _this.bindPostFix, function( argValue ) {
						var eventData = '';
						if( typeof argValue == 'object' ){
							eventData = JSON.stringify( argValue );
						} else {
							eventData = argValue;
						}
						_this.sendStatsData( eventName, eventData );
					});
				break;
			}

		});
		mw.log('DolStatistics:: addPlayerBindings:: Events list: ', this.eventsList);
		// Continue player build out
		callback();
	},

	/* Create Index of Cue Points per 10% of video duration */
	calcCuePoints: function() {
		var _this = this;
		var duration = this.getDuration();

		for( var i=0; i<=100; i=i+10 ) {
			var cuePoint = Math.round( duration / 100 * i );
			_this.percentCuePoints[ cuePoint ] = false;
		}

		mw.log('DolStatistics:: calcCuePoints:: ', _this.percentCuePoints);
	},

	/* Custom percentReached event */
	monitorPercentage: function() {
		var _this = this;
		var duration = this.getDuration();
		var percentCuePoints = this.percentCuePoints;
		var currentTime = Math.round( this.embedPlayer.currentTime );

		// make sure 0% is fired
		if( currentTime > 0 && ! percentCuePoints[ 0 ] ){
			percentCuePoints[ 0 ] = true;
			_this.sendStatsData( 'percentReached', 0 );
		}

		if( percentCuePoints[ currentTime ] === false ) {
			percentCuePoints[ currentTime ] = true;
			var percent = Math.round(currentTime * 100 / duration );
			_this.sendStatsData( 'percentReached', percent );
		}
	},

	/* Custom playerUpdatePlayhead event */
	addMonitorBindings: function() {
		var _this = this;
		var embedPlayer = this.embedPlayer;
		var intervalTime = this.playheadFrequency * 1000;

		// Start monitor
		embedPlayer.bindHelper('onplay' + _this.bindPostFix, function() {
			if( ! _this.playheadInterval ) {
				_this.playheadInterval = setInterval( function(){
					_this.sendStatsData( 'playerUpdatePlayhead' , embedPlayer.currentTime);
				}, intervalTime );
			}
		});

		// Stop monitor
		embedPlayer.bindHelper('doStop' + _this.bindPostFix + ' onpause' + _this.bindPostFix + ' onChangeMedia' + _this.bindPostFix, function() {
			clearInterval( _this.playheadInterval );
			_this.playheadInterval = 0;
		});
	},

	/* Retrive video duration */
	getDuration: function() {
		if( ! this.duration ){
			this.duration = this.embedPlayer.evaluate('{duration}');
		}
		return this.duration;
	},

	getBitrate: function() {
		if( this.embedPlayer.mediaElement.selectedSource ) {
			return this.embedPlayer.mediaElement.selectedSource.getBitrate() || 0;
		}
		return 0;
	},

	/* Send stats data using Beacon or jsCallback */
	sendStatsData: function( eventName, eventData ) {
		var _this = this;
		var embedPlayer = this.embedPlayer;
		// If event name not in our event list, exit
		if( this.eventsList.indexOf( eventName ) === -1 ) {
			return ;
		}

		// Setup event params
		var params = {};
		// App name
		params['app'] = this.appName;
		// Grab from plugin config
		var configAttrs = [ 'DEVID', 'ASSETNAME', 'ASSETID' ];
		for( var x=0; x<configAttrs.length; x++) {
			params[ configAttrs[x] ] = _this.getConfig( configAttrs[x] ) || '';
		}
		// The auto played property;
		params['AUTO'] = embedPlayer.autoplay;
		// Embedded Page URL
		params['GENURL'] =  _this.getConfig('GENURL') || window.kWidgetSupport.getHostPageUrl();
		// Embedded Page Title
		params['GENTITLE'] =  _this.getConfig('GENTITLE') || mw.getConfig( 'EmbedPlayer.IframeParentTitle' );
		// User Agent
		params['USRAGNT'] =  _this.getConfig('USRAGNT') || window.navigator.userAgent;
		// Current Timestamp
		params['GENTIME'] = new Date().getTime();
		// Widget ID
		params['WIGID'] = this.embedPlayer.kwidgetid;
		// Flavor Bitrate
		params['BITRATE'] = this.getBitrate();
		// Video length
		params['VIDLEN'] = this.getDuration();
		// Player protocol ( hard coded to html5 )
		params['KDPPROTO'] = 'html5'; //mw.parseUri( mw.getConfig( 'Kaltura.ServiceUrl' ) ).protocol;
		// Kaltura Player ID
		params['KDPID'] = this.embedPlayer.kuiconfid;
		// Kaltura Session ID
		params['KSESSIONID'] = this.embedPlayer.evaluate('{configProxy.sessionId}');
		// Kaltura Playback ID ( kSessionId + playbackCounter )
		params['KPLAYBACKID'] = this.embedPlayer.evaluate('{configProxy.sessionId}') + $( this.embedPlayer ).data('DolStatisticsCounter');
		// Kaltura session Seq
		params['KSESSIONSEQ'] = $( this.embedPlayer ).data('DolStatisticsCounter');
		// Kaltura Event name
		params['KDPEVNT'] = eventName;
		// KDP Event Data
		params['KDPDAT_VALUE'] = eventData.toString();
		// Always include the current time:
		params['KDPDAT_PLAYHEAD'] = this.embedPlayer.currentTime;

		// try and pull the page title from the parent:
		try{
			params['HTML5GenTitle'] = parent.document.title;
		} catch (e){
			// could not get title from parent frame
		}

		// Add custom params
		for( var i =0; i < 10; i++ ){
			// Check for custom data key value pairs ( up to 9 )
			if( _this.getConfig( 'customDataKey' + i ) &&  _this.getConfig( 'customDataValue' + i ) ){
				params[ _this.getConfig( 'customDataKey' + i ) ] =  _this.getConfig( 'customDataValue' + i );
			}
		}
		// filter out undefined == NULL
		// TODO this is kind of an ugly hack we should have
		// evaluate support fallback names for undefined properties
		for( var i in params ){
			if( typeof params[i] == 'string' ){
				// Find undefined with no space on either side
				params[i] = params[i].replace( /undefined/g, 'NULL' );
			}
		}

		mw.log('DolStatistics:: Send Stats Data ' + statsUrl, params);

		// If we have access to parent, call the jsFunction provided
		if( this.getConfig( 'jsFunctionName' ) && window.parent ) {
			var callbackName = this.getConfig( 'jsFunctionName' );
			this._executeFunctionByName( callbackName, window.parent, params);
		} else {
			// Use beacon to send event data
			var statsUrl = this.getConfig( 'protocol' ) + '://' + this.getConfig( 'host' ) + '?' + $.param(params);
			$('body').append(
				$( '<img />' ).attr({
					'src' : statsUrl,
					'width' : 0,
					'height' : 0
				})
			);
		}
	},

	destroy: function() {
		clearInterval( this.playheadInterval );
		this.playheadInterval = 0;
		this.embedPlayer.unbindHelper( this.bindPostFix );
		this.percentCuePoints = {};
		this.duration = 0;
	},

	/* Execute function like: "cto.trackVideo" */
	_executeFunctionByName: function( functionName, context /*, args */) {
		var args = Array.prototype.slice.call(arguments).splice(2);
		var namespaces = functionName.split(".");
		var func = namespaces.pop();
		for(var i = 0; i < namespaces.length; i++) {
			context = context[namespaces[i]];
		}
		return context[func].apply(this, args);
	}
};<commit_msg>fix for NULL to use empty string<commit_after>/*
* DolStatistics plugin
*/
mw.DolStatistics = function( embedPlayer, callback ){
	this.init( embedPlayer, callback );
};

mw.DolStatistics.prototype = {

	pluginVersion: "1.1",
	bindPostFix: '.DolStatistics',
	appName: 'KDP',

	// Number of seconds between playhead event dispatches
	playheadFrequency: 5,
	playheadInterval: 0,

	// Entry duration
	duration: 0,

	// hold list of cue points per 10% of video duration
	percentCuePoints: {},

	init: function( embedPlayer, callback ){
		var _this = this;
		this.embedPlayer = embedPlayer;

		// List of all attributes we need from plugin configuration (flashVars/uiConf)
		var attributes = [
			'listenTo',
			'playheadFrequency',
			'jsFunctionName',
			'protocol',
			'host',
			'ASSETNAME',
			'GENURL',
			'GENTITLE',
			'DEVID',
			'USRAGNT',
			'ASSETID'
		];
		this.playheadFrequency = this.getConfig( 'playheadFrequency' ) || 5;

		// List of events we need to track
		var eventList = this.getConfig( 'listenTo' );
		this.eventsList = eventList.split(",");

		mw.log( 'DolStatistics:: eventList:' + this.eventsList );

		// Setup player counter, ( used global, because on change media we re-initialize the plugin and reset all vars )
		if( typeof $( embedPlayer ).data('DolStatisticsCounter') == 'undefined' ) {
			if( embedPlayer['data-playerError'] ){
				$( embedPlayer ).data('DolStatisticsCounter', 0 )
			} else {
				$( embedPlayer ).data('DolStatisticsCounter', 1 );
			}
		}
		// also increment counter during replays:
		embedPlayer.bindHelper('replayEvent' + this.bindPostFix, function(){
			// reset the percentage reached counter:
			_this.calcCuePoints();
			var curVal = $( embedPlayer ).data('DolStatisticsCounter' );
			 $( embedPlayer ).data('DolStatisticsCounter', curVal+1 );
		});

		mw.log('DolStatistics:: Init plugin :: Plugin config: ', this.embedPlayer.getKalturaConfig( 'dolStatistics') );

		// Add player binding
		this.addPlayerBindings( callback );
	},
	getConfig: function( attr ){
		return this.embedPlayer.getKalturaConfig( 'dolStatistics', attr );
	},
	addPlayerBindings: function( callback ) {
		var _this = this;
		var embedPlayer = this.embedPlayer;
		var $embedPlayer = $( embedPlayer );

		// Unbind any existing bindings
		this.destroy();

		// On change media remove any existing bindings:
		embedPlayer.bindHelper( 'onChangeMediaDone' + _this.bindPostFix, function(){
			if( ! embedPlayer['data-playerError'] ){
				$embedPlayer.data('DolStatisticsCounter', $embedPlayer.data('DolStatisticsCounter') + 1 );
			}
		});
		// Register to our events
		$.each(this.eventsList, function(k, eventName) {
			switch( eventName ) {
				// Special event
				case 'percentReached':
					_this.calcCuePoints();
					embedPlayer.bindHelper( 'monitorEvent' + _this.bindPostFix, function() {
						_this.monitorPercentage();
					});
				break;
				case 'volumeChanged':
					embedPlayer.addJsListener(eventName + _this.bindPostFix, function( eventData ) {
						_this.sendStatsData( 'volumeChanged', eventData.newVolume );
					});
				break;
				// Change playerUpdatePlayhead event to send events on playheadFrequency
				case 'playerUpdatePlayhead':
					_this.addMonitorBindings();
				break;
				// Use addJsListener for all other events
				default:
					embedPlayer.addJsListener(eventName + _this.bindPostFix, function( argValue ) {
						var eventData = '';
						if( typeof argValue == 'object' ){
							eventData = JSON.stringify( argValue );
						} else {
							eventData = argValue;
						}
						_this.sendStatsData( eventName, eventData );
					});
				break;
			}

		});
		mw.log('DolStatistics:: addPlayerBindings:: Events list: ', this.eventsList);
		// Continue player build out
		callback();
	},

	/* Create Index of Cue Points per 10% of video duration */
	calcCuePoints: function() {
		var _this = this;
		var duration = this.getDuration();

		for( var i=0; i<=100; i=i+10 ) {
			var cuePoint = Math.round( duration / 100 * i );
			_this.percentCuePoints[ cuePoint ] = false;
		}

		mw.log('DolStatistics:: calcCuePoints:: ', _this.percentCuePoints);
	},

	/* Custom percentReached event */
	monitorPercentage: function() {
		var _this = this;
		var duration = this.getDuration();
		var percentCuePoints = this.percentCuePoints;
		var currentTime = Math.round( this.embedPlayer.currentTime );
		mw.log( 'DolStatistics:: monitorPercentage>' + currentTime );

		// make sure 0% is fired
		if( currentTime > 0 && ! percentCuePoints[ 0 ] ){
			percentCuePoints[ 0 ] = true;
			_this.sendStatsData( 'percentReached', 0 );
		}

		if( percentCuePoints[ currentTime ] === false ) {
			percentCuePoints[ currentTime ] = true;
			var percent = Math.round(currentTime * 100 / duration );
			_this.sendStatsData( 'percentReached', percent );
		}
	},

	/* Custom playerUpdatePlayhead event */
	addMonitorBindings: function() {
		var _this = this;
		var embedPlayer = this.embedPlayer;
		var intervalTime = this.playheadFrequency * 1000;

		// Start monitor
		embedPlayer.bindHelper('onplay' + _this.bindPostFix, function() {
			if( ! _this.playheadInterval ) {
				_this.playheadInterval = setInterval( function(){
					_this.sendStatsData( 'playerUpdatePlayhead' , embedPlayer.currentTime);
				}, intervalTime );
			}
		});

		// Stop monitor
		embedPlayer.bindHelper('doStop' + _this.bindPostFix + ' onpause' + _this.bindPostFix + ' onChangeMedia' + _this.bindPostFix, function() {
			clearInterval( _this.playheadInterval );
			_this.playheadInterval = 0;
		});
	},

	/* Retrive video duration */
	getDuration: function() {
		if( ! this.duration ){
			this.duration = this.embedPlayer.evaluate('{duration}');
		}
		return this.duration;
	},

	getBitrate: function() {
		if( this.embedPlayer.mediaElement.selectedSource ) {
			return this.embedPlayer.mediaElement.selectedSource.getBitrate() || 0;
		}
		return 0;
	},

	/* Send stats data using Beacon or jsCallback */
	sendStatsData: function( eventName, eventData ) {
		var _this = this;
		var embedPlayer = this.embedPlayer;
		// If event name not in our event list, exit
		if( this.eventsList.indexOf( eventName ) === -1 ) {
			return ;
		}

		// Setup event params
		var params = {};
		// App name
		params['app'] = this.appName;
		// Grab from plugin config
		var configAttrs = [ 'DEVID', 'ASSETNAME', 'ASSETID' ];
		for( var x=0; x<configAttrs.length; x++) {
			params[ configAttrs[x] ] = _this.getConfig( configAttrs[x] ) || '';
		}
		// The auto played property;
		params['AUTO'] = embedPlayer.autoplay;
		// Embedded Page URL
		params['GENURL'] =  _this.getConfig('GENURL') || window.kWidgetSupport.getHostPageUrl();
		// Embedded Page Title
		params['GENTITLE'] =  _this.getConfig('GENTITLE') || mw.getConfig( 'EmbedPlayer.IframeParentTitle' );
		// User Agent
		params['USRAGNT'] =  _this.getConfig('USRAGNT') || window.navigator.userAgent;
		// Current Timestamp
		params['GENTIME'] = new Date().getTime();
		// Widget ID
		params['WIGID'] = this.embedPlayer.kwidgetid;
		// Flavor Bitrate
		params['BITRATE'] = this.getBitrate();
		// Video length
		params['VIDLEN'] = this.getDuration();
		// Player protocol ( hard coded to html5 )
		params['KDPPROTO'] = 'html5'; //mw.parseUri( mw.getConfig( 'Kaltura.ServiceUrl' ) ).protocol;
		// Kaltura Player ID
		params['KDPID'] = this.embedPlayer.kuiconfid;
		// Kaltura Session ID
		params['KSESSIONID'] = this.embedPlayer.evaluate('{configProxy.sessionId}');
		// Kaltura Playback ID ( kSessionId + playbackCounter )
		params['KPLAYBACKID'] = this.embedPlayer.evaluate('{configProxy.sessionId}') + $( this.embedPlayer ).data('DolStatisticsCounter');
		// Kaltura session Seq
		params['KSESSIONSEQ'] = $( this.embedPlayer ).data('DolStatisticsCounter');
		// Kaltura Event name
		params['KDPEVNT'] = eventName;
		// KDP Event Data
		params['KDPDAT_VALUE'] = eventData.toString();
		// Always include the current time:
		params['KDPDAT_PLAYHEAD'] = this.embedPlayer.currentTime;

		// try and pull the page title from the parent:
		try{
			params['HTML5GenTitle'] = parent.document.title;
		} catch (e){
			// could not get title from parent frame
		}

		// Add custom params
		for( var i =0; i < 10; i++ ){
			// Check for custom data key value pairs ( up to 9 )
			if( _this.getConfig( 'customDataKey' + i ) &&  _this.getConfig( 'customDataValue' + i ) ){
				params[ _this.getConfig( 'customDataKey' + i ) ] =  _this.getConfig( 'customDataValue' + i );
			}
		}
		// filter out undefined == NULL
		// TODO this is kind of an ugly hack we should have
		// evaluate support fallback names for undefined properties
		for( var i in params ){
			if( typeof params[i] == 'string' ){
				// Find undefined with no space on either side
				params[i] = params[i].replace( /undefined/g, '' );
			}
		}

		mw.log('DolStatistics:: Send Stats Data ' + statsUrl, params);

		// If we have access to parent, call the jsFunction provided
		if( this.getConfig( 'jsFunctionName' ) && window.parent ) {
			var callbackName = this.getConfig( 'jsFunctionName' );
			this._executeFunctionByName( callbackName, window.parent, params);
		} else {
			// Use beacon to send event data
			var statsUrl = this.getConfig( 'protocol' ) + '://' + this.getConfig( 'host' ) + '?' + $.param(params);
			$('body').append(
				$( '<img />' ).attr({
					'src' : statsUrl,
					'width' : 0,
					'height' : 0
				})
			);
		}
	},

	destroy: function() {
		clearInterval( this.playheadInterval );
		this.playheadInterval = 0;
		this.embedPlayer.unbindHelper( this.bindPostFix );
		this.percentCuePoints = {};
		this.duration = 0;
	},

	/* Execute function like: "cto.trackVideo" */
	_executeFunctionByName: function( functionName, context /*, args */) {
		var args = Array.prototype.slice.call(arguments).splice(2);
		var namespaces = functionName.split(".");
		var func = namespaces.pop();
		for(var i = 0; i < namespaces.length; i++) {
			context = context[namespaces[i]];
		}
		return context[func].apply(this, args);
	}
};<|endoftext|>


<commit_before>'use strict';

var expect = require('chai').expect;
var Expression = require('../app/scripts/expression');

describe('expression', function () {

  it('should initialize expression with unmodified input string', function () {
    var expression = new Expression({
      string: ' p and q '
    });
    expect(expression).to.have.property('string', ' p and q ');
  });

  function testExprs(args) {
    // Generate a test for each supplied expression
    args.exprStrings.forEach(function (exprString) {
      var expression = new Expression({string: exprString});
      it('should evaluate `' + exprString + '`', function () {
        // Test each expression against the given permutations of variable
        // values and the expected outputs
        args.testCases.forEach(function (testCase) {
          var actualOutput = expression.evaluate(testCase.varValues);
          expect(actualOutput).to.equal(testCase.output);
        });
      });
    });
  }

  describe('NOT operation', function () {
    testExprs({
      exprStrings: ['not p', 'not  p', 'NoT p', '!p', '!  p'],
      testCases: [
        {varValues: {p: false}, output: true},
        {varValues: {p: true}, output: false}
      ]
    });
  });

});
<commit_msg>Add tests for AND operation<commit_after>'use strict';

var expect = require('chai').expect;
var Expression = require('../app/scripts/expression');

describe('expression', function () {

  it('should initialize expression with unmodified input string', function () {
    var expression = new Expression({
      string: ' p and q '
    });
    expect(expression).to.have.property('string', ' p and q ');
  });

  function testExprs(args) {
    // Generate a test for each supplied expression
    args.exprStrings.forEach(function (exprString) {
      var expression = new Expression({string: exprString});
      it('should evaluate `' + exprString + '`', function () {
        // Test each expression against the given permutations of variable
        // values and the expected outputs
        args.testCases.forEach(function (testCase) {
          var actualOutput = expression.evaluate(testCase.varValues);
          expect(actualOutput).to.equal(testCase.output);
        });
      });
    });
  }

  describe('NOT operation', function () {
    testExprs({
      exprStrings: ['not p', 'not  p', 'NoT p', '!p', '!  p'],
      testCases: [
        {varValues: {p: false}, output: true},
        {varValues: {p: true}, output: false}
      ]
    });
  });

  describe('AND operation', function () {
    testExprs({
      exprStrings: ['p and q', 'p  and   q', 'p AnD q', 'p&q', 'p  &  q'],
      testCases: [
        {varValues: {p: false, q: false}, output: false},
        {varValues: {p: false, q: true}, output: false},
        {varValues: {p: true, q: false}, output: false},
        {varValues: {p: true, q: true}, output: true},
      ]
    });
  });

});
<|endoftext|>


<commit_before>jQuery(function($) {
  var $loader = $('#loader'),
      $results = $('#results'),
      $mask = $('#mask');

  var honeycomb = new Honeycomb();

  $loader.on('submit.api', function() {
    var form = this, url = form.url.value || '';

    $.ajax({
      url: url.replace(/https?:/, ''),
      dataType: 'jsonp'
    }).done(function(data) {
      window.json = data;
      var mask = window.mask = honeycomb.parse(data);
      var tree = window.tree = honeycomb.toTree(mask, function(node) {
        node.icon = false;
      });

      $mask.html(JSON.stringify(mask, null, 2));

      $.jstree.destroy();
      $results.jstree({
        'core': {
          'check_callback' : true,
          'data': tree
        },
        'plugins' : [ 'checkbox', 'changed' ]
      })
    }).fail(function() {
      $.jstree.destroy();
    });

    return false;
  });
});<commit_msg>Need to clear the mask too on error<commit_after>jQuery(function($) {
  var $loader = $('#loader'),
      $results = $('#results'),
      $mask = $('#mask');

  var honeycomb = new Honeycomb();

  $loader.on('submit.api', function() {
    var form = this, url = form.url.value || '';

    $.ajax({
      url: url.replace(/https?:/, ''),
      dataType: 'jsonp'
    }).done(function(data) {
      window.json = data;
      var mask = window.mask = honeycomb.parse(data);
      var tree = window.tree = honeycomb.toTree(mask, function(node) {
        node.icon = false;
      });

      $mask.html(JSON.stringify(mask, null, 2));

      $.jstree.destroy();
      $results.jstree({
        'core': {
          'check_callback' : true,
          'data': tree
        },
        'plugins' : [ 'checkbox', 'changed' ]
      })
    }).fail(function() {
      $mask.html('');
      $.jstree.destroy();
    });

    return false;
  });
});<|endoftext|>


<commit_before>/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
/* global Global, app, angular */

app.controller('SlideCtrl', ['$scope', 'HomeServices', function ($scope, HomeServices) {
    $scope.assets = window.location.origin+'/assets/';
    $scope.uploads = window.location.origin+'/uploads/';
    $scope.baseUrl = window.location.origin+'/';
    $scope.assets = Global.assets;
    $scope.uploads = Global.uploads;
    $scope.baseUrl = Global.baseurl;
    var services = [
      'getSlide',
      'getPopup'
    ];
    var params = {};
    var setSlide = function() {
        new RoyalSlider("#myGallery1", {
          captionShowEffects: ["moveleft", "fade"],
          captionShowDelay: 200,
          captionShowSpeed: 400,
          captionShowEasing: "easeOutBack",
          directionNavEnabled: true,
          controlNavEnabled: true,
          slideshowEnabled: true,
          slideshowPauseOnHover: true,
          autoScaleSlider: false,
          loop: true,
          slideshowDelay: 7000
        });
    };
    $scope.slides = [];
//        HomeServices.showLoad(true);
    var callService = function (serviceName) {
//          console.log(serviceName);
      var callServiceName = HomeServices[serviceName](params);
//          console.log(serviceName);
      callServiceName.success(function (data) {
//          console.log(data);
        if (data.status === 'success' && data.data) {
        var getData = angular.extend(data.data);
          if (serviceName === 'getSlide') {
            $scope.slides = getData;
            console.log(data);
            setTimeout(function(){
              setSlide();
            }, 1000);
          } else if  (serviceName === 'getPopup') {
            if (getData) {
              //popup
              $scope.popupUrl = Global.uploads+'popup/'+getData;
              popupShow();
            }
          }
        }
//        HomeServices.showLoad(false);
      }).error(function () {
//        HomeServices.showLoad(false);
        Global.handle.loseInternet();
      });
    };
//    loop call service
    for (name in services) {
      callService(services[name]);
    }

    var popupShow = function(){
      setTimeout(function(){
        $(".popup").colorbox({open:true, rel:'popup', transition:"none", width:"75%", height:"75%"});
      },1000);
    }

  }]);

<commit_msg>update<commit_after>/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
/* global Global, app, angular */

app.controller('SlideCtrl', ['$scope', 'HomeServices', function ($scope, HomeServices) {
    $scope.assets = window.location.origin+'/assets/';
    $scope.uploads = window.location.origin+'/uploads/';
    $scope.baseUrl = window.location.origin+'/';
    $scope.assets = Global.assets;
    $scope.uploads = Global.uploads;
    $scope.baseUrl = Global.baseurl;
    var services = [
      'getSlide',
      'getPopup'
    ];
    var params = {};
    var setSlide = function() {
        new RoyalSlider("#myGallery1", {
          captionShowEffects: ["moveleft", "fade"],
          captionShowDelay: 200,
          captionShowSpeed: 400,
          captionShowEasing: "easeOutBack",
          directionNavEnabled: true,
          controlNavEnabled: true,
          slideshowEnabled: true,
          slideshowPauseOnHover: true,
          autoScaleSlider: false,
          loop: true,
          slideshowDelay: 7000
        });
    };
    $scope.slides = [];
//        HomeServices.showLoad(true);
    var callService = function (serviceName) {
      var callServiceName = HomeServices[serviceName](params);
      callServiceName.success(function (data) {
        if (data.status === 'success' && data.data) {
        var getData = angular.extend(data.data);
          if (serviceName === 'getSlide') {
            $scope.slides = getData;
            console.log(data);
            setTimeout(function(){
              setSlide();
            }, 1000);
          } else if  (serviceName === 'getPopup') {
            if (getData) {
              //popup
              $scope.popupUrl = Global.uploads+'popup/'+getData;
              popupShow();
            }
          }
        }
//        HomeServices.showLoad(false);
      }).error(function () {
//        HomeServices.showLoad(false);
        Global.handle.loseInternet();
      });
    };
//    loop call service
    for (name in services) {
      callService(services[name]);
    }

    var popupShow = function(){
      setTimeout(function(){
        $(".popup").colorbox({open:true, rel:'popup', transition:"none", width:"75%", height:"75%"});
      },1000);
    }

  }]);

<|endoftext|>


<commit_before>var Amber=function(t){var e={};function n(o){if(e[o])return e[o].exports;var i=e[o]={i:o,l:!1,exports:{}};return t[o].call(i.exports,i,i.exports,n),i.l=!0,i.exports}return n.m=t,n.c=e,n.d=function(t,e,o){n.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:o})},n.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},n.t=function(t,e){if(1&e&&(t=n(t)),8&e)return t;if(4&e&&"object"==typeof t&&t&&t.__esModule)return t;var o=Object.create(null);if(n.r(o),Object.defineProperty(o,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var i in t)n.d(o,i,function(e){return t[e]}.bind(null,i));return o},n.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return n.d(e,"a",e),e},n.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},n.p="",n(n.s=0)}([function(t,e,n){"use strict";function o(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function i(t,e){for(var n=0;n<e.length;n++){var o=e[n];o.enumerable=o.enumerable||!1,o.configurable=!0,"value"in o&&(o.writable=!0),Object.defineProperty(t,o.key,o)}}function r(t,e,n){return e&&i(t.prototype,e),n&&i(t,n),t}n.r(e),n.d(e,"Channel",function(){return l}),n.d(e,"Socket",function(){return f});var c="join",a="leave",s="message",u=function(){return(new Date).getTime()},l=function(){function t(e,n){o(this,t),this.topic=e,this.socket=n,this.onMessageHandlers=[]}return r(t,[{key:"join",value:function(){this.socket.ws.send(JSON.stringify({event:c,topic:this.topic}))}},{key:"leave",value:function(){this.socket.ws.send(JSON.stringify({event:a,topic:this.topic}))}},{key:"handleMessage",value:function(t){this.onMessageHandlers.forEach(function(e){e.subject===t.subject&&e.callback(t.payload)})}},{key:"on",value:function(t,e){this.onMessageHandlers.push({subject:t,callback:e})}},{key:"push",value:function(t,e){this.socket.ws.send(JSON.stringify({event:s,topic:this.topic,subject:t,payload:e}))}}]),t}(),f=function(){function t(e){o(this,t),this.endpoint=e,this.ws=null,this.channels=[],this.lastPing=u(),this.reconnectTries=0,this.attemptReconnect=!0}return r(t,[{key:"_connectionIsStale",value:function(){return t=this.lastPing,(u()-t)/1e3>100;var t}},{key:"_reconnect",value:function(){var t=this;clearTimeout(this.reconnectTimeout),this.reconnectTimeout=setTimeout(function(){t.reconnectTries++,t.connect(t.params),t._reconnect()},this._reconnectInterval())}},{key:"_reconnectInterval",value:function(){return[1e3,2e3,5e3,1e4][this.reconnectTries]||1e4}},{key:"_poll",value:function(){var t=this;this.pollingTimeout=setTimeout(function(){t._connectionIsStale()?t._reconnect():t._poll()},1e4)}},{key:"_startPolling",value:function(){clearTimeout(this.pollingTimeout),this._poll()}},{key:"_handlePing",value:function(){this.lastPing=u()}},{key:"_reset",value:function(){clearTimeout(this.reconnectTimeout),this.reconnectTries=0,this.attemptReconnect=!0,this._startPolling()}},{key:"connect",value:function(t){var e=this;this.params=t;var n={location:window.location.hostname,port:window.location.port,protocol:"https:"===window.location.protocol?"wss:":"ws:"};return t&&Object.assign(n,t),n.port&&(n.location+=":".concat(n.port)),new Promise(function(t,o){e.ws=new WebSocket("".concat(n.protocol,"//").concat(n.location).concat(e.endpoint)),e.ws.onmessage=function(t){e.handleMessage(t)},e.ws.onclose=function(){e.attemptReconnect&&e._reconnect()},e.ws.onopen=function(){e._reset(),t()}})}},{key:"disconnect",value:function(){this.attemptReconnect=!1,clearTimeout(this.pollingTimeout),clearTimeout(this.reconnectTimeout),this.ws.close()}},{key:"channel",value:function(t){var e=new l(t,this);return this.channels.push(e),e}},{key:"handleMessage",value:function(t){if("ping"===t.data)return this._handlePing();var e=JSON.parse(t.data);this.channels.forEach(function(t){t.topic===e.topic&&t.handleMessage(e)})}}]),t}();e.default={Channel:l,Socket:f},document.addEventListener("DOMContentLoaded",function(){var t,e=document.querySelectorAll("a[data-method='delete']");for(t=0;t<e.length;t++)e[t].addEventListener("click",function(t){t.preventDefault();var e=t.target.getAttribute("data-confirm")||"Are you sure?";if(confirm(e)){var n=document.createElement("form"),o=document.createElement("input");n.setAttribute("action",t.target.getAttribute("href")),n.setAttribute("method","POST"),o.setAttribute("type","hidden"),o.setAttribute("name","_method"),o.setAttribute("value","DELETE"),n.appendChild(o),document.body.appendChild(n),n.submit()}return!1})}),Date.prototype.toGranite||function(){function t(t){return t<10?"0"+t:t}Date.prototype.toGranite=function(){return this.getUTCFullYear()+"-"+t(this.getUTCMonth()+1)+"-"+t(this.getUTCDate())+" "+t(this.getUTCHours())+":"+t(this.getUTCMinutes())+":"+t(this.getUTCSeconds())}}()}]);<commit_msg>Updated minified js file amber.min.js (#1162)<commit_after>const EVENTS={join:"join",leave:"leave",message:"message"},STALE_CONNECTION_THRESHOLD_SECONDS=100,SOCKET_POLLING_RATE=1e4;let now=()=>(new Date).getTime(),secondsSince=t=>(now()-t)/1e3;export class Channel{constructor(t,e){this.topic=t,this.socket=e,this.onMessageHandlers=[]}join(){this.socket.ws.send(JSON.stringify({event:EVENTS.join,topic:this.topic}))}leave(){this.socket.ws.send(JSON.stringify({event:EVENTS.leave,topic:this.topic}))}handleMessage(t){this.onMessageHandlers.forEach(e=>{e.subject===t.subject&&e.callback(t.payload)})}on(t,e){this.onMessageHandlers.push({subject:t,callback:e})}push(t,e){this.socket.ws.send(JSON.stringify({event:EVENTS.message,topic:this.topic,subject:t,payload:e}))}}export class Socket{constructor(t){this.endpoint=t,this.ws=null,this.channels=[],this.lastPing=now(),this.reconnectTries=0,this.attemptReconnect=!0}_connectionIsStale(){return secondsSince(this.lastPing)>STALE_CONNECTION_THRESHOLD_SECONDS}_reconnect(){clearTimeout(this.reconnectTimeout),this.reconnectTimeout=setTimeout(()=>{this.reconnectTries++,this.connect(this.params),this._reconnect()},this._reconnectInterval())}_reconnectInterval(){return[1e3,2e3,5e3,1e4][this.reconnectTries]||1e4}_poll(){this.pollingTimeout=setTimeout(()=>{this._connectionIsStale()?this._reconnect():this._poll()},SOCKET_POLLING_RATE)}_startPolling(){clearTimeout(this.pollingTimeout),this._poll()}_handlePing(){this.lastPing=now()}_reset(){clearTimeout(this.reconnectTimeout),this.reconnectTries=0,this.attemptReconnect=!0,this._startPolling()}connect(t){this.params=t;let e={location:window.location.hostname,port:window.location.port,protocol:"https:"===window.location.protocol?"wss:":"ws:"};return t&&Object.assign(e,t),e.port&&(e.location+=`:${e.port}`),new Promise((t,n)=>{this.ws=new WebSocket(`${e.protocol}//${e.location}${this.endpoint}`),this.ws.onmessage=(t=>{this.handleMessage(t)}),this.ws.onclose=(()=>{this.attemptReconnect&&this._reconnect()}),this.ws.onopen=(()=>{this._reset(),t()})})}disconnect(){this.attemptReconnect=!1,clearTimeout(this.pollingTimeout),clearTimeout(this.reconnectTimeout),this.ws.close()}channel(t){let e=new Channel(t,this);return this.channels.push(e),e}handleMessage(t){if("ping"===t.data)return this._handlePing();let e=JSON.parse(t.data);this.channels.forEach(t=>{t.topic===e.topic&&t.handleMessage(e)})}}export default{Channel:Channel,Socket:Socket};document.addEventListener("DOMContentLoaded",()=>{let t=document.querySelectorAll("a[data-method='delete']");for(let e=0;e<t.length;e++)t[e].addEventListener("click",t=>{t.preventDefault();let e=t.target.getAttribute("data-confirm")||"Are you sure?";if(confirm(e)){let e=document.createElement("form"),n=document.createElement("input");e.setAttribute("action",t.target.getAttribute("href")),e.setAttribute("method","POST"),n.setAttribute("type","hidden"),n.setAttribute("name","_method"),n.setAttribute("value","DELETE"),e.appendChild(n),document.body.appendChild(e),e.submit()}return!1})}),Date.prototype.toGranite||function(){function t(t){return t<10?"0"+t:t}Date.prototype.toGranite=function(){return this.getUTCFullYear()+"-"+t(this.getUTCMonth()+1)+"-"+t(this.getUTCDate())+" "+t(this.getUTCHours())+":"+t(this.getUTCMinutes())+":"+t(this.getUTCSeconds())}}();
<|endoftext|>