Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Дмитрий Бурдин #22

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@

Поставь зависимости и запусти сервер. Для этого перейди в директорию задачи и выполни команду `npm install`. После установки зависимостей, выполни команду `npm run dev`. После запуска, перейди по адресу [localhost:5000](http://localhost:5000)

1. Сейчас цвета палитры захардкожены в файле `/client/picker.mjs`, cделай так, чтобы цвета запрашивались с сервера в функции `drawPalette`
+++1. Сейчас цвета палитры захардкожены в файле `/client/picker.mjs`, cделай так, чтобы цвета запрашивались с сервера в функции `drawPalette`

2. На сервере мы будем использовать библиотеку [ws](https://github.com/websockets/ws) для подключения по протоколу [WebSocket](https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API). Она уже подключена, `WebSocket`-сервер уже правильно интегрирован с `express`, запущен и ждёт подключений по тому же порту, что и `express`.
+++2. На сервере мы будем использовать библиотеку [ws](https://github.com/websockets/ws) для подключения по протоколу [WebSocket](https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API). Она уже подключена, `WebSocket`-сервер уже правильно интегрирован с `express`, запущен и ждёт подключений по тому же порту, что и `express`.

Сделай так, чтобы `WebSocket`-сервер начал обрабатывать подключения, т.е. события `connection`, как [в примере](https://github.com/websockets/ws#simple-server)

3. Сделай так, чтобы после подключения, новому клиенту присылался текущий массив состояния поля. Так как от сервера к клиенту будут передаваться разные сообщения, то удобно, чтобы каждое сообщение имело следующую структуру:
+++3. Сделай так, чтобы после подключения, новому клиенту присылался текущий массив состояния поля. Так как от сервера к клиенту будут передаваться разные сообщения, то удобно, чтобы каждое сообщение имело следующую структуру:

```javascript
{
Expand All @@ -28,15 +28,15 @@

Как принимать и отправлять строковые сообщения уже было показано [в примере](https://github.com/websockets/ws#simple-server)

4. Сделай так, чтобы на клиенте при получении сообщения из `WebSocket` с начальным состоянием поля, заполнялось поле. Для этого измени обработчик события на `ws` в файле `/client/index.mjs`. В него сейчас приходят события [MessageEvent](https://developer.mozilla.org/en-US/docs/Web/API/MessageEvent). Для десериализации данных в событии используй `JSON.parse()`. Для отрисовки начального состояния используй `drawer.putArray()`
+++4. Сделай так, чтобы на клиенте при получении сообщения из `WebSocket` с начальным состоянием поля, заполнялось поле. Для этого измени обработчик события на `ws` в файле `/client/index.mjs`. В него сейчас приходят события [MessageEvent](https://developer.mozilla.org/en-US/docs/Web/API/MessageEvent). Для десериализации данных в событии используй `JSON.parse()`. Для отрисовки начального состояния используй `drawer.putArray()`

5. Сделай так, чтобы при клике на поле, на сервер по `WebSocket` передавалось сообщение с координатами и цветом. Посылай сообщения с помощью метода [send()](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/send). Для удобства, используй тот же формат, что и в сообщениях, посылаемых с сервера
+++5. Сделай так, чтобы при клике на поле, на сервер по `WebSocket` передавалось сообщение с координатами и цветом. Посылай сообщения с помощью метода [send()](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/send). Для удобства, используй тот же формат, что и в сообщениях, посылаемых с сервера

6. Сделай так, чтобы `WebSocket`-сервер при получении сообщения с координатами и цветом валидировал его на правильность координат и цвета, а затем рассылал всем активным клиентам. Как сделать `broadcast` посмотри [в примере](https://github.com/websockets/ws#server-broadcast)
+-6. Сделай так, чтобы `WebSocket`-сервер при получении сообщения с координатами и цветом валидировал его на правильность координат и цвета, а затем рассылал всем активным клиентам. Как сделать `broadcast` посмотри [в примере](https://github.com/websockets/ws#server-broadcast)

7. Сделай так, чтобы новые пиксели не только рассылались остальным клиентам, но и добавлялись в поле, хранимое на стороне сервера. Это нужно, чтобы новые клиенты получали текущее изображение, а не начальное. Как сделаешь — проверь: открой приложение с одной вкладки браузера, нарисуй что-нибудь, затем открой со второй вкладки и убедись, что изображения совпадают
+++7. Сделай так, чтобы новые пиксели не только рассылались остальным клиентам, но и добавлялись в поле, хранимое на стороне сервера. Это нужно, чтобы новые клиенты получали текущее изображение, а не начальное. Как сделаешь — проверь: открой приложение с одной вкладки браузера, нарисуй что-нибудь, затем открой со второй вкладки и убедись, что изображения совпадают

8. Удали из обработчика клика на поле отрисовку пикселя. Для этого сделай так, чтобы при `broadcast`-е текущему клиенту тоже отправлялось сообщение. А затем сделай так, чтобы отрисовка пикселя происходила только при получении клиентом сообщения из `WebSocket`. После этого сервер будет полностью контролировать целостность поля для рисования
+++8. Удали из обработчика клика на поле отрисовку пикселя. Для этого сделай так, чтобы при `broadcast`-е текущему клиенту тоже отправлялось сообщение. А затем сделай так, чтобы отрисовка пикселя происходила только при получении клиентом сообщения из `WebSocket`. После этого сервер будет полностью контролировать целостность поля для рисования

9. Опубликуй своё приложение на [Heroku](https://id.heroku.com/login). Для этого потребуются `heroku-cli`, и `git`, если чего-то нет, пройди [вот эти шаги](https://devcenter.heroku.com/articles/getting-started-with-nodejs#set-up).

Expand Down
22 changes: 20 additions & 2 deletions client/index.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,29 @@ document.querySelector("#start").addEventListener("submit", e => {

const main = apiKey => {
const ws = connect(apiKey);
ws.addEventListener("message", console.log);
ws.addEventListener("message", message => {
let result = JSON.parse(message.data)
console.log(result.type)
if (result.type == 'place') {
drawer.putArray(result.payload.place);
}
if(result.type == 'pick') {
drawer.put(result.payload.x, result.payload.y, result.payload.color);
}
})

timeout.next = new Date();

drawer.onClick = (x, y) => {
drawer.put(x, y, picker.color);

ws.send(JSON.stringify({
type: 'click',
payload: {
x: x,
y: y,
color: picker.color
}
}))
};
};

Expand Down
3 changes: 2 additions & 1 deletion client/picker.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ const setAttributes = (element, object) => {
};

const drawPalette = async () => {
const colors = hardcodedColors;
const response = await fetch("/api/getColors");
const colors = await response.json();
pickedColor = colors[0];
const palette = document.querySelector("#palette");
const fragment = document.createDocumentFragment();
Expand Down
42 changes: 42 additions & 0 deletions server.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -43,20 +43,62 @@ const app = express();

app.use(express.static(path.join(process.cwd(), "client")));

app.get('/api/getColors', (req, resp) => {
console.log(colors)
resp.json(colors)
})

app.get("/*", (_, res) => {
res.send("Place(holder)");
});

const server = app.listen(port);

const wss = new WebSocket.Server({
port: 3000,
noServer: true,
});


server.on("upgrade", (req, socket, head) => {
const url = new URL(req.url, req.headers.origin);
console.log(url);
wss.handleUpgrade(req, socket, head, (ws) => {
wss.emit("connection", ws, req);
});
});

wss.on('open', function open() {

});

function sendField(ws) {
let result = {
type: 'place',
payload: {
place: place
}
};
ws.send(JSON.stringify(result));
}

function insertPlace(payload) {
place[size * payload.y + payload.x] = payload.color;
wss.clients.forEach(client => {
if(client.readyState == WebSocket.OPEN) {
sendField(client);
}
});
}

wss.on('connection', (ws) => {
ws.on('message', (message) => {
let parseData = JSON.parse(message);

if(parseData.type == 'click') {
insertPlace(parseData.payload);
}
})

sendField(ws)
})