CodeFest 2019. Валерия Зелёная (HTML Academy) — Как технологии помогают учить людей

16b6c87229eaf58768d25ed7b2bbbf52?s=47 CodeFest
April 06, 2019

CodeFest 2019. Валерия Зелёная (HTML Academy) — Как технологии помогают учить людей

Интерактивные онлайн-курсы дают возможность учиться разработке в любое время и в любом месте. Но как пользователю узнать, что его решение правильное, и он действительно разобрался, как работают события и замыкания?

Расскажу, зачем нам Puppeteer и AST, какие технологии помогают давать обратную связь пользователям, через какие проблемы мы пробирались, чтобы прийти к тому продукту, который есть сейчас.

16b6c87229eaf58768d25ed7b2bbbf52?s=128

CodeFest

April 06, 2019
Tweet

Transcript

  1. Как технологии помогают учить людей

  2. 13

  3. 13 — У нас креативная команда,
 будет весело, —
 говорили

    они
  4. Интерфейс задания. Редактор 4

  5. Интерфейс задания. Мини-браузер 5

  6. Интерфейс задания. Консоль 6

  7. Интерфейс задания. Задачи 7

  8. 1. Консоль

  9. Как запустить код студента? 9

  10. Как запустить код студента? 10 !"

  11. Пользователь может сломать интерфейс 11

  12. Пользователь может сломать интерфейс 12

  13. Запуск кода – Песочница — айфрейм, скрытый на странице –

    Нодовский пакет vm создаёт айфреймы 13
  14. Запуск кода – Песочница — айфрейм, скрытый на странице –

    Нодовский пакет vm создаёт айфреймы – Контекст — способ vm настроить глобальный объект window для айфрейма: – Переопределение дефолтных методов (например, console.log ) – Определение кастомных методов (keks.ask, keks.score) 14
  15. Запуск кода – Песочница — айфрейм, скрытый на странице –

    Нодовский пакет vm создаёт айфреймы – Контекст — способ vm настроить глобальный объект window для айфрейма: – Переопределение дефолтных методов (например, console.log ) – Определение кастомных методов (keks.ask, keks.score) – Ловим вызов методов и выводим в нашу консоль 15
  16. Создание песочницы 16 !// Определяем наши методы
 const sandbox =

    vm.createContext({
 console: {
 log: (message) => {
 myConsole.appendChild(message);
 }
 }
 });
 !// Запускаем код юзера в контексте песочницы
 const code = 'console.log(`Привет!`)';
 vm.runInContext(code, sandbox);
  17. Внутри Webpack 17 !// 1.Создаём iframe, прячем и добавляем в

    документ var iframe = document.createElement('iframe'); if (!iframe.style) iframe.style = {}; iframe.style.display = 'none'; document.body.appendChild(iframe);
  18. Внутри Webpack 18 !// 2. Записываем/переопределяем свойства window в iframe

    var win = iframe.contentWindow; 
 forEach(Object.keys(context), function (key) { win[key] = context[key]; });
  19. Внутри Webpack 19 !// 3. Запускаем код в контексте iframe


    var res = win.eval.call(win, this.code);
 !// 4. Удаляем iframe
 document.body.removeChild(iframe);
  20. Как выводится код 20

  21. Как работают кастомные методы 21

  22. 2. Кратко про мини-браузер

  23. Как отобразить код студента? 23

  24. Как отобразить код студента? 24 !"

  25. Как отобразить код студента? 25

  26. Валидатор 26

  27. 3. Проверки

  28. Проверки – Сравнение DOM-деревьев – Нормализация – Сравнение по AST

    – Сравнение по скриншотам 13
  29. Сравнение DOM-деревьев 29

  30. Как выглядит задание 13

  31. Браузер преобразовывает свойства 13

  32. Браузер преобразовывает свойства 13

  33. Браузер преобразовывает свойства 13

  34. Как происходит проверка 13 <div class="land"> <div>Газон!</div> <div>Вода!</div> <div>Скалы!</div> !</div>

  35. Как происходит проверка 13 <div class="land"> <div>Газон!</div> <div>Вода!</div> <div>Скалы!</div> !</div>

    display: flex $% .land div div div
  36. Как происходит проверка 13 <div class="land"> <div>Газон!</div> <div>Вода!</div> <div>Скалы!</div> !</div>

    display: flex $% display: grid .land div div div .land div div div
  37. Как происходит проверка 13 <div class="land"> <div>Газон!</div> <div>Вода!</div> <div>Скалы!</div> !</div>

    display: flex $% display: grid .land div div div .land div div div .land .land
  38. Как проверка выглядит в коде 38 // Задаём стили в

    эталоне
 dom.changeEtalon(function () {
 this.css(function () {
 this.append('.land { display: grid }');
 this.append('.land { grid-template-columns: 100px 100px 10 });
 });
 // Сравниваем стили в документе студента с эталоном
 return dom.node('.land').hasSame(
 '{display,grid-template-columns}'
 );
  39. Как выглядит задание 13

  40. Сравнение по AST 40

  41. Как выглядит задание 13

  42. Как выглядит AST 13 for (var i = 1; i

    <= 10; i++) { }
  43. Как выглядит AST 13 for (
 var i = 1;


    i <= 10;
 i++
 ) { }
  44. Как выглядит AST 13 for for (
 var i =

    1;
 i <= 10;
 i++
 ) { }
  45. Как выглядит AST 13 for var 1 i for (


    var i = 1;
 i <= 10;
 i++
 ) { }
  46. Как выглядит AST 13 for var 10 <= i 1

    i for (
 var i = 1;
 i <= 10;
 i++
 ) { }
  47. Как выглядит AST 13 for var 10 i ++ <=

    i 1 i for (
 var i = 1;
 i <= 10;
 i++
 ) { }
  48. Как выглядит AST 13 for var 10 i {} ++

    <= i 1 i for (
 var i = 1;
 i <= 10;
 i++
 ) { }
  49. Как выглядит проверка 13 for var 10 i {} ++

    <= i 1 i for (
 var i = 1;
 i <= 10;
 i++
 ) { }
  50. Как выглядит проверка 13 for var 10 i {} ++

    <= i 1 i for (
 var i = 1;
 i <= 10;
 i++
 ) { } 10 <= i 10
  51. Как проверка выглядит в коде 13 // Задаём шаблон для

    проверки AST
 goal('for.i').code(
 '"#builtin.anything"; for (var i = 1; "#f.cond"; "#f.inc") { ) .fragment('f.cond').code('i <= 10', '10 >= i', 'i < 11', '11 .fragment('f.inc').code('i++', '++i', 'i += 1', 'i = i + 1',
  52. Путь кода 13 Строка AST Ищем узлы Замена vm eval

    Строка
  53. Замена кода в испытаниях 13

  54. Как проверка выглядит в коде 13 // Переопределяем значения переменных

    в коде пользователя
 this.initializeVariables({
 encodedMessage: [12, 53, 57, 58, 38, 66, 44, 48, 52, 45, 38, });
 
 this.assertHiddenEquals({
 decodedMessage: 'Лучше котлета в зубах, чем синица в небе.'
 });
  55. Замена кода в испытаниях 13

  56. Сравнение скриншотами 56

  57. Как выглядит задание 13

  58. Как выглядит тестирование .land { grid-template-areas: "w w l l"

    "w w l l" "g g l l" "r r r r"; } $%
  59. Как выглядит тестирование .land { grid-template-areas: "w w l l"

    "w w l l" "g g l l" "r r r r"; } .land { grid-template-areas: "w w l l" "w w l l" "g g l l" "r r l l"; } $%
  60. Как выглядит тестирование .land { grid-template-areas: "w w l l"

    "w w l l" "g g l l" "r r r r"; } .land { grid-template-areas: "w w l l" "w w l l" "g g l l" "r r l l"; } $% Сервер
  61. Как выглядит тестирование .land { grid-template-areas: "w w l l"

    "w w l l" "g g l l" "r r r r"; } .land { grid-template-areas: "w w l l" "w w l l" "g g l l" "r r l l"; } $% Сервер
  62. Как выглядит задание 13

  63. Как выглядит задание 13

  64. Как выглядит задание 13

  65. Phantom JS – Webkit – Редко обновлялся – Отставал от

    текущих версий браузеров – Перестал поддерживаться 13
  66. Phantom JS – Webkit – Редко обновлялся – Отставал от

    текущих версий браузеров – Перестал поддерживаться 13 Puppeteer – Chromium – Часто обновляется – Соответствует текущим браузерам – Развивается
  67. Нормализация 67

  68. Как выглядит задание 13

  69. Как выглядит проверка transition <button class="btn" type="button">
 +
 !</button> $%

    <button class="btn" type="button">
 +
 !</button>
  70. iframe <button class="btn" type="button">
 +
 !</button> $% <button class="btn" type="button">


    +
 !</button> Как выглядит проверка transition
  71. iframe <button class="btn" type="button">
 +
 !</button> $% <button class="btn" type="button">


    +
 !</button> Как выглядит проверка transition
  72. iframe iframe <button class="btn" type="button">
 +
 !</button> $% <button class="btn"

    type="button">
 +
 !</button> Как выглядит проверка transition
  73. iframe iframe <button class="btn" type="button">
 +
 !</button> $% <button class="btn"

    type="button">
 +
 !</button> Как выглядит проверка transition
  74. iframe iframe <button class="btn" type="button">
 +
 !</button> $% <button class="btn"

    type="button">
 +
 !</button> Как выглядит проверка transition
  75. Как это выглядит в коде 13 !// Задаём финальное состояние

    эталону
 dom.changeEtalon(function () { this.html(function () {
 this
 .find('<button class="btn" type="button">')
 .replace('<button class="btn btn-active" type="button">' });
 this.css(function () {
 this.append('.btn-active { color: #ffffff; transform: rota });
 });
  76. Как это выглядит в коде 13 !// Обнуляем время трансформации,

    добавляем класс кнопке
 dom.changeUserFrame(function () {
 this.css(function () {
 this.append('.btn {transition-duration: 0s;}');
 this.querySelector('.btn').classList.add('btn-active');
 });
 });
 return dom.userFrame() !// Сравниваем два узла
 .node('.btn-active')
 .hasSame('{color, transform}');
  77. Как выглядит задание 13

  78. Как выглядит задание 13

  79. Как выглядит задание 13

  80. 4. Редактор

  81. Как показать правильный ответ 81

  82. Как показать правильный ответ 82

  83. Как это выглядит в коде 83 this.setAnswers([{ !// Номер цели

    и вкладка редактора
 goal: 1, editor: 'js', data: function () {
 this
 !// Текст подсказки
 .tooltip('Заменяем сравнение на строгое') .at(3, 13) !// Позиция курсора .add('='); !// Что делаем в коде
 }
 }]);
  84. Как выглядит показ ответа 84

  85. Как выглядит показ ответа 85

  86. Как выглядит показ ответа 86

  87. Как выглядит показ ответа 87

  88. Если нет типовых решений 88

  89. Если нет типовых решений, нужно подходить к задачам творчески 89

  90. Если нет типовых решений, нужно подходить к задачам творчески или

    искать ответы в других областях 90
  91. Спасибо! 13

  92. 13 iamlerun greenlera