axeOS
The idea
"axeOS" is a comprehensive full-stack software solution developed for an axe throwing company that utilizes projectors to display targets and scores. Divided into server and client components, the software enhances the customer experience by providing lane selection, customizable game modes, personalized player profiles, staff management tools, and more.
Tech stack
axeOS utilizes web sockets in order to quickly transmit information between the clients and the server.
- Server: Runs with a custom Node server. The backend efficiently handles web socket requests and responses, ensuring seamless communication between components.
- Client: Built with Next.js, TypeScript, and Zustand, the frontend offers a responsive and intuitive user interface, facilitating easy navigation and interaction.
var express = require('express')
var path = require('path')
var cookieParser = require('cookie-parser')
var cors = require('cors')
require('./cleanup')()
var targetsRouter = require('./routes/targets')
var app = express()
app.use(cors())
app.use(express.json())
app.use(express.urlencoded({ extended: false }))
app.use(cookieParser())
app.use(express.static(path.join(__dirname, 'public')))
app.use('/targets', targetsRouter)
/** Error responder. */
app.use((error, req, res, next) => {
console.log(new Date(), `(${req.ip} ${req.url})`, '\x1b[31m', error)
res.status(error.status ?? 500).json({ message: error.message })
})
module.exports = app
Features
- Lane Selection: Allows users to choose their desired axe throwing lane.
- Player Profiles: Provides users with the ability to create profiles for their session.
- Custom Targets: Enables users to define and select custom targets for a personalized experience.
- Staff Portal: Equips staff with tools for managing lanes, monitoring activity, and providing assistance.
- Timer: Incorporates a timer feature for regulating game sessions.
- Custom Game Modes: Offers flexibility with customizable game modes to suit different preferences.
- Custom Photo Upload: Enables users to upload their own photos to use as targets, enhancing personalization. Staff members need to approve the photos before they can be selected.
export function useSocketRequest() {
const socket = useSocket()
return async <T>(emitEventName: string, successEventName: string, payload: T) => {
return new Promise<T>((resolve, reject) => {
try {
if (null === socket) throw new Error('The socket has not been initialized.')
if (!socket.connected) throw new Error('There is no connection to the server.')
const handleResolve = (payload: T, timeout: NodeJS.Timeout) => {
resolve(payload)
clearTimeout(timeout)
}
const handleSuccessEvent = (payload: T) => handleResolve(payload, timeout)
const timeout = setTimeout(() => {
socket?.off(successEventName, handleSuccessEvent)
reject('Sorry, there was an issue making sure that request went through.')
}, 3000)
socket.once(successEventName, handleSuccessEvent)
socket.emit(emitEventName, payload)
} catch (error) {
reject('Sorry, there was an issue making sure that request went through. Please try again.')
console.error(error)
}
})
}
}
Implementation
Designed to operate with one central server per location, axeOS synchronizes each axe throwing lane with its corresponding scoreboard and selected target, ensuring consistent and synchronized gameplay experiences across all lanes.
Obstacles
The primary challenge encountered during development was managing the scale of the project. Balancing the addition of new features with the refinement of existing ones required effective communication and meticulous planning to ensure smooth implementation.