Servizio noleggio biciclette città
बनाया गया: 11 जनवरी 2025
बनाया गया: 11 जनवरी 2025
Crafting a bike-sharing system
I’m tasked with designing a municipal bike-sharing system, which includes outlining the technical infrastructure, table normalization, and ensuring robust security measures.
Formulating the approach
I’m thinking through the technical infrastructure, database design, and security measures for the bike-sharing system, ensuring a structured and detailed solution with comprehensive data security.
Thought about bike rental system design per 5 secondi
Di seguito viene proposto un progetto complessivo (in forma discorsiva, ma strutturato), che affronta le varie richieste. Per maggiore chiarezza, l’elaborato è suddiviso nei punti indicati.
Scenario generale
Abbiamo diverse stazioni di noleggio/riconsegna dislocate sul territorio cittadino, ciascuna dotata di:
Rete di comunicazione
In ogni stazione, quindi, il controller locale si occupa di:
Sicurezza e affidabilità
Componenti a livello centrale
Componenti a livello delle stazioni
Software
Si propone un modello concettuale (E/R) e poi il modello logico (relazionale).
Nota: A volte si può separare “Noleggio” e “Riconsegna” in due tabelle, ma spesso è più comodo un’unica tabella con DataOraInizio e DataOraFine.
Di seguito uno schema possibile (campi semplificati):
TABELLA Utente (
ID_Utente INT PRIMARY KEY,
Nome VARCHAR(50) NOT NULL,
Cognome VARCHAR(50) NOT NULL,
Indirizzo VARCHAR(100),
Email VARCHAR(100) UNIQUE,
NumCartaCredito VARCHAR(20),
ProfiloTariffa VARCHAR(20) -- es. standard, premium, etc.
-- altri campi a piacere
);
TABELLA Stazione (
ID_Stazione INT PRIMARY KEY,
Nome VARCHAR(50),
Indirizzo VARCHAR(100),
Latitudine DECIMAL(9,6),
Longitudine DECIMAL(9,6)
-- si possono aggiungere altri campi (es: zone, quartiere, etc.)
);
TABELLA Slot (
ID_Slot INT PRIMARY KEY,
ID_Stazione INT NOT NULL,
StatoSlot VARCHAR(20) -- "libero", "occupato", "guasto", ...
-- vincolo di FK
FOREIGN KEY (ID_Stazione) REFERENCES Stazione(ID_Stazione)
);
TABELLA Bicicletta (
ID_Bicicletta INT PRIMARY KEY,
Modello VARCHAR(50),
Stato VARCHAR(20) -- "disponibile", "noleggiata", "manutenzione", ...
);
TABELLA Noleggio (
ID_Noleggio INT PRIMARY KEY,
ID_Utente INT NOT NULL,
ID_Bicicletta INT NOT NULL,
StazionePrelievo INT NOT NULL,
StazioneRiconsegna INT, -- potrebbe essere NULL finché non riconsegnata
DataOraInizio DATETIME NOT NULL,
DataOraFine DATETIME, -- potrebbe essere NULL finché non riconsegnata
Costo DECIMAL(6,2),
-- vincoli di FK
FOREIGN KEY (ID_Utente) REFERENCES Utente(ID_Utente),
FOREIGN KEY (ID_Bicicletta) REFERENCES Bicicletta(ID_Bicicletta),
FOREIGN KEY (StazionePrelievo) REFERENCES Stazione(ID_Stazione),
FOREIGN KEY (StazioneRiconsegna) REFERENCES Stazione(ID_Stazione)
);
Gestione dello stato degli Slot e delle Biciclette:
Per semplicità, supponiamo di avere un portale con diverse sezioni. Le funzionalità richieste sono:
Mappa delle stazioni: all’accesso, si visualizza una mappa interattiva (Google Maps o altra libreria).
Visualizzare le biciclette attualmente in uso
(a) Verifica disponibilità bici in una data stazione
<!-- pagina stazioni.html --> <!DOCTYPE html> <html> <head> <title>Bike Sharing - Stazioni</title> <!-- include librerie JS per la mappa, CSS, etc. --> </head> <body> <h1>Elenco Stazioni</h1> <!-- Mappa interattiva, omessa per brevità --> <div id="mappa"></div> <!-- Elenco stazioni testuale, da generare dinamicamente --> <table> <tr> <th>Stazione</th> <th>Indirizzo</th> <th>Biciclette Disponibili</th> <th>Slot Liberi</th> </tr> <!-- Ciclo sulle stazioni --> <?php // Esempio di query per ottenere la disponibilità // SELECT s.ID_Stazione, s.Nome, s.Indirizzo, // (SELECT COUNT(*) FROM Slot sl // WHERE sl.ID_Stazione = s.ID_Stazione // AND sl.ID_Bicicletta IS NOT NULL) AS bikeAvailable, // (SELECT COUNT(*) FROM Slot sl // WHERE sl.ID_Stazione = s.ID_Stazione // AND sl.ID_Bicicletta IS NULL) AS slotFree // FROM Stazione s // Esempio di rendering while($row = fetch($result)) { echo "<tr>"; echo "<td>{$row['Nome']}</td>"; echo "<td>{$row['Indirizzo']}</td>"; echo "<td>{$row['bikeAvailable']}</td>"; echo "<td>{$row['slotFree']}</td>"; echo "</tr>"; } ?> </table> </body> </html>
(b) Biciclette in uso
<!-- pagina gestione.html --> <!DOCTYPE html> <html> <head> <title>Gestione - Biciclette in uso</title> </head> <body> <h1>Biciclette Attualmente Noleggiate</h1> <table> <tr> <th>ID Bicicletta</th> <th>Utente</th> <th>Stazione Prelievo</th> <th>Data/Ora Inizio</th> </tr> <?php // Query esemplificativa: // SELECT b.ID_Bicicletta, u.Nome, u.Cognome, st.Nome AS NomeStazione, n.DataOraInizio // FROM Noleggio n // JOIN Bicicletta b ON n.ID_Bicicletta = b.ID_Bicicletta // JOIN Utente u ON n.ID_Utente = u.ID_Utente // JOIN Stazione st ON n.StazionePrelievo = st.ID_Stazione // WHERE n.DataOraFine IS NULL (--> significa che il noleggio è in corso) while($row = fetch($result)) { echo "<tr>"; echo "<td>{$row['ID_Bicicletta']}</td>"; echo "<td>{$row['Nome']} {$row['Cognome']}</td>"; echo "<td>{$row['NomeStazione']}</td>"; echo "<td>{$row['DataOraInizio']}</td>"; echo "</tr>"; } ?> </table> </body> </html>
Specifica: L’utente deve poter richiedere (o ricevere periodicamente) un report con:
Ad esempio, un file PDF/HTML inviato via mail:
Report noleggi - Utente Mario Rossi (ID_Utente=123)
---------------------------------------------------
1) Bicicletta: 25
Stazione prelievo: StazioneCentro
Stazione riconsegna: StazioneStadio
Inizio: 2025-01-10 08:15 Fine: 2025-01-10 09:05
Durata: 00:50
Costo: 2,50 €
2) Bicicletta: 14
...
Costo: ...
---------------------------------------------------
TOTALE speso: ...
Invio periodico automatico
Motivazione: è una soluzione standard e robusta, perché:
Sono richieste due query:
Supponiamo di voler estrarre: ID_Utente, Nome, Cognome. Usando la convenzione che MONTH(DataOraInizio) = MONTH(CURDATE()) indica il mese corrente e YEAR(DataOraInizio) = YEAR(CURDATE()) indica l’anno corrente.
SELECT DISTINCT u.ID_Utente, u.Nome, u.Cognome FROM Noleggio n JOIN Utente u ON n.ID_Utente = u.ID_Utente WHERE n.ID_Bicicletta = :idBici AND MONTH(n.DataOraInizio) = MONTH(CURDATE()) AND YEAR(n.DataOraInizio) = YEAR(CURDATE());
(Al posto di :idBici
mettiamo il codice della bicicletta.)
Definiamo il periodo con due parametri: :dataInizio
, :dataFine
. Vogliamo ID_Stazione o Nome, e il conteggio.
SELECT s.ID_Stazione, s.Nome, COUNT(*) as numeroNoleggi FROM Noleggio n JOIN Stazione s ON n.StazionePrelievo = s.ID_Stazione WHERE n.DataOraInizio BETWEEN :dataInizio AND :dataFine GROUP BY s.ID_Stazione, s.Nome ORDER BY numeroNoleggi DESC LIMIT 1;
In questo modo otteniamo la stazione con più noleggi nel periodo desiderato (tramite LIMIT 1
).
Abbiamo la relazione:
QUADRO(
Cod_Quadro,
Cod_Museo,
Titolo_Quadro,
Nome_Museo,
Citta_Museo,
Prezzo,
DataInizioEsposizione,
DataFineEsposizione
)
1FN (Prima forma normale)
2FN (Seconda forma normale)
(Cod_Quadro)
. A meno che si consideri la coppia (Cod_Quadro, Cod_Museo)
come chiave, ma di solito il codice del quadro (univoco) basta.3FN (Terza forma normale)
Nome_Museo
e Citta_Museo
dipendono da Cod_Museo
, non da Cod_Quadro
.Cod_Museo → Nome_Museo, Citta_Museo
.Cod_Quadro → Prezzo, DataInizioEsposizione, DataFineEsposizione, (Cod_Museo?)
.Schema normalizzato
QUADRO (
Cod_Quadro PK,
Cod_Museo FK,
Titolo_Quadro,
Prezzo,
DataInizioEsposizione,
DataFineEsposizione
)
MUSEO (
Cod_Museo PK,
Nome_Museo,
Citta_Museo
)
Motivazione
Nome_Museo
e Citta_Museo
non vengono duplicati.Nella gestione di un sistema informatico di rete, è fondamentale autenticare gli utenti in modo sicuro. Principali tecniche/protocolli:
Autenticazione basata su password
Autenticazione a due fattori (2FA)
Certificati digitali (autenticazione basata su certificato)
Single Sign-On (SSO) con protocolli quali OAuth2 / OpenID Connect / SAML
Sicurezza di trasporto (TLS/SSL)
Considerazioni finali
La soluzione proposta:
È un progetto che può essere facilmente implementato con tecnologie moderne (REST API, database SQL, front-end JavaScript/HTML5, app mobile). L’importante è assicurare la scalabilità (in caso la città cresca e si aggiungano più stazioni) e la manutenibilità del sistema (aggiornamenti, nuove funzionalità, gestione guasti).