// 1. makeProfileTimer
// Напишите функцию makeProfileTimer, которая служит для замера времени выполнения другого кода и работает следующим образом:

// {
//     function makeProfileTimer () {
//         let t0 = performance.now();
//         return function () {
//             let t1 = performance.now();
//             return `Время работы этого alert ${t1-t0}`
//         }
//     }
//
//     let timer = makeProfileTimer()
//     alert('Замеряем время работы этого alert');
//     alert(timer())
// }

//2. makeSaver
// Напишите функцию makeSaver, которая:

//Таким образом makeSaver решает две задачи:
//
//     Навсегда сохраняет результат функции. Это актуально, например, для Math.random.
//     Действует лениво, то есть вызывает Math.random только тогда, когда результат действительно нужен. Если же по
//     каким-то причинам значение не понадобится, то Math.random даже не будет вызван
//
// function makeSaver(fn) {
//     let result;
//     let resultSave = false;
//     return function () {
//         if (!resultSave) {
//             result = fn();
//             resultSave = true;
//         }
//         return result;
//     }
// }
//
// var saver = makeSaver(Math.random);
// var value1 = saver();
// var value2 = saver();
// value1 === value2;
//
// var saver2 = makeSaver(() => console.log('saved function called') || [null, undefined, false, '', 0, Math.random()][Math.ceil(Math.random() * 6)]);
// var value3 = saver2();
// var value4 = saver2();
//
// value3 === value4;
//
// let namePrompt = prompt.bind(window, 'Как тебя зовут?');
// let nameSaver = makeSaver(namePrompt);
// alert(`Привет! Prompt еще не было!`);
// alert(`Привет ${nameSaver()}. Только что запустился prompt, первый и последний раз`);
// alert(`Слушай, ${nameSaver()}, го пить пиво. Ведь prompt был только один раз`);



//3. myBind +-
// Изучите встроенную функцию bind, и сделайте свою версию, которая позволит определить "значение по умолчанию" не
// только для первых параметров, но для любых других, например для степени в Math.pow:
// {
//     function myBind (func, place, parametr) {
//         function wrapper () {
//             let args = Object.assign(parametr, arguments);
//             return func.apply(place, args);
//         }
//         return wrapper;
//     }
//
//     let pow5 = myBind(Math.pow, Math, [, 5])
//     console.log(pow5(2))
//
//     let cube = myBind(Math.pow, Math, [, 3]);
//     console.log(cube(3))
//
//     let zeroPrompt = myBind(prompt, window, [undefined, '0'])
//     let someNumber = zeroPrompt("Введите число");
//     alert(someNumber)
//
//     let chessMin = myBind(Math.min, Math, [ 4, 5, 8, 9]);
//     console.log(chessMin(-1,-10,3,15))
//
//     const bindedJoiner = myBind((...params) => params.join(''), null, [ ,'b', , ,'e','f'])
//     console.log(bindedJoiner('a','c','d'))
// }

//4. checkResult
// Напишите декоратор checkResult, который:
//
//     принимает функцию для запуска и проверки результата (оригинал)
//     принимает функцию для проверки результата (валидатор)
//     возвращает обертку, которая запускает оригинал до тех пор, пока оригинал не вернет значение, удовлетворяющее
//     функции-валидатору. В валидатор передается результат оригинальной функции. Если валидатор возвращает true, то
//     обертка возвращает результат оригинальной функции. Если валидатор возвращает что-то другое, то оригинал
//     запускается еще, пока валидатор не вернет true.

function checkResult(original, validator) {
    function wrapper(...params) {
        let result;
        do {
            result = original.apply(this, params);
        } while (!validator(result));
        return result;
    }
    return wrapper;
}
//numberPrompt - это функция, которая будет запускать prompt до тех пор, пока пользователь не введет число
const numberPrompt = checkResult(prompt, x => !isNaN(+x))
let   number       = +numberPrompt("Введите число", "0")  //параметры передаются насквозь в оригинал. Не забудьте передать this, используя call или apply
console.log(number);

//gamePrompt - это функция, которая будет запускать prompt до тех пор, пока пользователь не введет одно из слов 'камень', 'ножницы', 'бумага'
const gamePrompt   = checkResult(prompt, x => ['камень', 'ножницы', 'бумага'].includes(x.toLowerCase()))
const turn         = gamePrompt("Введите что то из списка: 'камень', 'ножницы', 'бумага'")
console.log(turn);

// Используя checkResult сделайте функции, которые:
// randomHigh. Возвращает случайное число в диапазоне от 0.5 до 1*
const randomHigh = checkResult(Math.random, x => x >= 0.5 && x <=1 ? true : false )
console.log(randomHigh())

//alwaysSayYes. Достает пользователя окном confirm пока он не согласится (не нажмет OK)
const alwaysSayYes = checkResult(confirm, x => x)
alwaysSayYes()