This commit is contained in:
Andrew 2022-03-14 13:35:21 +07:00
parent f662d9933f
commit cb0a0dee2b
11 changed files with 116895 additions and 0 deletions

3
w7/.dockerignore Normal file
View file

@ -0,0 +1,3 @@
node_modules
Dockerfile
.dockerignore

16
w7/Dockerfile Normal file
View file

@ -0,0 +1,16 @@
FROM node:16.13.2-alpine3.14
RUN mkdir -p /home/node/app/node_modules && chown -R node:node /home/node/app
WORKDIR /home/node/app
COPY --chown=node:node . .
RUN corepack enable
RUN corepack prepare pnpm@6.32.2 --activate
RUN pnpm install
USER node
EXPOSE 9559/tcp
CMD [ "pnpm", "start" ]

100
w7/index.js Normal file
View file

@ -0,0 +1,100 @@
import express from "express";
import mustache from "mustache";
import bodyParse from "body-parser";
import { readdirSync, readFileSync } from "fs";
import { Server } from "socket.io";
import http from "http";
const app = express();
app.use(express.static("./static"));
app.use(bodyParse.urlencoded({ extended: true }));
const port = 9779;
const server = http.createServer(app);
const io = new Server(server);
class Room {
id = 0
history = []
static newRoom() {
const room = new Room();
room.id = db.roomsCount++;
db.rooms.push(room);
return room;
}
/**
*
* @param {String} type
* @param {Array.<Any>} params
*/
addCmd(type, params) {
this.history.push([Date.now(), type, params]);
}
}
const db = {
roomsCount: 0,
/** @type {Array.<Room>} */
rooms: [],
/**
*
* @param {Number} roomId
*/
findRoom(roomId) {
let room = null;
for (let _room of db.rooms) {
if (_room.id === roomId) {
room = _room;
}
}
return room;
}
};
const templates = new Map(readdirSync("./templates").map(fn => [fn, readFileSync(`./templates/${fn}`, "utf-8")]));
app.get("/", (req, res) => {
res.send(mustache.render(templates.get("mainPage.html"), { db }));
});
app.get("/createRoom", (req, res) => {
let room = Room.newRoom();
res.redirect(`/room/${room.id}`);
});
app.get("/room/:roomId", (req, res) => {
let room = db.findRoom(parseInt(req.params.roomId));
if (room === null) {
res.redirect("/");
} else {
res.send(mustache.render(templates.get("roomPage.html"), { room }));
}
});
io.on("connection", (socket) => {
socket.on("draw", (data) => {
console.log(`data: ${JSON.stringify(data)}`);
let room = db.findRoom(parseInt(data.roomId));
if (room === null) {
console.error(`No room with id ${data.roomId}!`);
} else {
room.addCmd(data.type, data.params);
io.emit("draw_sync", data);
}
});
socket.on("sync_me", (data) => {
console.log(`data: ${JSON.stringify(data)}`);
let room = db.findRoom(parseInt(data.roomId));
if (room === null) {
console.error(`No room with id ${data.roomId}!`);
} else {
socket.emit("sync_history", { roomId: data.roomId, history: room.history });
}
});
});
server.listen(port, () => console.log(`⚡️ Serving on port ${port}`));

23
w7/package.json Normal file
View file

@ -0,0 +1,23 @@
{
"name": "w7",
"version": "1.0.0",
"description": "",
"main": "index.js",
"type": "module",
"scripts": {
"start": "node .",
"watch": "nodemon -e *",
"build": "docker build -t nuark/w7_bld ."
},
"author": "nuark",
"license": "MIT",
"dependencies": {
"body-parser": "^1.19.2",
"express": "^4.17.3",
"mustache": "^4.2.0",
"socket.io": "^4.4.1"
},
"devDependencies": {
"nodemon": "^2.0.15"
}
}

1224
w7/pnpm-lock.yaml generated Normal file

File diff suppressed because it is too large Load diff

5
w7/static/css/styles.css Normal file
View file

@ -0,0 +1,5 @@
* {
padding: 0;
margin: 0;
overflow: hidden;
}

70
w7/static/js/app.js Normal file
View file

@ -0,0 +1,70 @@
const socket = io();
let sizeSlider;
let colorPicker;
let drawings = [];
const syncDrawing = function(data) {
const {roomId, type, params} = data;
if (data.roomId !== roomId) return;
push();
drawCmd(type, params);
pop();
}
const syncHistory = function(data) {
const {roomId, history} = data;
if (data.roomId !== roomId) return;
push();
for (const hItem of history) {
const [when, type, params] = hItem;
drawCmd(type, params);
}
pop();
}
const drawCmd = function(type, params) {
if (type == "stroke") {
fill(...params.color);
ellipse(params.x, params.y, params.strokeSize);
}
}
function setup() {
createCanvas(windowWidth, windowHeight);
sizeSlider = createSlider(1, 100, 6);
sizeSlider.position(10, 10);
sizeSlider.style("width", "200px");
colorPicker = createColorPicker(color(255, 204, 0));
colorPicker.position(10, 40);
noStroke();
socket.on("draw_sync", syncDrawing);
socket.on("sync_history", syncHistory);
socket.emit("sync_me", { roomId });
}
function draw() {
fill(colorPicker.color());
}
function mouseDragged(event) {
if (!event.target.classList.value.includes("p5Canvas")) return;
socket.emit("draw", { roomId, type: "stroke", params: { color: colorPicker.color().levels, strokeSize: sizeSlider.value(), x: mouseX, y: mouseY } });
}
function windowResized() {
resizeCanvas(windowWidth, windowHeight);
socket.emit("sync_me", { roomId });
}

111165
w7/static/js/p5.js Normal file

File diff suppressed because one or more lines are too long

4240
w7/static/js/socket.io.js Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,31 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Main page</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Smooch+Sans:wght@300;400;700&display=swap" rel="stylesheet">
<link rel="stylesheet" href="/css/styles.css">
</head>
<body>
<main>
<section class="roomsSection">
<h3>Available {{db.roomsCount}} rooms:</h3>
<div class="rooms">
{{#db.rooms}}
<a class="roomItem" href="/room/{{id}}">
Room {{id}}
</a>
{{/db.rooms}}
{{^db.rooms}}
<p><b>No rooms available!</b></p>
{{/db.rooms}}
</div>
<button onclick="javascript:location = `/createRoom`">Create new room</button>
</section>
</main>
</body>
</html>

View file

@ -0,0 +1,18 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Room {{room.id}}</title>
<link rel="stylesheet" href="/css/styles.css">
</head>
<body>
</body>
<script>
const roomId = parseInt("{{room.id}}");
</script>
<script src="/js/socket.io.js"></script>
<script src="/js/p5.js"></script>
<script src="/js/app.js"></script>
</html>