Skip to content
Merged
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
14 changes: 0 additions & 14 deletions .env.example

This file was deleted.

1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
node_modules
.env
frontend/dist
Notes
firebase-debug.log
firestore-debug.log
Expand Down
56 changes: 29 additions & 27 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ This project is a typing practice web-app, that helps you improve your speed by

## Tech stack

- HTML, CSS, Javascript, firebase, socket.io
- HTML, CSS, Javascript, firebase, socket.io, Vite

## How to contribute

Expand All @@ -20,10 +20,7 @@ This project is a typing practice web-app, that helps you improve your speed by
│ .firebaserc
│ .gitignore
│ firebase.json
│ package-lock.json
│ package.json
│ README.md
│ webpack.config.js
├───.github
│ └───workflows
Expand All @@ -37,30 +34,35 @@ This project is a typing practice web-app, that helps you improve your speed by
│ race.js
│ user.js
├───docs
│ │ base.css
│ │ bundle.js
│ │ index.html
│ │ style.css
│ │
│ └───assets
│ icon.svg
│ loading.gif
│ text-logo.svg
└───src
│ script.js
└───frontend
│ .env
│ .env.example
│ index.html
│ package.json
│ vite.config.js
├───public
│ │ base.css
│ │ style.css
│ │
│ └───assets
│ icon.svg
│ loading.gif
│ text-logo.svg
├───firebase
│ *.js
├───functions
│ *.js
├───socket
│ *.js
├───storage
│ *.js
└───ui
*.js
└───src
│ script.js
├───firebase
│ *.js
├───functions
│ *.js
├───socket
│ *.js
├───storage
│ *.js
└───ui
*.js
```

## Discussions
Expand Down
4 changes: 2 additions & 2 deletions backend/controllers/textController.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import { COMMON_WORDS } from "../data/words.js";

const CONSTANTS = {
DEFAULT_WORD_COUNT: 50,
DEFAULT_WORD_COUNT: 25,
MIN_WORD_COUNT: 1,
MAX_WORD_COUNT: 200,
};

/**
* Generate random text from common English words
* @param {number} wordCount - Number of words to generate (default: 50)
* @param {number} wordCount - Number of words to generate (default: 25)
* @returns {string} Random text with specified number of words
*/
export function generateRandomText(wordCount = CONSTANTS.DEFAULT_WORD_COUNT) {
Expand Down
6 changes: 3 additions & 3 deletions backend/getText.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ import { generateRandomText } from "./controllers/textController.js";

const CONSTANTS = {
LOG_PREVIEW_LENGTH: 50,
DEFAULT_WORD_COUNT: 50,
DEFAULT_WORD_COUNT: 25,
};

export default async function getText(io, room) {
export default async function getText(io, room, wordCount) {
try {
const text = generateRandomText(CONSTANTS.DEFAULT_WORD_COUNT);
const text = generateRandomText(wordCount || CONSTANTS.DEFAULT_WORD_COUNT);
console.log(
`[INFO] New text fetched for room ${room}: "${text.substring(0, CONSTANTS.LOG_PREVIEW_LENGTH)}..."`
);
Expand Down
38 changes: 32 additions & 6 deletions backend/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,32 @@ app.use(cors());
const httpServer = createServer(app);
let corsOrigin;

const ROOM_WORD_COUNT_OPTIONS = [10, 25, 50, 100];
const DEFAULT_WORD_COUNT = 25;
const roomSettings = new Map();

function normalizeWordCount(value) {
const parsed = parseInt(value, 10);
return ROOM_WORD_COUNT_OPTIONS.includes(parsed)
? parsed
: DEFAULT_WORD_COUNT;
}

console.log("[INFO] Initializing server...");

process.env.DEVELOPMENT_MODE == "true"
? (corsOrigin = ["http://localhost:8080", "http://127.0.0.1:5500"])
? (corsOrigin = [
"http://localhost:5173",
"http://127.0.0.1:5173",
"http://localhost:8080",
"http://127.0.0.1:5500",
])
: (corsOrigin = [process.env.FRONTEND_ADDRESS]);


app.get("/api/text", (req, res) => {
try {
const wordCount = req.query.words || 50;
const wordCount = req.query.words || DEFAULT_WORD_COUNT;
const text = generateRandomText(wordCount);
res.json({ content: text });
} catch (error) {
Expand Down Expand Up @@ -63,7 +79,9 @@ const PORT = process.env.PORT || 3000;

io.on("connection", (socket) => {
console.log(`[INFO] New socket connection: ${socket.id}`);
socket.on("createRoom", (userName, room) => createRoom(userName, room));
socket.on("createRoom", (userName, room, settings) =>
createRoom(userName, room, settings)
);
socket.on("joinRoom", (userName, room) => joinRoom(userName, room));

socket.on("typing", (user) => {
Expand All @@ -73,13 +91,15 @@ io.on("connection", (socket) => {
io.to(user.room).emit("playerList", playerList);
});

function createRoom(userName, room) {
function createRoom(userName, room, settings) {
if (!room) {
console.log("[INFO] Room creation failed: no room name provided");
return;
}
let roomId = room.slice(0, 6);
socket.join(roomId);
const wordCount = normalizeWordCount(settings && settings.wordCount);
roomSettings.set(roomId, { wordCount });
console.log(`[INFO] Room created: ${roomId} by user: ${userName || 'guest'}`);
socket.emit("roomId", roomId);
let tempUser = {
Expand All @@ -97,7 +117,9 @@ io.on("connection", (socket) => {

socket.on("getText", (room) => {
console.log(`[INFO] Fetching new text for room: ${room}`);
getText(io, room);
const settings = roomSettings.get(room);
const wordCount = normalizeWordCount(settings && settings.wordCount);
getText(io, room, wordCount);
const playerList = resetUser(room);
io.to(room).emit("playerList", playerList);
});
Expand Down Expand Up @@ -156,7 +178,11 @@ io.on("connection", (socket) => {
const user = removeUser(socket.id);
if (user) {
console.log(`[INFO] User ${user.name} disconnected from room: ${user.room}`);
io.to(user.room).emit("playerList", getUsersInRoom(user.room));
const remainingUsers = getUsersInRoom(user.room);
io.to(user.room).emit("playerList", remainingUsers);
if (remainingUsers.length === 0) {
roomSettings.delete(user.room);
}
} else {
console.log(`[INFO] Socket ${socket.id} disconnected (user not found)`);
}
Expand Down
Loading
Loading