After A2oJ’s expiration at the end of 2019, it left us gloomy, leading us to create a similar application with extra features and a striking user interface. As a tribute to it, I had built a project, CoderBano (or become a coder) alongside Aakash Goel. It lets users register with their Codeforces handle and keeps track of the different Codeforces ladders questions with analytics of users and their friends.
If you haven’t used A2oJ till now, read on to learn how it works. One of the notable features is that it provides us with a ladder (or list) of questions, ordered by the div (division). A question belongs to a div by the level of its difficulty (e.g., div 2a has easier questions than div 2b, div 1d).
Users can select a ladder of a particular div and view their questions, which usually contains a hundred questions, all locked by default. A user has to solve the questions one by one to unlock the whole ladder. The author, Ahmad Aly, maintains all of them. Hence, it becomes a better way to warm-up queries of a certain difficulty.
Our initial goal involved forming a dashboard for the user, enabling them to see all the solved problems and nudging them to attempt the latest unlocked one. Aakash and I wished to calculate the number of questions a user solved across all ladders and aggregate and compute some analytics (like most used language, productive day and the time of day and a user’s last activity in a div).
Tech Stack and Explanation
This project is a full-stack application, and we went with the MERN stack. For simplicity, we created a monorepo for the frontend and the backend. I handled the backend architecture and database, whereas Aakash oversaw the frontend design and architecture.
We ran the Codeforces API on the backend to compute the analytics for a user.
For the deployment, we used Vercel for the react-app, Heroku for the node-app, and MongoDB-Atlas for the database.
Problems and Thought Process
Since we overly depend on the Codeforces API, we had to brainstorm over a solution to mend the users’ submission data problem, in case the API went down. Initially, we were requesting all the submissions of a user and then iterating each of them. After cleaning and analysing the data, we returned the results to the frontend. This took a lot of time to respond, as some users had too many submissions. Later we thought of saving a user’s submissions on the first request so that on subsequent requests, we could grab the old ones from the database and analyse the new ones.
This solution cut short the users’ server response time, who had a lot of submissions.
Next problem was in the authentication module. We used to authenticate users using jwt tokens, with our server issuing a signed token on successful login. Then the user would return that token back to access authenticated data. However, this held a major flaw if we wanted to revoke a user’s token. As the user’s browser saves the token, we had no access to it. In the event of a breach, we could only change the jwt secret on a server which requires signing this token, expiring all the issued tokens till date. As this is poor for the UX, we came with a solution to use Redis.
Redis is an in-memory data structure store, used as a database, cache, and message broker. It has fast read/writes for small data. We use it to maintain a list of revoked tokens, denying them access to the authenticated data.
While working on the app, we picked up many ways of handling authentications. This allowed us to try out Redis and develop our own system. We also understood the value of a decent user interface that raises the app’s usability.
We had figured out of a couple of features, while a few were over-ambitious, some were useful too:
- A friend-stalking area, where a user can add other users as friends and see their analytics.
- A detailed page, showing the list of upcoming and ongoing contests on various coding - platforms.
- A playground for the users to compile and run their code.
Although we somewhat achieved the third point, using HackerEarth’s API, it rate-limited us right away.
You can create your own account now on the live demo, using your Codeforces handle. If you don’t have one, you can use my credentials to capture the look and feel.
- Username: rhnmht30
- Password: rhnmht30@123
Also, check out the source code of the app, if you are interested. It’s open-source, so contributions of any kind are welcome.