Я дауншифтер. Так получилось, что последние три года мы с женой и младшим ребёнком наслаждаемся сельским пейзажем за окном, свежим воздухом и пением птиц. Удобства в доме, оптический интернет от местного провайдера, мощный бесперебойник и нагрянувший ковид неожиданно сделали идею переезда из мегаполиса не такой уж странной.
Пока я увлеченно занимался веб разработкой, где-то на фоне жена периодически жаловалась на проблемы выбора школы для ребёнка. И тут (вдруг) ребёнок подрос и школьный вопрос встал ребром. Ладно, значит, время пришло. Давайте вместе разберёмся, что же все-таки не так с системой образования в бывшей 1/6 части суши, и что мы с вами можем с этим сделать?
Традиционные методы очного обучения я оставлю за рамками этой статьи. Скажу только, что у обычных школ есть как неоспоримые преимущества, так и серьезные недостатки, к которым, кстати, в последнее время добавилась вынужденная самоизоляция. Здесь мы рассмотрим варианты дистанционного и семейного образования, которые, по целому ряду причин, в последнее время привлекают все больше родителей.
Внесу ясность: дистанционное обучение подразумевает занятия в обычной школе с помощью «дистанционных образовательных технологий» (ДОТ), а семейное означает добровольный уход из школы и обучение только силами семьи (по сути, это старый добрый экстернат). Впрочем, в любом случае ребёнка нужно прикрепить к какой-либо из доступных школ, как минимум, для сдачи промежуточных аттестаций.
А теперь немного наблюдений из жизни. С вынужденным переводом на дистанционку детей, уже учившихся в обычной школе, все грустно. Школьники воспринимают этот подарок судьбы как своего рода каникулы, родители не привыкли следить за дисциплиной во время занятий и в результате общая успеваемость неизбежно падает.
С первоклашками, особенно в случае семейной формы, у родителей, пожалуй, появляется шанс поставить ребёнка «на рельсы», используя естественный интерес и эффект новизны. Лично для меня добиться самостоятельности — главная задача. Сидеть и делать с ребёнком домашку я считаю
Ближе к делу. Выбираем государственную школу
Пожалуй, семейное образование мне нравится больше из-за возможности выбрать программу и график обучения. Да и физически посещать школу можно реже. Но выбрать государственную школу, поговорить с директором о прикреплении ребёнка и получить приказ о зачислении в первый класс нужно уже в конце зимы, чтобы в сентябре не было сюрпризов. Хотя, с юридической точки зрения, закон об образовании вроде бы не требует ежегодных аттестаций, «дедлайны», по моему опыту, отлично мотивируют, поэтому пусть будут аттестации. Вряд ли любая школа примет нас с распростертыми объятьями, но найти достойный вариант в ближайшем городе мы сможем, я уверен.
Выбираем учебную программу
Именно выбираем. Пытаться составить программу самостоятельно, не имея профильного образования, не разумно. Хотя существуют государственные образовательные ресурсы, такие как Российская Электронная Школа (РЭШ) и Московская Электронная Школа (МЭШ), которых в теории могло было бы хватить, но… Оба варианта предоставляют планы уроков, видеозаписи, тесты и учебные пособия. Вот чего мне не удалось найти, так это самих учебников, даже по обязательной программе.
И тут нет самого главного: общения. Обучить ребёнка, показывая ему бесконечные видеоролики и заставляя ставить галочки в тестах, не получится. Значит, нужно либо проводить уроки полностью самостоятельно, либо выбрать одну из онлайн школ.
Выбираем онлайн школу
Мы почти вернулись к тому, с чего начали. Дистанционка? Ладно, присмотримся к ней повнимательней. Как вообще можно организовать учебный процесс удаленно? Тут возникает много вопросов, я подниму только ключевые:
* Живое общение. Что предлагают школы? Скайп, в лучшем случае Тимс. Уроки по Скайпу? Серьёзно? Если я не ошибаюсь, на дворе 2020-й. Открыть перед первоклашкой несколько окон с красивыми разноцветными кнопочками и ждать, что он на них не нажмет, а будет пол-дня послушно слушать скучного дядю или тетю? Ни разу таких детей не видел. А вы?
* Домашка. Точнее, как она попадает к учителю на проверку? На самом деле, это действительно сложный вопрос, возможно, даже не решаемый в принципе. Существующие варианты:
- Написать в тетрадке, сфоткать и отправить учителю. Бр-р-р, не хочу заставлять учителей ломать глаза в попытках прочесть мутные фотки с мобильников, сделанные, как правило, по какому-то неписанному закону в темноте.
- Отправить скан. Полумера, в общем случае невозможная из-за отсутствия у родителей нужного оборудования.
- Оцифровать рукописный ввод с помощью дигитайзера или планшета. Так себе вариант, но об этом чуть позже.
- Напечатать текст. В принципе, допустимо, но вот как ребёнок введёт с клавиатуры, например, математическую или химическую формулу? Никак. Плюс, для более продвинутых деток, проблема с плагиатом.
- Выполнить онлайн тест. Это, безусловно, самый популярный вариант. Полагаю, большинство школ, включая РЭШ и МЭШ, ориентируются на него. На практике это означает скорее дрессировку, чем обучение. Дети учатся ставить галочки в правильном месте. За бортом остаются предметы, требующие любой формы творчества, например, сочинения, а также диктанты и непопулярное теперь по неведомой мне причине чистописание. Сюда же можно отнести умение отстаивать своё мнение.
* Оценки. Очевидно, выставленные на уроке и при проверке домашних заданий оценки должны попадать в электронный дневник, доступный родителям. И они туда попадают. Вот только не сразу. Я поинтересовался у старших детей, закончивших один из престижных лицеев златоглавой (по иронии судьбы, с информационным уклоном), почему так? Ответ, честно сказать, меня удивил. Оказывается, учителя записывают оценки на бумажку, а после уроков вбивают их в этот самый электронный дневник на государственном портале. И это в то время, как Теслы Илона Маска бороздят просторы космоса…
Ладно, пора провести небольшое техническое исследование и проверить, может существуют объективные причины такого положения дел?
Давайте определим требования к гипотетической идеальной платформе для обучения. На самом деле, все просто: дети должны оставаться на уроке, сосредоточившись на том, что говорит и показывает учитель, при необходимости отвечая на вопросы и при желании поднимая руку. По сути, нам нужно окно на полный экран с потоком с учительской камеры, презентацией или интерактивной доской. Самый простой способ добиться этого — использовать технологию WebRTC (real-time communications, коммуникации в реальном времени). Эта штука работает в любом более-менее современном браузере, не требует покупки дополнительного оборудования и, к тому же, обеспечивает хорошее качество связи. И да, этот стандарт требует асинхронного программирования как минимум потому, что необходимый JS метод navigator.mediaDevices.getUserMedia() возвращает промис. Вроде все понятно, приступаю к реализации.
// Выбрать элемент
element = $(selector);
element = document.querySelector(selector);
// Выбрать элемент внутри элемента
element2 = element.find(selector2);
element2 = element.querySelector(selector2);
// Скрыть элемент
element.hide(); // добавляет стиль display: none
element.classList.add('hidden');
Тут нужно пояснить, что CSS классу «hidden», при желании, можно прописать свойства opacity и transition, что даст эффект fadeIn/fadeOut на чистом CSS. Отлично, давно хотел отказаться от JS анимации!
// Слушать событие onClick
element.click(e => { ... });
element.onclick = (e) => { ... }
// Переключить класс
element.toggleClass(class_name);
element.classList.toggle(class_name);
// Создать div
div = $("<div>");
div = document.createElement("div");
// Вставить созданный div в element
// (это не опечатка, можно писать одинаково)
element.append(div);
element.append(div);
И т.д и т.п. В целом, код на чистом JS получается немного более многословным, но такова цена повышения производительности и снижения трафика. Нет, я никого не агитирую, но для эксперимента использую «нативный» JS с удовольствием!
WebRTC предназначен для связи между браузерами напрямую, по технологии точка-точка (p2p). Однако, чтобы установить эту связь, браузеры должны сообщить друг другу о своем намерении общаться. Для этого понадобится сервер сигнализации.
'use strict';
(function () {
const selfView = document.querySelector('#self-view'),
remoteMaster = document.querySelector('#remote-master'),
remoteSlaves = document.querySelector('#remote-slaves');
let localStream,
selfStream = null,
socket = null,
selfId = null,
connections = {};
// ***********************
// UserMedia & DOM methods
// ***********************
const init = async () => {
try {
let stream = await navigator.mediaDevices.getUserMedia({
audio: true, video: {
width: { max: 640 }, height: { max: 480 }
}
});
localStream = stream;
selfStream = new MediaStream();
stream.getVideoTracks().forEach(track => {
selfStream.addTrack(track, stream); // track.kind == 'video'
});
selfView.querySelector('video').srcObject = selfStream;
} catch (e) {
document.querySelector('#self-view').innerHTML =
'<i>Веб камера и микрофон не найдены</i>';
console.error('Local stream not found: ', e);
}
wsInit();
}
const createRemoteView = (id, username) => {
let iDiv = document.querySelector('#pc' + id);
if (!iDiv) {
iDiv = document.createElement('div');
iDiv.className = 'remote-view';
iDiv.id = 'pc' + id;
let iVideo = document.createElement('video');
iVideo.setAttribute('autoplay', 'true');
iVideo.setAttribute('playsinline', 'true');
let iLabel = document.createElement('span');
iDiv.append(iVideo);
iDiv.append(iLabel);
if (!remoteMaster.querySelector('video')) {
remoteMaster.append(iDiv);
iLabel.textContent = 'Ведущий';
} else {
remoteSlaves.append(iDiv);
iLabel.textContent = username;
}
remoteMaster.style.removeProperty('display');
}
}
// *******************************
// Signaling (Web Socket) methods
// *******************************
const wsInit = () => {
socket = new WebSocket(SIGNALING_SERVER_URL);
socket.onopen = function (e) {
log('[socket open] Соединение установлено');
}
socket.onmessage = function (event) {
log('[socket message] Данные получены с сервера', event);
wsHandle(event.data);
}
socket.onclose = function (event) {
if (event.wasClean) {
log('[close] Соединение закрыто чисто, ' +
`код=${event.code} причина=${event.reason}`);
} else {
log('[socket close] Соединение прервано', event);
}
clearInterval(socket.timer);
}
socket.onerror = function (error) {
logError('[socket error]', error);
}
socket.timer = setInterval(() => {
socket.send('heartbeat');
}, 10000);
}
const wsHandle = async (data) => {
if (!data) {
return;
}
try {
data = JSON.parse(data);
} catch (e) {
return;
}
switch (data.type) {
case 'handshake':
selfId = data.uid;
if (!Object.keys(data.users).length) {
createRemoteView(selfId, 'Ведущий');
remoteMaster.querySelector('video').srcObject =
selfStream;
selfView.remove();
break;
} else {
selfView.style.removeProperty('display');
}
for (let id in data.users) {
await pcCreate(id, data.users[id]);
}
break;
case 'offer':
await wsHandleOffer(data);
break;
case 'answer':
await wsHandleAnswer(data)
break;
case 'candidate':
await wsHandleICECandidate(data);
break;
default:
break;
}
}
const wsHandleOffer = async (data) => {
let pc = null;
if (!connections[data.src]) {
await pcCreate(data.src, data.username);
}
pc = connections[data.src].pc;
// We need to set the remote description to the received SDP offer
// so that our local WebRTC layer knows how to talk to the caller.
let desc = new RTCSessionDescription(data.sdp);
pc.setRemoteDescription(desc).catch(error => {
logError('handleOffer', error);
});
await pc.setLocalDescription(await pc.createAnswer());
wsSend({
type: 'answer',
target: data.src,
sdp: pc.localDescription
});
connections[data.src].pc = pc; // ???
}
const wsHandleAnswer = async (data) => {
log('*** Call recipient has accepted our call, answer:', data);
let pc = connections[data.src].pc;
// Configure the remote description,
// which is the SDP payload in our 'answer' message.
let desc = new RTCSessionDescription(data.sdp);
await pc.setRemoteDescription(desc).catch((error) => {
logError('handleAnswer', error);
});
}
const wsHandleICECandidate = async (data) => {
let pc = connections[data.src].pc;
let candidate = new RTCIceCandidate(data.candidate);
log('*** Adding received ICE candidate', candidate);
pc.addIceCandidate(candidate).catch(error => {
logError('handleICECandidate', error);
});
}
const wsSend = (data) => {
if (socket.readyState !== WebSocket.OPEN) {
return;
}
socket.send(JSON.stringify(data));
}
// ***********************
// Peer Connection methods
// ***********************
const pcCreate = async (id, username) => {
if (connections[id]) {
return;
}
try {
let pc = new RTCPeerConnection(PC_CONFIG);
pc.onicecandidate = (event) =>
pcOnIceCandidate(event, id);
pc.oniceconnectionstatechange = (event) =>
pcOnIceConnectionStateChange(event, id);
pc.onsignalingstatechange = (event) =>
pcOnSignalingStateChangeEvent(event, id);
pc.onnegotiationneeded = (event) =>
pcOnNegotiationNeeded(event, id);
pc.ontrack = (event) =>
pcOnTrack(event, id);
connections[id] = {
pc: pc,
username: username
}
if (localStream) {
try {
localStream.getTracks().forEach(
(track) => connections[id].pc.addTransceiver(track, {
streams: [localStream]
})
);
} catch (err) {
logError(err);
}
} else {
// Start negotiation to listen remote stream only
pcOnNegotiationNeeded(null, id);
}
createRemoteView(id, username);
} catch (error) {
logError('Peer: Connection failed', error);
}
}
const pcOnTrack = (event, id) => {
let iVideo = document.querySelector('#pc' + id + ' video');
iVideo.srcObject = event.streams[0];
}
const pcOnIceCandidate = (event, id) => {
let pc = connections[id].pc;
if (event.candidate && pc.remoteDescription) {
log('*** Outgoing ICE candidate: ' + event.candidate);
wsSend({
type: 'candidate',
target: id,
candidate: event.candidate
});
}
}
const pcOnNegotiationNeeded = async (event, id) => {
let pc = connections[id].pc;
try {
const offer = await pc.createOffer();
// If the connection hasn't yet achieved the "stable" state,
// return to the caller. Another negotiationneeded event
// will be fired when the state stabilizes.
if (pc.signalingState != 'stable') {
return;
}
// Establish the offer as the local peer's current
// description.
await pc.setLocalDescription(offer);
// Send the offer to the remote peer.
wsSend({
type: 'offer',
target: id,
sdp: pc.localDescription
});
} catch(err) {
logError('*** The following error occurred while handling' +
' the negotiationneeded event:', err);
};
}
const pcOnIceConnectionStateChange = (event, id) => {
let pc = connections[id].pc;
switch (pc.iceConnectionState) {
case 'closed':
case 'failed':
case 'disconnected':
pcClose(id);
break;
}
}
const pcOnSignalingStateChangeEvent = (event, id) => {
let pc = connections[id].pc;
log('*** WebRTC signaling state changed to: ' + pc.signalingState);
switch (pc.signalingState) {
case 'closed':
pcClose(id);
break;
}
}
const pcClose = (id) => {
let remoteView = document.querySelector('#pc' + id);
if (connections[id]) {
let pc = connections[id].pc;
pc.close();
delete connections[id];
}
if (remoteView) {
remoteView.remove();
}
}
// *******
// Helpers
// *******
const log = (msg, data) => {
if (!data) {
data = ''
}
console.log(msg, data);
}
const logError = (msg, data) => {
if (!data) {
data = ''
}
console.error(msg, data);
}
init();
})();
Сервер сигнализации выполнен на Python фреймвоке aiohttp и представляет собой простую «вьюху», тривиально проксирующую запросы WebRTC. Соединение с сервером в этом примере выполнено на веб сокетах. Ну и, в дополнение, через канал сигнализации передаются данные простого текстового чата.
import json
from aiohttp.web import WebSocketResponse, Response
from aiohttp import WSMsgType
from uuid import uuid1
from lib.views import BaseView
class WebSocket(BaseView):
""" Process WS connections """
async def get(self):
username = self.request['current_user'].firstname or 'Аноним'
room_id = self.request.match_info.get('room_id')
if room_id != 'test_room' and
self.request['current_user'].is_anonymous:
self.raise_error('forbidden') # @TODO: send 4000
if (self.request.headers.get('connection', '').lower() != 'upgrade' or
self.request.headers.get('upgrade', '').lower() != 'websocket'):
return Response(text=self.request.path) # ???
self.ws = WebSocketResponse()
await self.ws.prepare(self.request)
self.uid = str(uuid1())
if room_id not in self.request.app['web_sockets']:
self.request.app['web_sockets'][room_id] = {}
self.room = self.request.app['web_sockets'][room_id]
users = {}
for id, data in self.room.items():
users[id] = data['name']
ip = self.request.headers.get(
'X-FORWARDED-FOR',
self.request.headers.get('X-REAL-IP',
self.request.remote))
msg = {
'type': 'handshake',
'uid': str(self.uid),
'users': users, 'ip': ip}
await self.ws.send_str(json.dumps(msg, ensure_ascii=False))
self.room[self.uid] = {'name': username, 'ws': self.ws}
try:
async for msg in self.ws:
if msg.type == WSMsgType.TEXT:
if msg.data == 'heartbeat':
print('---heartbeat---')
continue
try:
msg_data = json.loads(msg.data)
if 'target' not in msg_data or
msg_data['target'] not in self.room:
continue
msg_data['src'] = self.uid
if 'type' in msg_data and 'target' in msg_data:
if msg_data['type'] == 'offer':
msg_data['username'] = username
else:
print('INVALID DATA:', msg_data)
except Exception as e:
print('INVALID JSON', e, msg)
try:
await self.room[msg_data['target']]['ws'].send_json(
msg_data);
except Exception as e:
if 'target' in msg_data:
self.room.pop(msg_data['target'])
finally:
self.room.pop(self.uid)
return self.ws
Технология WebRTC, кроме видеосвязи, позволяет предоставить браузеру разрешение на захват содержимого дисплея или отдельного приложения, что может оказаться незаменимым при проведении онлайн уроков, вебинаров или презентаций. Отлично, используем.
Я так увлекся современными возможностями видеосвязи, что чуть не забыл о самом главном предмете в классе — интерактивной доске. Впрочем, базовая реализация настолько тривиальна, что я не стану загромождать ею эту статью. Просто добавляем canvas, слушаем события перемещения мыши onmousemove (ontouchmove для планшетов) и отправляем полученные координаты всем подключенным точкам через тот же сервер сигнализации.
Тестируем интерактивную доску
Тут понадобится планшет, дигитайзер и живой ребёнок. Заодно проверим возможность оцифровки рукописного ввода.
Для начала я взял старенький планшет Galaxy Tab на андроиде 4.4, самодельный стилус и первые попавшиеся прописи в качестве фона для canvas. Дополнительные программы не устанавливал. Результат меня обескуражил: мой планшет абсолютно не пригоден для письма! То есть водить по нему пальцем — без проблем, а вот попасть стилусом в контур буквы, даже такой огромной, как на картинке ниже, уже проблема. Плюс гаджет начинает тупить в процессе рисования, в результате чего линии становятся ломанными. Плюс мне не удалось заставить ребёнка не опирать запястье на экран, отчего под рукой остается дополнительная мазня, а сам планшет начинает тормозить еще больше. Итог: обычный планшет для письма на доске не подходит. Максимум его возможностей — двигать пальцем по экрану достаточно крупные фигуры. Но предлагать это школьникам поздновато.
Ладно, у нас ведь чисто теоретическое исследование, верно? Тогда берем дигитайзер (он же графический планшет) Wacom Bamboo формата A8, и наблюдаем за ребёнком.
Замечу, что мой подопытный шести лет от роду получил ноутбук, да еще с графическим пером первый раз в жизни. На получение базовых навыков обращения с пером у нас ушло минут десять, а уже на втором уроке ребёнок пользовался планшетом вполне уверенно, самостоятельно стирал с доски, рисовал рожицы, цветочки, нашу собаку и даже начал тыкать доступные в эпсилон окрестности кнопки, попутно задавая вопросы типа «А зачем в школе поднимают руку?». Вот только результат неизменно оставлял желать лучшего. Дело в том, что дизайнеры и художники для прорисовки элемента максимально увеличивают фрагмент изображения, что и делает линии точными. Здесь же мы должны видеть доску целиком, в масштабе 1:1. Тут и взрослый не попадет в линию. Вот что получилось у нас:
Итоговый вердикт: ни о каком рукописном вводе не может быть и речи. А если мы хотим «поставить руку» нашим детям, нужно добиваться этого самостоятельно, на бумаге, школа в этом никак не поможет.
Надо сказать, что ребёнок воспринял все мои эксперименты с восторгом и, более того, с тех пор ходит за мной хвостиком и просит «включить прописи». Уже хорошо, полученный навык ему пригодится, только совсем для других целей.
Так или иначе, в результате экспериментов я фактически получил MVP — минимально жизнеспособный продукт (minimum viable product), почти пригодный для проведения онлайн уроков, с видео/аудио конференцией, общим экраном, интерактивной доской, простым текстовым чатом и кнопкой «поднять руку». Это на случай, если у ребёнка вдруг не окажется микрофона. Да, такое бывает, особенно у детей, не выучивших уроки.
Но в этой бочке меда, к сожалению, есть пара ложек дёгтя.
Тестируем WebRTC
Ложка №1. Поскольку наша видеосвязь использует прямые подключения между клиентами, нужно первым делом проверить масштабируемость такого решения. Для теста я взял старенький ноутбук с двухядерным i5-3230M на борту, и начал подключать к нему клиентов с отключенными веб камерами, то есть эмулируя режим один-ко-многим:
Как видите, подопытный ноут в состоянии более-менее комфортно вещать пяти клиентам (при загрузке CPU в пределах 60%). И это при условии снижения разрешения исходящего видеопотока до 720p (640x480px) и frame rate до 15 fps. В принципе, не так уж и плохо, но при подключении класса из нескольких десятков учеников от «фулл меша» придется отказаться в пользу каскадирования, то есть каждый из первых пяти клиентов проксирует поток следующим пяти и так далее.
Ложка №2. Для создания прямого интерактивного подключения (ICE) между клиентами им нужно обойти сетевые экраны и преобразователи NAT. Для этого WebRTC использует сервер STUN, который сообщает клиентам внешние параметры подключения. Считается, что в большинстве случаев этого достаточно. Но мне почти сразу же «повезло»:
Как видите, отладчик ругается на невозможность ICE соединения и требует подключения TURN сервера, то есть ретранслятора (relay). А это уже ДОРОГО. Простым сервером сигнализации тут не обойтись. Вывод — придётся пропускать все потоки через медиа сервер.
Медиа сервер
Для тестирования я использовал aiortc. Интересная разработка, позволяет подключить браузер напрямую к серверу через WebRTC. Отдельная сигнализация не нужна, можно использовать канал данных самого соединения. Это работает, все мои тестовые точки подключились без проблем. Но вот с производительностью беда. Простое эхо видео/аудио потока с теми же ограничениями 720p и 15fps съели 50% моего виртуального CPU на тестовом VDS. Причём, если увеличить нагрузку до 100%, видео поток не успевает выгружаться клиентам и начинает забивать память, что в итоге приводит к остановке сервера. Очевидно, Питон, который мы любим использовать для задач обработки ввода/вывода, не очень подходит для «CPU bound». Придётся поискать более специализированное решение, например, Янус или Джитси.
В любом случае, полноценное решение потребует выделенных серверов, по моим прикидкам, из расчёта 1 ядро на комнату (класс). Это уже стоит денег и выходит за рамки простого тестирования, поэтому в этом месте первую фазу моего исследования я буду считать завершённой.
Выводы
1. Мягко говоря, странно видеть на официальном портале Российской Федерации инструкции по скачиванию и ссылки на регистрацию в программе бывшего потенциального врага №1 (тут про Microsoft Teams). И это в эпоху санкций и импортозамещения.
Нет, лично я за дружбу народов и вообще всяческую толерантность, но неужели только у меня от такой «интеграции» встают волосы дыбом? Разве нет наших разработок?
2. Интеграция МЭШ/РЭШ со школами. Вообще-то, разработчики МЭШ молодцы, даже с Яндекс.репетитором интеграцию сделали. А как быть с выставлением оценок в реальном времени во время уроков, когда будет API? Или я чего-то не знаю?
3. Выбирая дистанционную или семейную форму обучения, нужно быть честным с собой: переложить ответственность за образование ребёнка на школу не получится. Вся работа по проведению уроков (в случае семейного образования), поддержанию дисциплины и самоорганизованности (в любом случае) полностью ложится на родителей. Нужно отдавать себе в этом отчёт и найти время на занятия. Впрочем, в больших семьях с этим проблем быть не должно.
4. Я не буду приводить здесь ссылки на выбранные нами онлайн школы, чтобы это не сочли рекламой. Скажу только, что мы остановились на частных школах среднего ценового диапазона. В любом случае, окончательный результат будет зависеть от ребёнка и получим мы его не раньше сентября.
Или есть смысл довести до логического конца начатую здесь разработку и организовать свою школу? Что вы думаете? Есть единомышленники, имеющие профильные знания и опыт в области образования?
Полезные ссылки:
Российская Электронная Школа
Московская Электронная Школа
Библиотека МЭШ
Разработчику
Azya
Ну-ну, если добьётесь того, что в начальных классах ребенок будет делать домашнюю работу полностью самостоятельно, надеюсь расскажите потом как.
vladpen Автор
Так уже. Не сказать, что полностью самостоятельно, но ребёнок приучен хотя бы попытаться выполнить задание, и придти либо с результатом на проверку, либо с конкретным вопросом о том, что именно не получается. Разбирать новые темы и выполнять задания каждого нового вида в любом случае приходится вместе.
Иначе получается полная ерунда: ребёнок сидит и ЖДЕТ, пока мама или папа придут делать с ним уроки. И у нас это не первый ребёнок, поверьте.
MichaelProtector
В большинстве случаев с моей практики — не с ним, а ЗА него
Хочу пожелать вам успехов, не у всех родителей хватает терпения на семейное образование.
Azya
Ну это и есть делать с ребенком домашнюю работу, вопрос в необходимой степени помощи, который для разных детей сильно разнится.
vladpen Автор
Я лишь хотел лишний раз подчеркнуть, что лично моя цель в долгосрочной перспективе — не накормить ребёнка, а дать ему удочку и научить ловить рыбу. Я отдаю себе отчет, что это получится не у всех родителей и не со всеми детьми. Но мы честно пытаемся.
Azya
Благая цель, полностью с ней согласен. Просто триггернул на ваше безапелляционное заявление.
DmitryAnatolich
М-м-м, я пошел в первый класс «всего» 20 лет назад, и «в то время» ни у кого и в мыслях не было делать с ребёнками домашние задания.
И не только потому, что все дети были такими умными, а учителя всё отлично объясняли, но и потому, что родители работают и им тоже не помешало бы отдохнуть. Ну и фактор «ой, мы такого не изучали/я этого уже не помню» тоже присутствовал.
Могу через год написать сюда дополнение с личным опытом уже с родительской стороны :).
Azya
Со мной на постоянной основе делали до 4го класса (хотя я этого не помню и по наивности думал, что делал всегда сам), больше 20 лет назад, и по рассказам мамы — делало большинство родителей, а те кому не помогали — хорошо не учились. Но наверно, сейчас это более распространено, родительская опека вообще имеет тенденцию увеличиваться. Тут еще накладывается тот момент, что нагрузка в начальной школе сейчас гораздо выше, многие темы проходят вскользь, а спрашивают полноценно, чтобы ребенок усваивал все без помощи родителей, он должен обладать отличной усидчивостью, умом и мотивацией.
DmitryAnatolich
Опять-таки, смотря где, смотря какой учитель/программа, смотря какая подготовка у ребенка.
Мы с женой предвкушаем, что дочь в следующем году пойдет в школу и будет еще разок учиться читать/писать/считать (как и мы в своё время). Для закрепления, так сказать.
Azya
Ваша правда. Но читать, мне кажется, уже ни в одной школе не учат.
DistortNeo
Ну вот я делал домашнюю работу полностью самостоятельно в младших классах. Вообще, ситуацию, когда родитель вынужден принимать участие в обучении ребёнка, помимо основной работы, считаю ненормальной.
vladpen Автор
Принимать участие надо, а вот делать за ребёнка — однозначно нет.
Я в школе, начиная с первого класса, только приносил родителям дневник с оценками (по вечерам, все работали). Если оценки падали, тогда уже со мной разбирались. Не припоминаю проблем с успеваемостью. Закончил школу с очень приличным средним баллом, что позволило мне поступить в престижный технический вуз. Значит, метод работает. Да и опыт со старшими детьми это подтверждает. Хотя, там были свои трудности, но это уже совсем другая история.