// server.js const express = require('express'); const bodyParser = require('body-parser'); const sqlite3 = require('sqlite3').verbose(); const path = require('path'); const http = require('http'); const { Server } = require('socket.io'); const fs = require('fs'); const app = express(); const server = http.createServer(app); const io = new Server(server); app.use(bodyParser.json()); app.use(express.static(path.join(__dirname, 'public'))); // open (or create) the SQLite database file const db = new sqlite3.Database('positions.db', err => { if (err) { console.error('Could not open DB', err); process.exit(1); } }); // create table if not exists db.run( `CREATE TABLE IF NOT EXISTS positions ( square_id TEXT PRIMARY KEY, fruit TEXT )`, (err) => { if (err) console.error('Could not ensure table', err); } ); // get all saved positions app.get('/api/positions', (req, res) => { db.all('SELECT square_id, fruit FROM positions', (err, rows) => { if (err) return res.status(500).json({ error: err.message }); // convert to an object. should look like this: { "1": "Apple", "2": "Banana", … } const mapping = {}; rows.forEach(r => (mapping[r.square_id] = r.fruit)); res.json(mapping); }); }); // save (or update) a single square’s item app.post('/api/positions', (req, res) => { const { squareId, fruit } = req.body; if (!squareId || typeof fruit !== 'string') { return res.status(400).json({ error: 'squareId and fruit required' }); } db.run( `INSERT INTO positions (square_id, fruit) VALUES (?, ?) ON CONFLICT(square_id) DO UPDATE SET fruit=excluded.fruit`, [squareId, fruit], function (err) { if (err) return res.status(500).json({ error: err.message }); // broadcast update via Socket.io io.emit('update', { squareId, fruit }); res.json({ success: true }); } ); }); // Serve categories and fruits from a JSON file app.get('/api/categories', (req, res) => { const categoriesPath = path.join(__dirname, 'categories.json'); fs.readFile(categoriesPath, 'utf8', (err, data) => { if (err) return res.status(500).json({ error: 'Could not load categories' }); try { const categories = JSON.parse(data); res.json(categories); } catch (e) { res.status(500).json({ error: 'Invalid categories file' }); } }); }); // Add a fruit to a category in categories.json app.post('/api/add-fruit', (req, res) => { const { category, fruit } = req.body; if (!category || !fruit) { return res.status(400).json({ error: 'category and fruit required' }); } const categoriesPath = path.join(__dirname, 'categories.json'); fs.readFile(categoriesPath, 'utf8', (err, data) => { if (err) return res.status(500).json({ error: 'Could not load categories' }); let categories; try { categories = JSON.parse(data); } catch (e) { return res.status(500).json({ error: 'Invalid categories file' }); } const cat = categories.find(c => c.name === category); if (!cat) return res.status(404).json({ error: 'Category not found' }); // Prevent duplicates if (cat.fruits.includes(fruit)) { return res.status(400).json({ error: 'Fruit already exists in category' }); } cat.fruits.push(fruit); fs.writeFile(categoriesPath, JSON.stringify(categories, null, 2), err2 => { if (err2) return res.status(500).json({ error: 'Could not save categories' }); res.json({ success: true }); }); }); }); // Delete a fruit from a category in categories.json app.post('/api/delete-fruit', (req, res) => { const { category, fruit } = req.body; if (!category || !fruit) { return res.status(400).json({ error: 'category and fruit required' }); } const categoriesPath = path.join(__dirname, 'categories.json'); fs.readFile(categoriesPath, 'utf8', (err, data) => { if (err) return res.status(500).json({ error: 'Could not load categories' }); let categories; try { categories = JSON.parse(data); } catch (e) { return res.status(500).json({ error: 'Invalid categories file' }); } const cat = categories.find(c => c.name === category); if (!cat) return res.status(404).json({ error: 'Category not found' }); const idx = cat.fruits.indexOf(fruit); if (idx === -1) return res.status(404).json({ error: 'Fruit not found in category' }); cat.fruits.splice(idx, 1); fs.writeFile(categoriesPath, JSON.stringify(categories, null, 2), err2 => { if (err2) return res.status(500).json({ error: 'Could not save categories' }); res.json({ success: true }); }); }); }); // start server const PORT = process.env.PORT || 3085; server.listen(PORT, () => { console.log(`Listening on http://localhost:${PORT}`); });