Вопрос: а не поздно ли мы всё это делаем? ЕГЭ-то уже прошло.

Ответ: нет, не поздно. Банк заданий по математике относительно стабилен, можно с высокой долей уверенности ожидать, что в следующем году часть В или не изменится, или просто поменяет порядок заданий (как между 2013 и 2014).
По уточнённым данным, готовится деление на профильный и базовый уровень. Тренажёр по проекту профильному уровню доступен через меню "Предметы". Обновление от 17 июля 2015 года: изменения, конечно, были, некоторые задания усложнились, но в следующем году вряд ли кто-то будет разрабатывать банк заданий с нуля. Так что верной дорогой идём, товарищи!

Инструкция

Примечание: c 20 декабря 2014 года использование window.vopr и т.п. считается устаревшим способом. Рекомендуется использование только NApi и NLib (разработку которых ведёт Сергей Наумов). Тем не менее, мы заботимся об обратной совместимости, и ранее написанные шаблоны продолжают работать.
  1. Переходим по адресу оболочки отладки (откроется в новом окне)
  2. В поле "Ввести программу" уже должна быть вот такая заготовка:
    (function(){
    NAinfo.requireApiVersion(0, 0);
    
    })();
    
    Если там по каким-то причинам её нет, просто скопируйте отсюда.
  3. Теперь попробуем выполнить какую-нибудь программу. В поле "Ввести программу" (кстати, его размер можно изменить, потянув за нижний правый угол!) введите, например:
    (function(){
    NAinfo.requireApiVersion(0, 0);
    alert('Привет!');
    })();
    
    и нажмите кнопку "Составить задание по программе" под полем ввода. Задание как таковое не составится, но браузер выдаст сообщение "Привет!". Грабли: если выскочило сообщение "Нужно указать путь к загружаемому файлу!", значит, Вы нажали не ту кнопку. Надо нажать ту, которая под, а не ту, которая над!
  4. Дальнейшие действия проведём на примере прототипа №77339 Открытого банка заданий (далее для краткости - Обзад)
  5. Сначала вернёмся к заготовке:
    (function(){
    NAinfo.requireApiVersion(0, 0);
    
    })();
    
    Это заголовок замыкания и проверка версии NApi, они нам в рамках этой инструкции неинтересны. Набирать текст нашего шаблона мы будем между второй и четвёртой строчками:
    (function(){'use strict';
    NAinfo.requireApiVersion(0, 0);
    /*Вот здесь!*/
    })();
    
  6. То, что окружено парами символов /* и */ - комментарий, на комментарии компьютер не обращает никакого внимания. Совет: Нажмите кнопку "Включить редактор АСЕ", чтобы активировать подсветку синтаксиса и приверку некоторых ошибок на лету (значки появляются слева). Можно выставить размер шрифта и количество строк.
  7. После этого и каждого из следующих шагов уже можно нажимать кнопку "Составить задание по программе" - будет виден результат.
    Итак, вставим в нашу заготовку текст вопроса:
    (function(){'use strict';
    NAinfo.requireApiVersion(0, 0);
    
    NAtask.setTask({
    text: 'В среднем за день во время конференции расходуется 70 пакетиков чая. Конференция длится 4 дня. В пачке чая 100 пакетиков. Какого наименьшего количества пачек чая хватит на все дни конференции?',
    });
    })();
    
    Выполняем. Появилась задача, но ответ на неё даже нельзя проверить.
  8. Теперь добавим ответ:
    (function(){'use strict';
    NAinfo.requireApiVersion(0, 0);
    
    NAtask.setTask({
    text: 'В среднем за день во время конференции расходуется 70 пакетиков чая. Конференция длится 4 дня. В пачке чая 100 пакетиков. Какого наименьшего количества пачек чая хватит на все дни конференции?',
    answers: 3,
    });
    })();
    
    Уже лучше: после того, как задание составлено, в поле "Ответ" можно ввести ответ (Кэп!), и тренажёр проверит его правильность. Потренируйтесь вводить ответ, если нужно :-)
  9. Строка с текстом вопроса не влезает в экран :-( Давайте разобьём её на несколько строк. На следующих шагах это нам прибавит удобства.
    (function(){'use strict';
    NAinfo.requireApiVersion(0, 0);
    
    NAtask.setTask({
    text: 'В среднем за день во время конференции расходуется 70 пакетиков чая. '+
    	'Конференция длится 4 дня. В пачке чая 100 пакетиков. '+
    	'Какого наименьшего количества пачек чая хватит на все дни конференции?',
    answers: 3,
    });
    })();
    
    Обратите внимание: знак + должен находиться на верхней строке (подобно переносу в словах), а слева перед каждой перенесённой частью строки делается отступ (например, 4 или 8 пробелов, но лучше - таб). Для программиста расставить отступы - это как помыть руки перед едой.
  10. Наш шаблон генерирует всё время одинаковые задания. Хотелось бы, чтобы что-то всё-таки менялось, ведь именно в этом - одно из ключевых преимуществ "Час ЕГЭ". Но сначала нам нужно описать, как мы получили ответ:
    (function(){'use strict';
    NAinfo.requireApiVersion(0, 0);
    
    NAtask.setTask({
    text: 'В среднем за день во время конференции расходуется 70 пакетиков чая. '+
    	'Конференция длится 4 дня. В пачке чая 100 пакетиков. '+
    	'Какого наименьшего количества пачек чая хватит на все дни конференции?',
    answers: (70*4/100).ceil(),
    });
    })();
    
    
    Запись (число).ceil() сообщает компьютеру, что число нужно округлить в большую сторону. Чтобы округлить число в меньшую сторону, напишите (число).floor() , а чтобы по обычным правилам округления - используйте (число).round()
  11. Теперь давайте внесём в задачу обещанное разнообразие. Начнём с простого: сделаем так, чтобы иногда упоминался чай, а иногда - кофе. Сначала "выкусим" кавчками все упоминания чая:
    (function(){'use strict';
    NAinfo.requireApiVersion(0, 0);
    
    NAtask.setTask({
    text: 'В среднем за день во время конференции расходуется 70 пакетиков '+'чая'+'. '+
    	'Конференция длится 4 дня. В пачке '+'чая'+' 100 пакетиков. '+
    	'Какого наименьшего количества пачек '+'чая'+' хватит на все дни конференции?',
    answers: (70*4/100).ceil(),
    });
    })();
    
    
  12. Теперь введём переменную napitka, в которую положим строку "чая". В Javascript все переменные объявляются с помощью слова var, а типов у переменных нет:
    (function(){'use strict';
    NAinfo.requireApiVersion(0, 0);
    
    var napitka='чая';
    NAtask.setTask({
    text: 'В среднем за день во время конференции расходуется 70 пакетиков '+'чая'+'. '+
    	'Конференция длится 4 дня. В пачке '+'чая'+' 100 пакетиков. '+
    	'Какого наименьшего количества пачек '+'чая'+' хватит на все дни конференции?',
    answers: (70*4/100).ceil(),
    });
    })();
    
    
  13. Заменим теперь "выкушенные" строки 'чая' на переменную napitka:
    (function(){'use strict';
    NAinfo.requireApiVersion(0, 0);
    
    var napitka='чая';
    NAtask.setTask({
    text: 'В среднем за день во время конференции расходуется 70 пакетиков '+napitka+'. '+
    	'Конференция длится 4 дня. В пачке '+napitka+' 100 пакетиков. '+
    	'Какого наименьшего количества пачек '+napitka+' хватит на все дни конференции?',
    answers: (70*4/100).ceil(),
    });
    })();
    
    
    Пока всё осталось как есть. Кофе появится на следующем шаге.
  14. (Отныне комментарии пишем прямо в коде - так принято):
    
    (function(){'use strict';
    NAinfo.requireApiVersion(0, 0);
    //Кстати, если в строке стоит двойная дробь // - то всё, что идёт после этой дроби и до конца строки,
    //превращается в комментарий
    
    var napitka=['чая','кофе'].iz();//Вернёт случайным образом 'чая' или 'кофе'
    
    NAtask.setTask({
    text: 'В среднем за день во время конференции расходуется 70 пакетиков '+napitka+'. '+
    	'Конференция длится 4 дня. В пачке '+napitka+' 100 пакетиков. '+
    	'Какого наименьшего количества пачек '+napitka+' хватит на все дни конференции?',
    answers: (70*4/100).ceil(),
    });
    })();
    
    
    Здесь запись ['чая','кофе'] - это массив строк, а функция iz() случайным образом выбирает элемент из массива. Велосипед: эта функция входит в библиотеку chas-lib и не является стандартной.
  15. Попробуйте несколько раз составить задание. Имейте в виду: генератор случайных чисел "любит пошутить", иногда может пять раз выпасть "чай", на шестой - "кофе" (а вовсе не обязательно они строго чередуются).
  16. Теперь на примере конференции научимся работать с падежами. "Выкусывание" и введение переменной нам уже знакомы, так что смело пишем:
    (function(){'use strict';
    NAinfo.requireApiVersion(0, 0);
    
    var napitka=['чая','кофе'].iz();//Вернёт случайным образом 'чая' или 'кофе'
    var meropr=['конференция','мероприятие','слёт'].iz();
    
    NAtask.setTask({
    text: 'В среднем за день во время конференции расходуется 70 пакетиков '+napitka+'. '+
    	'Конференция длится 4 дня. В пачке '+napitka+' 100 пакетиков. '+
    	'Какого наименьшего количества пачек '+napitka+' хватит на все дни конференции?',
    answers: (70*4/100).ceil(),
    });
    })();
    
    
  17. Но вот незадача - конференция упоминается в разных падежах, просто строку использовать нельзя! У нас в проекте за склонение существительных отвечает специальный модуль - лексический. В его создании, кстати, достаточно активно участвовала доброволец Любовь Ерышова. Как правило, там, где этот модуль вызывается, упоминается буквосочетание lx. Превратим переменную meropr в существительное, падежи которого составит лексический модуль:
    (function(){'use strict';
    NAinfo.requireApiVersion(0, 0);
    
    var napitka=['чая','кофе'].iz();//Вернёт случайным образом 'чая' или 'кофе'
    var meropr=['конференция','мероприятие','слёт'].iz();
    meropr=sklonlxkand(meropr);
    
    NAtask.setTask({
    text: 'В среднем за день во время конференции расходуется 70 пакетиков '+napitka+'. '+
    	'Конференция длится 4 дня. В пачке '+napitka+' 100 пакетиков. '+
    	'Какого наименьшего количества пачек '+napitka+' хватит на все дни конференции?',
    answers: (70*4/100).ceil(),
    });
    })();
    
    
  18. Обычно пишут короче:
    (function(){'use strict';
    NAinfo.requireApiVersion(0, 0);
    
    var napitka=['чая','кофе'].iz();//Вернёт случайным образом 'чая' или 'кофе'
    var meropr=sklonlxkand(['конференция','мероприятие','слёт'].iz());
    
    NAtask.setTask({
    text: 'В среднем за день во время конференции расходуется 70 пакетиков '+napitka+'. '+
    	'Конференция длится 4 дня. В пачке '+napitka+' 100 пакетиков. '+
    	'Какого наименьшего количества пачек '+napitka+' хватит на все дни конференции?',
    answers: (70*4/100).ceil(),
    });
    })();
    
    
  19. Теперь включаем переменную meropr в вопрос:
    (function(){'use strict';
    NAinfo.requireApiVersion(0, 0);
    
    var napitka=['чая','кофе'].iz();//Вернёт случайным образом 'чая' или 'кофе'
    var meropr=sklonlxkand(['конференция','мероприятие','слёт'].iz());
    
    NAtask.setTask({
    text: 'В среднем за день во время '+meropr.re+' расходуется 70 пакетиков '+napitka+'. '+
    	meropr.ie+' длится 4 дня. В пачке '+napitka+' 100 пакетиков. '+
    	'Какого наименьшего количества пачек '+napitka+' хватит на все дни '+meropr.re+'?',
    answers: (70*4/100).ceil(),
    });
    })();
    
    
    Первая буква после точки - падеж, вторая - число (транслитом). Т. е. meropr.re - это родительный падеж единственного числа слова, содержащегося в переменной meropr, и предварительно подготовленного с помощью sklonlxkand (это важно!).
  20. Внимательный доброволец заметит, что наименование мероприятия во втором предложении начинается с маленькой буквы. Это не дело! Исправим с помощью функции toZagl()
    (function(){'use strict';
    NAinfo.requireApiVersion(0, 0);
    
    var napitka=['чая','кофе'].iz();//Вернёт случайным образом 'чая' или 'кофе'
    var meropr=sklonlxkand(['конференция','мероприятие','слёт'].iz());
    
    NAtask.setTask({
    text: 'В среднем за день во время '+meropr.re+' расходуется 70 пакетиков '+napitka+'. '+
    	meropr.ie.toZagl()+' длится 4 дня. В пачке '+napitka+' 100 пакетиков. '+
    	'Какого наименьшего количества пачек '+napitka+' хватит на все дни '+meropr.re+'?',
    answers: (70*4/100).ceil(),
    });
    })();
    
    
    Обратите внимание: мы последовательно применили взятие именительного падежа и "вставку" заглавной буквы: meropr.ie.toZagl() Такой код на жаргоне называют "лапшой". Порядок операций важен!
  21. Самостоятельно разнообразьте, например, пачки коробками и упаковками. Вообще, разнооборазие слов, не относящихся к решению задачи (будем называть их антуражем) и данных задачи целиком и полностью лежит на совести человека, который пишет шаблон. Но чем разнообразнее - тем обычно лучше, хотя всё хорошо в меру. Разнообразие, в частности, усложняет гугление учащимися условий задач.
  22. Теперь пора заняться числами! Всё-таки задача по математике, а не по русскому языку ;-) "Выкусывание" чисел нужно производить вместе с "привязанными" к ним существительными (для филологов: да знаю я термин "синтаксически неразрывное словосочетание", но так проще и понятнее!). Это связано с тем, что существительное изменяется вместе с числительным: один гриб, два гриба, пять грибов. Итак, будем варьировать количество дней. Сначала просто "выкусываем":
    (function(){'use strict';
    NAinfo.requireApiVersion(0, 0);
    
    var napitka=['чая','кофе'].iz();//Вернёт случайным образом 'чая' или 'кофе'
    var meropr=sklonlxkand(['конференция','мероприятие','слёт'].iz());
    
    NAtask.setTask({
    text: 'В среднем за день во время '+meropr.re+' расходуется 70 пакетиков '+napitka+'. '+
    	meropr.ie.toZagl()+' длится '+'4 дня'+'. В пачке '+napitka+' 100 пакетиков. '+
    	'Какого наименьшего количества пачек '+napitka+' хватит на все дни '+meropr.re+'?',
    answers: (70*4/100).ceil(),
    });
    })();
    
    
  23. Теперь запишем с помощью функции chislitlx(число, существительное):
    (function(){'use strict';
    NAinfo.requireApiVersion(0, 0);
    
    var napitka=['чая','кофе'].iz();//Вернёт случайным образом 'чая' или 'кофе'
    var meropr=sklonlxkand(['конференция','мероприятие','слёт'].iz());
    
    NAtask.setTask({
    text: 'В среднем за день во время '+meropr.re+' расходуется 70 пакетиков '+napitka+'. '+
    	meropr.ie.toZagl()+' длится '+chislitlx(4,'день')+'. В пачке '+napitka+' 100 пакетиков. '+
    	'Какого наименьшего количества пачек '+napitka+' хватит на все дни '+meropr.re+'?',
    answers: (70*4/100).ceil(),
    });
    })();
    
    
  24. Теперь вносим собственно разнообразие. Для этого, как несложно догадаться, нам потребуется переменная. Назовём её dni, присвоим ей значение 4 и везде число 4 заменим на эту переменную (в вопросе и в ответе!)
    (function(){'use strict';
    NAinfo.requireApiVersion(0, 0);
    
    var napitka=['чая','кофе'].iz();//Вернёт случайным образом 'чая' или 'кофе'
    var meropr=sklonlxkand(['конференция','мероприятие','слёт'].iz());
    var dni=4;
    
    NAtask.setTask({
    text: 'В среднем за день во время '+meropr.re+' расходуется 70 пакетиков '+napitka+'. '+
    	meropr.ie.toZagl()+' длится '+chislitlx(dni,'день')+'. В пачке '+napitka+' 100 пакетиков. '+
    	'Какого наименьшего количества пачек '+napitka+' хватит на все дни '+meropr.re+'?',
    answers: (70*dni/100).ceil(),
    });
    })();
    
    
  25. И, наконец, сгенерируем случайное количество дней от 2 до 10 с помощью функции sluchch(от, до):
    (function(){'use strict';
    NAinfo.requireApiVersion(0, 0);
    
    var napitka=['чая','кофе'].iz();//Вернёт случайным образом 'чая' или 'кофе'
    var meropr=sklonlxkand(['конференция','мероприятие','слёт'].iz());
    var dni=sluchch(2,10);
    
    NAtask.setTask({
    text: 'В среднем за день во время '+meropr.re+' расходуется 70 пакетиков '+napitka+'. '+
    	meropr.ie.toZagl()+' длится '+chislitlx(dni,'день')+'. В пачке '+napitka+' 100 пакетиков. '+
    	'Какого наименьшего количества пачек '+napitka+' хватит на все дни '+meropr.re+'?',
    answers: (70*dni/100).ceil(),
    });
    })();
    
    
    Помните: выбор диапазона случайных значений доверяется автору шаблона! Сверяйтесь с Обзадом ;-)
  26. Проделаем теперь то же самое с пакетиками:
    (function(){'use strict';
    NAinfo.requireApiVersion(0, 0);
    
    var napitka=['чая','кофе'].iz();//Вернёт случайным образом 'чая' или 'кофе'
    var meropr=sklonlxkand(['конференция','мероприятие','слёт'].iz());
    var dni=sluchch(2,10);
    var pak=sluchch(50,200);
    
    NAtask.setTask({
    text: 'В среднем за день во время '+meropr.re+' расходуется 70 пакетиков '+napitka+'. '+
    	meropr.ie.toZagl()+' длится '+chislitlx(dni,'день')+'. В пачке '+napitka+' '+chislitlx(pak,'пакетик')+'. '+
    	'Какого наименьшего количества пачек '+napitka+' хватит на все дни '+meropr.re+'?',
    answers: (70*dni/pak).ceil(),
    });
    })();
    
    
  27. И всё бы хорошо, но вряд ли какой-нибудь производитель будет класть в пачку, например, 73 пакетика. Укажем функции sluchch шаг случайного числа (пользуясь случаем, говорю Алине Широковой спасибо за обнаруженный баг):
    (function(){'use strict';
    NAinfo.requireApiVersion(0, 0);
    
    var napitka=['чая','кофе'].iz();//Вернёт случайным образом 'чая' или 'кофе'
    var meropr=sklonlxkand(['конференция','мероприятие','слёт'].iz());
    var dni=sluchch(2,10);
    var pak=sluchch(50,200,10);
    
    NAtask.setTask({
    text: 'В среднем за день во время '+meropr.re+' расходуется 70 пакетиков '+napitka+'. '+
    	meropr.ie.toZagl()+' длится '+chislitlx(dni,'день')+'. В пачке '+napitka+' '+chislitlx(pak,'пакетик')+'. '+
    	'Какого наименьшего количества пачек '+napitka+' хватит на все дни '+meropr.re+'?',
    answers: (70*dni/pak).ceil(),
    });
    })();
    
  28. Самостоятельно проделайте то же самое с количеством пакетиков, расходуемых в день.
  29. С учётом предыдущего задания для самостоятельного решения должно получиться нечто вроде этого:
    (function(){'use strict';
    NAinfo.requireApiVersion(0, 0);
    
    var napitka=['чая','кофе'].iz();//Вернёт случайным образом 'чая' или 'кофе'
    var meropr=sklonlxkand(['конференция','мероприятие','слёт'].iz());
    var up=sklonlxkand(['пачка','коробка','упаковка'].iz())
    var dni=sluchch(2,10);
    var pak=sluchch(50,200,10);
    var rash=sluchch(20,100);
    
    NAtask.setTask({
    text: 'В среднем за день во время '+meropr.re+' расходуется '+chislitlx(rash,'пакетик')+' '+napitka+'. '+
    	meropr.ie.toZagl()+' длится '+chislitlx(dni,'день')+'. В '+up.pe+' '+napitka+' '+chislitlx(pak,'пакетик')+'. '+
    	'Какого наименьшего количества '+up.rm+' '+napitka+' хватит на все дни '+meropr.re+'?',
    answers: (rash*dni/pak).ceil(),
    });
    })();
    
    
  30. Теперь указываем источник шаблона и автора:
    (function(){'use strict';
    NAinfo.requireApiVersion(0, 0);
    
    var napitka=['чая','кофе'].iz();//Вернёт случайным образом 'чая' или 'кофе'
    var meropr=sklonlxkand(['конференция','мероприятие','слёт'].iz());
    var up=sklonlxkand(['пачка','коробка','упаковка'].iz())
    var dni=sluchch(2,10);
    var pak=sluchch(50,200,10);
    var rash=sluchch(20,100);
    
    NAtask.setTask({
    text: 'В среднем за день во время '+meropr.re+' расходуется '+chislitlx(rash,'пакетик')+' '+napitka+'. '+
    	meropr.ie.toZagl()+' длится '+chislitlx(dni,'день')+'. В '+up.pe+' '+napitka+' '+chislitlx(pak,'пакетик')+'. '+
    	'Какого наименьшего количества '+up.rm+' '+napitka+' хватит на все дни '+meropr.re+'?',
    answers: (rash*dni/pak).ceil(),
    });
    })();
    //Обзад 77339
    //NickKolok
    
    
    Можно подписаться реальным именем, можно ником.
  31. Нажимаем кнопку "Отправить на pastebin.ru" (предварительно можно ввести имя и название - по желанию). Откроется новая вкладка со страницей, содержащей Ваш код. Ссылку на полученную страницу из адресной строки браузера отправляем мне.
  32. Спасибо!

Приложение 1: работаем с $\TeX$

$\TeX$ - это язык записи математических формул. (Если быть точным, то не только формул, но нам нужны именно они.) В "Час ЕГЭ" для поддержки $\TeX$ используется внешняя библиотека MathJax. Из-за особенностей используемых технологий при работе с $\TeX$ нужно помнить следующее: