Computer Science Code
Computer Science Code
import [Link]
import random
from datetime import datetime, timedelta, date, time
# ============================================================
# DATABASE CONFIGURATION
# ============================================================
HOST = "localhost"
USER = "root"
PASSWORD = "MYSQL" # Enter your MySQL password here
DB_NAME = "RailWay"
# ============================================================
# CONSTANTS - COACH & SEATS
# ============================================================
SEATS_PER_COACH = {
'1st-AC': 18,
'2nd-AC': 46,
'3rd-AC': 64,
'SL': 72
}
COACH_PREFIX = {
'1st-AC': 'A',
'2nd-AC': 'B',
'3rd-AC': 'C',
'SL': 'D'
}
CLASS_NAMES = {
'1st-AC': 'First AC',
'2nd-AC': 'Second AC',
'3rd-AC': 'Third AC',
'SL': 'Sleeper'
}
# ============================================================
# UTILITY FUNCTIONS
# ============================================================
def print_header(title):
print()
print_line("=")
print([Link](80))
1
print_line("=")
def print_subheader(title):
print()
print_line("-", 60)
print([Link](60))
print_line("-", 60)
def press_enter():
input("\n>>> Press ENTER to continue...")
col_widths = []
for i in range(len(headers)):
max_width = len(str(headers[i]))
for row in rows:
if i < len(row):
cell_len = len(str(row[i])) if row[i] is not None else 4
if cell_len > max_width:
max_width = cell_len
col_widths.append(max_width + 2)
header_row = "|"
for i, h in enumerate(headers):
header_row += str(h).center(col_widths[i]) + "|"
print(header_row)
def print_dict_table(data_dict):
rows = [(k, v) for k, v in data_dict.items()]
print_table(["Field", "Value"], rows)
# ============================================================
# VALIDATION FUNCTIONS
# ============================================================
2
def is_junction_station(station_id):
"""Check if a station is a junction"""
conn = connect_with_db()
cursor = [Link]()
[Link]("SELECT station_name FROM stations WHERE station_id = %s", (station_id
result = [Link]()
[Link]()
[Link]()
if result:
station_name = result[0].lower()
return "junction" in station_name
return False
def count_junctions_in_route(train_id):
"""Count number of junction stations in a train route"""
conn = connect_with_db()
cursor = [Link]()
[Link]("""
SELECT COUNT(*) FROM train_routes tr
JOIN stations s ON tr.station_id = s.station_id
WHERE tr.train_id = %s AND LOWER(s.station_name) LIKE '%junction%'
""", (train_id,))
count = [Link]()[0]
[Link]()
[Link]()
return count
def get_junction_count_for_stations(station_ids):
"""Count junctions in a list of station IDs"""
if not station_ids:
return 0
conn = connect_with_db()
cursor = [Link]()
count = [Link]()[0]
[Link]()
[Link]()
return count
def validate_username(username):
if len(username) < 3:
return False, "Username must be at least 3 characters."
if not username[0].isalpha():
3
return False, "Username must start with a letter."
if not [Link]():
return False, "Username can only contain letters and numbers."
return True, ""
def validate_train_name(train_name):
if not train_name:
return False, "Train name cannot be empty."
if not train_name[0].isalpha():
return False, "Train name must start with a letter."
for char in train_name:
if [Link]():
return False, "Train name cannot contain numbers."
return True, ""
def validate_train_number(train_no):
if train_no.isdigit() and len(train_no) == 5:
return True
return False
def get_valid_time_12hr():
while True:
try:
hour = get_valid_integer(" Hour (1-12): ", 1, 12)
minute = get_valid_integer(" Minute (0-59): ", 0, 59)
while True:
ampm = input(" AM or PM: ").strip().upper()
if ampm in ["AM", "PM"]:
break
print(" ERROR: Enter AM or PM only.")
if ampm == "AM":
hour_24 = 0 if hour == 12 else hour
else:
hour_24 = 12 if hour == 12 else hour + 12
return f"{hour_24:02d}:{minute:02d}:00"
except Exception:
print("ERROR: Invalid time. Try again.")
def time_str_to_minutes(time_str):
if time_str is None:
return 0
if isinstance(time_str, timedelta):
return int(time_str.total_seconds() // 60)
parts = str(time_str).split(":")
return int(parts[0]) * 60 + int(parts[1])
5
def convert_to_12hr(time_obj):
if time_obj is None:
return "N/A"
if isinstance(time_obj, timedelta):
total_seconds = int(time_obj.total_seconds())
hours = total_seconds // 3600
minutes = (total_seconds % 3600) // 60
elif isinstance(time_obj, str):
parts = time_obj.split(":")
hours = int(parts[0])
minutes = int(parts[1])
else:
hours = time_obj.hour
minutes = time_obj.minute
if hours == 0:
return f"12:{minutes:02d} AM"
elif hours < 12:
return f"{hours}:{minutes:02d} AM"
elif hours == 12:
return f"12:{minutes:02d} PM"
else:
return f"{hours - 12}:{minutes:02d} PM"
return entered_date.strftime("%Y-%m-%d")
except ValueError:
print("ERROR: Invalid date. Please check values.")
def get_travel_date():
print("\nTravel Date (Press ENTER for today):")
while True:
date_input = input(" Enter date (DD-MM-YYYY) or press ENTER: ").strip()
if not date_input:
return [Link]().strftime("%Y-%m-%d")
6
try:
parts = date_input.split("-")
if len(parts) == 3:
day, month, year = int(parts[0]), int(parts[1]), int(parts[2])
entered_date = date(year, month, day)
today = [Link]()
return entered_date.strftime("%Y-%m-%d")
else:
print("ERROR: Invalid format! Use DD-MM-YYYY")
continue
except ValueError:
print("ERROR: Invalid date! Use DD-MM-YYYY")
continue
def get_yes_no(prompt):
while True:
choice = input(prompt + " (Y/N): ").strip().upper()
if choice in ["Y", "YES"]:
return True
elif choice in ["N", "NO"]:
return False
print("ERROR: Enter Y or N.")
# ============================================================
# DATABASE FUNCTIONS
# ============================================================
def connect_without_db():
return [Link](host=HOST, user=USER, password=PASSWORD)
def connect_with_db():
return [Link](host=HOST, user=USER, password=PASSWORD, database=DB_N
def check_database_exists():
conn = connect_without_db()
cursor = [Link]()
[Link]("SHOW DATABASES LIKE %s", (DB_NAME,))
result = [Link]()
[Link]()
[Link]()
return result is not None
7
def create_database():
conn = connect_without_db()
cursor = [Link]()
[Link](f"CREATE DATABASE {DB_NAME}")
[Link]()
[Link]()
[Link]()
print(f"Database '{DB_NAME}' created!")
def create_tables():
conn = connect_with_db()
cursor = [Link]()
[Link]("""
CREATE TABLE IF NOT EXISTS users (
user_id INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50) NOT NULL UNIQUE,
password VARCHAR(50) NOT NULL,
full_name VARCHAR(100),
security_question VARCHAR(200),
security_answer VARCHAR(100),
role VARCHAR(10) DEFAULT 'user',
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
)
""")
[Link]("""
CREATE TABLE IF NOT EXISTS states (
state_id INT AUTO_INCREMENT PRIMARY KEY,
state_name VARCHAR(100) NOT NULL UNIQUE
)
""")
[Link]("""
CREATE TABLE IF NOT EXISTS cities (
city_id INT AUTO_INCREMENT PRIMARY KEY,
city_name VARCHAR(100) NOT NULL,
state_id INT,
FOREIGN KEY (state_id) REFERENCES states(state_id)
)
""")
[Link]("""
CREATE TABLE IF NOT EXISTS stations (
station_id INT AUTO_INCREMENT PRIMARY KEY,
station_code VARCHAR(10) NOT NULL UNIQUE,
station_name VARCHAR(100) NOT NULL,
city_id INT,
platform_count INT DEFAULT 5,
FOREIGN KEY (city_id) REFERENCES cities(city_id)
)
""")
# Train number + date combination should be unique (same train can run on different d
8
[Link]("""
CREATE TABLE IF NOT EXISTS trains (
train_id INT AUTO_INCREMENT PRIMARY KEY,
train_number VARCHAR(5) NOT NULL,
train_name VARCHAR(100) NOT NULL,
start_station_id INT,
end_station_id INT,
total_distance INT DEFAULT 0,
journey_start_date DATE,
start_platform INT DEFAULT 1,
end_platform INT DEFAULT 1,
train_status VARCHAR(50) DEFAULT 'Yet to Start',
is_active BOOLEAN DEFAULT TRUE,
FOREIGN KEY (start_station_id) REFERENCES stations(station_id),
FOREIGN KEY (end_station_id) REFERENCES stations(station_id),
UNIQUE KEY unique_train_date (train_number, journey_start_date)
)
""")
[Link]("""
CREATE TABLE IF NOT EXISTS train_routes (
route_id INT AUTO_INCREMENT PRIMARY KEY,
train_id INT,
station_id INT,
stop_number INT,
arrival_time TIME,
departure_time TIME,
day_number INT DEFAULT 1,
distance_from_start INT DEFAULT 0,
platform_number INT DEFAULT 1,
halt_minutes INT DEFAULT 2,
FOREIGN KEY (train_id) REFERENCES trains(train_id) ON DELETE CASCADE,
FOREIGN KEY (station_id) REFERENCES stations(station_id)
)
""")
[Link]("""
CREATE TABLE IF NOT EXISTS train_classes (
class_id INT AUTO_INCREMENT PRIMARY KEY,
train_id INT,
class_code VARCHAR(10) NOT NULL,
class_name VARCHAR(50),
num_coaches INT DEFAULT 1,
total_seats INT DEFAULT 0,
available_seats INT DEFAULT 0,
base_fare DECIMAL(10, 2) DEFAULT 0,
FOREIGN KEY (train_id) REFERENCES trains(train_id) ON DELETE CASCADE,
UNIQUE KEY unique_train_class (train_id, class_code)
)
""")
[Link]("""
CREATE TABLE IF NOT EXISTS train_live_status (
status_id INT AUTO_INCREMENT PRIMARY KEY,
9
train_id INT UNIQUE,
current_station_id INT,
current_stop_number INT DEFAULT 1,
delay_minutes INT DEFAULT 0,
last_updated DATETIME DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (train_id) REFERENCES trains(train_id) ON DELETE CASCADE,
FOREIGN KEY (current_station_id) REFERENCES stations(station_id)
)
""")
[Link]()
[Link]()
[Link]()
print("Tables created/verified!")
def insert_default_data():
10
conn = connect_with_db()
cursor = [Link]()
cities_stations = {
'Maharashtra': [
('Mumbai', [('CSMT', 'Chhatrapati Shivaji Terminus'), ('BCT', 'Mumbai Cen
('Pune', [('PUNE', 'Pune Junction')]),
('Nagpur', [('NGP', 'Nagpur Junction')])
],
'Delhi': [
('New Delhi', [('NDLS', 'New Delhi'), ('DLI', 'Old Delhi'), ('NZM', 'Hazr
],
'Karnataka': [
('Bengaluru', [('SBC', 'KSR Bengaluru'), ('YPR', 'Yesvantpur Junction'
('Mysuru', [('MYS', 'Mysuru Junction')])
],
'Tamil Nadu': [
('Chennai', [('MAS', 'Chennai Central'), ('MS', 'Chennai Egmore')]),
('Coimbatore', [('CBE', 'Coimbatore Junction')])
],
'West Bengal': [
('Kolkata', [('HWH', 'Howrah Junction'), ('KOAA', 'Kolkata')])
],
'Gujarat': [
('Ahmedabad', [('ADI', 'Ahmedabad Junction')]),
('Surat', [('ST', 'Surat')]),
('Vadodara', [('BRC', 'Vadodara Junction')])
],
'Rajasthan': [
('Jaipur', [('JP', 'Jaipur Junction')]),
('Jodhpur', [('JU', 'Jodhpur Junction')])
],
'Uttar Pradesh': [
11
('Lucknow', [('LKO', 'Lucknow NR')]),
('Kanpur', [('CNB', 'Kanpur Central')]),
('Varanasi', [('BSB', 'Varanasi Junction')]),
('Agra', [('AGC', 'Agra Cantt')])
],
'Madhya Pradesh': [
('Bhopal', [('BPL', 'Bhopal Junction')]),
('Indore', [('INDB', 'Indore Junction')])
],
'Kerala': [
('Thiruvananthapuram', [('TVC', 'Thiruvananthapuram Central')]),
('Kochi', [('ERS', 'Ernakulam Junction')])
],
'Telangana': [
('Hyderabad', [('SC', 'Secunderabad Junction'), ('HYB', 'Hyderabad Deccan
],
'Andhra Pradesh': [
('Visakhapatnam', [('VSKP', 'Visakhapatnam')]),
('Vijayawada', [('BZA', 'Vijayawada Junction')])
],
'Punjab': [
('Amritsar', [('ASR', 'Amritsar Junction')])
],
'Bihar': [
('Patna', [('PNBE', 'Patna Junction')])
],
'Odisha': [
('Bhubaneswar', [('BBS', 'Bhubaneswar')])
],
'Jharkhand': [
('Ranchi', [('RNC', 'Ranchi')]),
('Jamshedpur', [('TATA', 'Tatanagar Junction')])
],
'Assam': [
('Guwahati', [('GHY', 'Guwahati')])
],
'Haryana': [
('Ambala', [('UMB', 'Ambala Cantt')])
],
'Goa': [
('Madgaon', [('MAO', 'Madgaon Junction')])
]
}
[Link]()
[Link]()
[Link]()
def initialize_database():
print_header("DATABASE INITIALIZATION")
if check_database_exists():
print(f"Database '{DB_NAME}' found.")
else:
print(f"Database '{DB_NAME}' not found.")
if get_yes_no("Create database?"):
create_database()
else:
print("Exiting...")
exit()
create_tables()
insert_default_data()
print("\nDatabase ready!")
press_enter()
# ============================================================
# STATION FUNCTIONS
# ============================================================
def select_state():
conn = connect_with_db()
cursor = [Link]()
[Link]("SELECT state_id, state_name FROM states ORDER BY state_name")
states = [Link]()
[Link]()
[Link]()
if not states:
print("No states available.")
return None
print_subheader("SELECT STATE")
print_table(["ID", "State Name"], states)
while True:
state_id = get_valid_integer("\nEnter State ID: ")
for s in states:
if s[0] == state_id:
return state_id
print("Invalid State ID.")
13
def select_city(state_id):
conn = connect_with_db()
cursor = [Link]()
[Link]("SELECT city_id, city_name FROM cities WHERE state_id = %s ORDER BY ci
cities = [Link]()
[Link]()
[Link]()
if not cities:
print("No cities available.")
return None
print_subheader("SELECT CITY")
print_table(["ID", "City Name"], cities)
while True:
city_id = get_valid_integer("\nEnter City ID: ")
for c in cities:
if c[0] == city_id:
return city_id
print("Invalid City ID.")
def select_station(city_id):
conn = connect_with_db()
cursor = [Link]()
[Link]("SELECT station_id, station_code, station_name FROM stations WHERE cit
stations = [Link]()
[Link]()
[Link]()
if not stations:
print("No stations available.")
return None
print_subheader("SELECT STATION")
print_table(["ID", "Code", "Station Name"], stations)
while True:
station_id = get_valid_integer("\nEnter Station ID: ")
for s in stations:
if s[0] == station_id:
return station_id
print("Invalid Station ID.")
def select_station_full(prompt_text=""):
if prompt_text:
print(f"\n>>> {prompt_text}")
state_id = select_state()
if not state_id:
return None
city_id = select_city(state_id)
if not city_id:
14
return None
return select_station(city_id)
def get_station_info(station_id):
conn = connect_with_db()
cursor = [Link]()
[Link]("""
SELECT s.station_id, s.station_code, s.station_name, c.city_name, st.state_name,
FROM stations s
JOIN cities c ON s.city_id = c.city_id
JOIN states st ON c.state_id = st.state_id
WHERE s.station_id = %s
""", (station_id,))
result = [Link]()
[Link]()
[Link]()
return result
def get_station_name(station_id):
info = get_station_info(station_id)
if info:
return f"{info[2]} ({info[1]})"
return "Unknown"
def get_station_display_name(station_id):
info = get_station_info(station_id)
if info:
return f"{info[2]} ({info[1]}) - {info[3]}, {info[4]}"
return "Unknown Station"
# ============================================================
# USER AUTHENTICATION
# ============================================================
def check_username_exists(username):
conn = connect_with_db()
cursor = [Link]()
[Link]("SELECT user_id FROM users WHERE username = %s", (username,))
result = [Link]()
[Link]()
[Link]()
return result is not None
if role:
[Link]("""
SELECT user_id, username, full_name, role FROM users
WHERE username = %s AND password = %s AND role = %s
""", (username, password, role))
else:
[Link]("""
SELECT user_id, username, full_name, role FROM users
WHERE username = %s AND password = %s
""", (username, password))
result = [Link]()
[Link]()
[Link]()
if result:
return {'user_id': result[0], 'username': result[1], 'full_name': result[2],
return None
def forgot_password(role=None):
print_header("FORGOT PASSWORD")
conn = connect_with_db()
cursor = [Link]()
if role:
[Link]("""
SELECT user_id, full_name, password, security_question, security_answer
FROM users WHERE username = %s AND role = %s
""", (username, role))
else:
[Link]("""
SELECT user_id, full_name, password, security_question, security_answer
FROM users WHERE username = %s
""", (username,))
16
user_data = [Link]()
if not user_data:
print("\nUser not found!")
[Link]()
[Link]()
return False
print(f"\nUser: {full_name}")
print(f"Security Question: {security_question}")
if user_answer.lower() == security_answer.lower():
print("\n✓ Verified!")
print("\n1. View password")
print("2. Reset password")
print("0. Cancel")
if choice == "1":
print(f"\nYour password: {current_password}")
elif choice == "2":
while True:
new_pass = input("New password (min 4 chars): ").strip()
if len(new_pass) < 4:
print("Too short!")
continue
confirm = input("Confirm: ").strip()
if new_pass != confirm:
print("Don't match!")
continue
[Link]()
[Link]()
return True
else:
print("✗ Wrong answer!")
def signup_user():
17
print_header("USER SIGNUP")
while True:
username = input("Username: ").strip()
valid, msg = validate_username(username)
if not valid:
print(f"ERROR: {msg}")
continue
if check_username_exists(username):
print("ERROR: Username exists!")
continue
break
while True:
password = input("Password (min 4 chars): ").strip()
if len(password) < 4:
print("ERROR: Too short!")
continue
confirm = input("Confirm password: ").strip()
if password != confirm:
print("ERROR: Don't match!")
continue
break
print("\nSecurity questions:")
print("1. Mother's maiden name?")
print("2. Pet's name?")
print("3. School name?")
print("4. Favorite movie?")
print("5. Custom")
questions = {
1: "What is your mother's maiden name?",
2: "What is your pet's name?",
3: "What is your school name?",
4: "What is your favorite movie?"
}
print_header("SIGNUP SUCCESSFUL")
print(f"User ID: {user_id}")
print(f"Username: {username}")
18
username = input("Username: ").strip()
password = input("Password: ").strip()
if user:
print(f"\n✓ Welcome, {user['full_name']}!")
return user
else:
print("\n✗ Invalid credentials!")
print("\n1. Try again")
print("2. Forgot Password")
print("0. Back")
if choice == "1":
return login_with_forgot_option(role, role_name)
elif choice == "2":
forgot_password(role)
return None
# ============================================================
# TRAIN STATUS FUNCTIONS
# ============================================================
def calculate_train_status(train_id):
"""Calculate train status based on current date/time with departed logic"""
conn = connect_with_db()
cursor = [Link]()
if not train_info:
[Link]()
[Link]()
return "Unknown", None, None
journey_date = train_info[0]
if journey_date is None:
[Link]("UPDATE trains SET train_status = 'Not Scheduled' WHERE train_id =
[Link]()
[Link]()
[Link]()
return "Not Scheduled", None, None
if isinstance(journey_date, str):
journey_date = [Link](journey_date, "%Y-%m-%d").date()
today = [Link]()
now = [Link]()
19
[Link]("""
SELECT tr.stop_number, tr.arrival_time, tr.departure_time, tr.day_number, [Link]
FROM train_routes tr
JOIN stations s ON tr.station_id = s.station_id
WHERE tr.train_id = %s ORDER BY tr.stop_number
""", (train_id,))
routes = [Link]()
if not routes:
[Link]("UPDATE trains SET train_status = 'No Route' WHERE train_id = %s"
[Link]()
[Link]()
[Link]()
return "No Route", None, None
last_stop = routes[-1]
last_day = last_stop[3]
journey_end_date = journey_date + timedelta(days=last_day - 1)
current_stop = 1
current_station_name = routes[0][4]
status = "Running"
departed_from = None
at_station = None
if at_station:
status = f"At {at_station}"
current_station_name = at_station
elif departed_from:
status = f"Departed from {departed_from}"
current_station_name = departed_from
else:
status = "Running"
if delay > 0:
status += f" (Late by {delay} min)"
elif delay < 0:
status += f" (Early by {abs(delay)} min)"
[Link]("""
UPDATE train_live_status SET current_stop_number = %s, last_updated = NOW()
WHERE train_id = %s
""", (current_stop, train_id))
[Link]()
[Link]()
[Link]()
# ============================================================
# TRAIN DISPLAY FUNCTIONS
# ============================================================
def get_train_by_number(train_number):
"""Get any train by number (returns first match)"""
conn = connect_with_db()
cursor = [Link]()
[Link]("""
SELECT train_id, train_number, train_name, start_station_id, end_station_id,
train_status, is_active, total_distance, journey_start_date, start_platfor
FROM trains WHERE train_number = %s ORDER BY journey_start_date DESC LIMIT 1
""", (train_number,))
result = [Link]()
21
[Link]()
[Link]()
return result
def get_train_by_id(train_id):
conn = connect_with_db()
cursor = [Link]()
[Link]("""
SELECT train_id, train_number, train_name, start_station_id, end_station_id,
train_status, is_active, total_distance, journey_start_date, start_platfor
FROM trains WHERE train_id = %s
""", (train_id,))
result = [Link]()
[Link]()
[Link]()
return result
def show_train_basic(train_id):
train = get_train_by_id(train_id)
if not train:
return
def show_train_routes_only(train_id):
conn = connect_with_db()
cursor = [Link]()
[Link]("""
SELECT tr.stop_number, s.station_code, s.station_name,
tr.arrival_time, tr.departure_time, tr.day_number,
tr.distance_from_start, tr.platform_number, tr.station_id
FROM train_routes tr
JOIN stations s ON tr.station_id = s.station_id
WHERE tr.train_id = %s ORDER BY tr.stop_number
""", (train_id,))
22
routes = [Link]()
# Count junctions
junction_count = count_junctions_in_route(train_id)
[Link]()
[Link]()
if routes:
print_subheader(f"ROUTE DETAILS (Junctions: {junction_count}/{MAX_JUNCTIONS})"
headers = ["Stop", "Code", "Station", "Arrival", "Departure", "Day", "Distance"
rows = []
for r in routes:
arr = convert_to_12hr(r[3]) if r[3] else "Origin"
dep = convert_to_12hr(r[4]) if r[4] else "Terminus"
is_junc = "Yes" if "junction" in r[2].lower() else "No"
[Link]((r[0], r[1], r[2], arr, dep, f"Day {r[5]}", f"{r[6]} km", r[7
print_table(headers, rows)
return routes
def show_train_classes_only(train_id):
conn = connect_with_db()
cursor = [Link]()
[Link]("""
SELECT class_code, class_name, num_coaches, total_seats, available_seats, base_fa
FROM train_classes WHERE train_id = %s ORDER BY class_code
""", (train_id,))
classes = [Link]()
[Link]()
[Link]()
if classes:
print_subheader("CLASS DETAILS")
headers = ["Class", "Name", "Coaches", "Total", "Available", "Booked", "Fare"
rows = []
for c in classes:
booked = c[3] - c[4]
[Link]((c[0], c[1], c[2], c[3], c[4], booked, f"Rs.{c[5]}"))
print_table(headers, rows)
return classes
def show_train_fare_only(train_id):
train = get_train_by_id(train_id)
if train:
print(f"\nTotal Distance: {train[7]} km")
conn = connect_with_db()
cursor = [Link]()
[Link]("""
SELECT class_code, class_name, base_fare
23
FROM train_classes WHERE train_id = %s ORDER BY class_code
""", (train_id,))
classes = [Link]()
[Link]()
[Link]()
if classes:
print_subheader("FARE DETAILS")
print_table(["Class", "Name", "Base Fare"], [(c[0], c[1], f"Rs.{c[2]}") for c
def show_train_coaches_only(train_id):
conn = connect_with_db()
cursor = [Link]()
[Link]("""
SELECT class_code, class_name, num_coaches, total_seats, available_seats
FROM train_classes WHERE train_id = %s ORDER BY class_code
""", (train_id,))
classes = [Link]()
[Link]()
[Link]()
if classes:
print_subheader("COACH DETAILS")
headers = ["Class", "Name", "Coaches", "Seats/Coach", "Total", "Available", "Book
rows = []
for c in classes:
seats_per = SEATS_PER_COACH.get(c[0], 50)
booked = c[3] - c[4]
[Link]((c[0], c[1], c[2], seats_per, c[3], c[4], booked))
print_table(headers, rows)
def view_train_info(train_number):
train = get_train_by_number(train_number)
if not train:
print("\nTrain not found!")
return False
train_id = train[0]
status, current_stop, current_station = calculate_train_status(train_id)
basic_info = {
"Train Number": train[1],
"Train Name": train[2],
"From": get_station_display_name(train[3]),
"To": get_station_display_name(train[4]),
"Journey Date": str(train[8]) if train[8] else "Not Set",
"Distance": f"{train[7]} km",
"Status": status,
"Active": "Yes" if train[6] else "No"
}
24
print_subheader("BASIC INFORMATION")
print_dict_table(basic_info)
show_train_classes_only(train_id)
show_train_routes_only(train_id)
return True
def view_all_trains():
print_header("ALL TRAINS")
conn = connect_with_db()
cursor = [Link]()
[Link]("""
SELECT t.train_id, t.train_number, t.train_name,
s1.station_name, s2.station_name,
t.journey_start_date, t.total_distance, t.is_active, t.train_status
FROM trains t
JOIN stations s1 ON t.start_station_id = s1.station_id
JOIN stations s2 ON t.end_station_id = s2.station_id
ORDER BY t.journey_start_date, t.train_number
""")
trains = [Link]()
[Link]()
[Link]()
if not trains:
print("\nNo trains found!")
return
rows = []
for t in trains:
status = "Active" if t[7] else "Inactive"
date_str = str(t[5]) if t[5] else "Not Set"
# ============================================================
# TRAIN MANAGEMENT FUNCTIONS
# ============================================================
def add_train_manual():
print_header("ADD TRAIN - MANUAL")
print(f"\n*** Note: Maximum {MAX_JUNCTIONS} junction stations allowed per train ***\n
25
while True:
train_name = input("Train Name: ").strip()
valid, msg = validate_train_name(train_name)
if not valid:
print(f"ERROR: {msg}")
continue
if check_train_name_exists(train_name):
print("ERROR: Train name already exists!")
continue
break
while True:
train_number = get_valid_train_number("5-digit Train Number: ")
break
selected_stations.append(start_station_id)
if is_junction_station(start_station_id):
junction_count += 1
print(f" (Junction station - {junction_count}/{MAX_JUNCTIONS} junctions used)"
start_name = get_station_name(start_station_id)
if start_station_id == end_station_id:
print("ERROR: Same as origin station!")
continue
break
selected_stations.append(end_station_id)
26
end_name = get_station_name(end_station_id)
conn = connect_with_db()
cursor = [Link]()
[Link]("""
INSERT INTO trains (train_number, train_name, start_station_id, end_station_id,
total_distance, journey_start_date, start_platform, end_platfo
VALUES (%s, %s, %s, %s, %s, %s, %s, %s)
""", (train_number, train_name, start_station_id, end_station_id,
total_distance, journey_date, start_platform, end_platform))
train_id = [Link]
[Link]("""
27
INSERT INTO train_routes (train_id, station_id, stop_number, departure_time,
day_number, distance_from_start, platform_number)
VALUES (%s, %s, 1, %s, 1, 0, %s)
""", (train_id, start_station_id, start_departure, start_platform))
[Link]("""
INSERT INTO train_routes (train_id, station_id, stop_number, arrival_time,
day_number, distance_from_start, platform_number)
VALUES (%s, %s, 2, %s, %s, %s, %s)
""", (train_id, end_station_id, end_arrival, end_day, total_distance, end_platform))
[Link]("""
INSERT INTO train_live_status (train_id, current_station_id, current_stop_number)
VALUES (%s, %s, 1)
""", (train_id, start_station_id))
[Link]()
if num_coaches > 0:
total_seats = num_coaches * seats_per
base_fare = get_valid_float(f"Base fare for {cls} (Rs.): ", 0)
[Link]("""
INSERT INTO train_classes (train_id, class_code, class_name, num_coaches,
total_seats, available_seats, base_fare)
VALUES (%s, %s, %s, %s, %s, %s, %s)
""", (train_id, cls, CLASS_NAMES[cls], num_coaches, total_seats, total_seats,
[Link]()
[Link]()
[Link]()
print_header("TRAIN ADDED!")
print(f"Number: {train_number}")
print(f"Name: {train_name}")
print(f"Date: {journey_date}")
print(f"Route: {start_name} → {end_name}")
print(f"Junctions: {junction_count}/{MAX_JUNCTIONS}")
def add_train_automatic():
print_header("ADD TRAIN - AUTOMATIC")
conn = connect_with_db()
cursor = [Link]()
28
journey_date = ([Link]() + timedelta(days=[Link](1, 30))).strftime("%Y-%m
while True:
train_name = f"{[Link](prefixes)} {[Link](suffixes)}"
if not check_train_name_exists(train_name):
break
train_name = f"{[Link](prefixes)} {[Link](suffixes)} {[Link]
if not check_train_name_exists(train_name):
break
if len(all_stations_data) < 6:
print("Not enough stations!")
[Link]()
[Link]()
return
for s in all_stations_data:
if "junction" in s[1].lower():
junction_stations.append(s[0])
else:
non_junction_stations.append(s[0])
if len(selected_stations) < 6:
print("Not enough valid stations!")
[Link]()
[Link]()
return
start_station_id = selected_stations[0]
end_station_id = selected_stations[1]
mid_stations = selected_stations[2:min(8, len(selected_stations))]
num_mid_stations = min(len(mid_stations), 6)
mid_stations = mid_stations[:num_mid_stations]
end_hour = end_minutes // 60
end_min = end_minutes % 60
end_arrival = f"{end_hour:02d}:{end_min:02d}:00"
start_platform = [Link](1, 8)
end_platform = [Link](1, 8)
[Link]("""
INSERT INTO trains (train_number, train_name, start_station_id, end_station_id,
total_distance, journey_start_date, start_platform, end_platfo
VALUES (%s, %s, %s, %s, %s, %s, %s, %s)
""", (train_number, train_name, start_station_id, end_station_id,
total_distance, journey_date, start_platform, end_platform))
train_id = [Link]
total_stops = num_mid_stations + 2
30
mid_distances = []
for i in range(num_mid_stations):
min_dist = (i + 1) * (total_distance // (num_mid_stations + 2))
max_dist = (i + 2) * (total_distance // (num_mid_stations + 2))
mid_distances.append([Link](min_dist, max_dist))
[Link]("""
INSERT INTO train_routes (train_id, station_id, stop_number, arrival_time, depart
day_number, distance_from_start, platform_number, halt_m
VALUES (%s, %s, 1, NULL, %s, 1, 0, %s, 0)
""", (train_id, start_station_id, start_departure, start_platform))
current_minutes = start_dep_minutes
current_day = 1
arr_hour = current_minutes // 60
arr_min = current_minutes % 60
arrival_time = f"{arr_hour:02d}:{arr_min:02d}:00"
dep_hour = current_minutes // 60
dep_min = current_minutes % 60
departure_time = f"{dep_hour:02d}:{dep_min:02d}:00"
mid_platform = [Link](1, 8)
mid_distance = mid_distances[i]
[Link]("""
INSERT INTO train_routes (train_id, station_id, stop_number, arrival_time, de
day_number, distance_from_start, platform_number, ha
VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s)
""", (train_id, mid_station_id, stop_number, arrival_time, departure_time,
current_day, mid_distance, mid_platform, halt_time))
[Link]("""
INSERT INTO train_routes (train_id, station_id, stop_number, arrival_time, depart
31
day_number, distance_from_start, platform_number, halt_m
VALUES (%s, %s, %s, %s, NULL, %s, %s, %s, 0)
""", (train_id, end_station_id, num_mid_stations + 2, end_arrival, end_day, total_dis
[Link]("""
INSERT INTO train_live_status (train_id, current_station_id, current_stop_number)
VALUES (%s, %s, 1)
""", (train_id, start_station_id))
fare_ranges = {
'1st-AC': (1500, 4000),
'2nd-AC': (800, 2500),
'3rd-AC': (500, 1500),
'SL': (200, 700)
}
[Link]("""
INSERT INTO train_classes (train_id, class_code, class_name, num_coaches,
total_seats, available_seats, base_fare)
VALUES (%s, %s, %s, %s, %s, %s, %s)
""", (train_id, cls, CLASS_NAMES[cls], num_coaches, total_seats, total_seats, bas
[Link]()
print_header("TRAIN CREATED!")
print(f"\nNumber: {train_number}")
print(f"Name: {train_name}")
print(f"Date: {journey_date}")
print(f"Distance: {total_distance} km")
print(f"Stops: {total_stops}")
print(f"Junctions: {actual_junction_count}/{MAX_JUNCTIONS}")
print_subheader("ROUTE")
[Link]("""
SELECT tr.stop_number, s.station_code, s.station_name,
tr.arrival_time, tr.departure_time, tr.day_number, tr.distance_from_start
FROM train_routes tr
JOIN stations s ON tr.station_id = s.station_id
WHERE tr.train_id = %s ORDER BY tr.stop_number
""", (train_id,))
routes = [Link]()
rows = []
for r in routes:
arr = convert_to_12hr(r[3]) if r[3] else "Origin"
dep = convert_to_12hr(r[4]) if r[4] else "Terminus"
32
is_junc = "Yes" if "junction" in r[2].lower() else "No"
[Link]((r[0], r[1], r[2], arr, dep, f"Day {r[5]}", f"{r[6]} km", is_junc))
[Link]()
[Link]()
def copy_train():
print_header("COPY EXISTING TRAIN")
if choice == "1":
train_number = get_valid_train_number()
source_train = get_train_by_number(train_number)
if not source_train:
print("Not found!")
return
source_train_id = source_train[0]
elif choice == "2":
print("\n--- SELECT START STATION ---")
start_station_id = select_station_full()
if not start_station_id:
return
conn = connect_with_db()
cursor = [Link]()
[Link]("""
SELECT train_id, train_number, train_name, journey_start_date
FROM trains WHERE start_station_id = %s AND end_station_id = %s
""", (start_station_id, end_station_id))
trains = [Link]()
[Link]()
[Link]()
if not trains:
print("No trains found!")
return
print_subheader("MATCHING TRAINS")
print_table(["ID", "Number", "Name", "Date"], trains)
source_train_name = source_train[2]
source_train_number = source_train[1]
source_train_date = source_train[8]
print_subheader("SOURCE TRAIN")
view_train_info(source_train[1])
if name_choice == "2":
while True:
new_name = input("New train name: ").strip()
valid, msg = validate_train_name(new_name)
if not valid:
print(f"ERROR: {msg}")
continue
if check_train_name_exists(new_name):
print("ERROR: Name exists!")
continue
break
else:
new_name = source_train_name
if num_choice == "3":
while True:
new_number = get_valid_train_number("Enter 5-digit train number: ")
break
elif num_choice == "1":
new_number = source_train_number
else:
34
while True:
new_number = str([Link](10000, 99999))
# Will validate with date later
break
if existing_dates:
print(f"\nExisting dates for train {new_number}:")
for d in existing_dates:
print(f" - {d}")
while True:
new_date = get_valid_date("Enter NEW journey date")
if check_train_number_date_exists(new_number, new_date):
print(f"ERROR: Train {new_number} already exists for {new_date}!")
continue
break
conn = connect_with_db()
cursor = [Link]()
[Link]("""
INSERT INTO trains (train_number, train_name, start_station_id, end_station_id,
total_distance, journey_start_date, start_platform, end_platfo
SELECT %s, %s, start_station_id, end_station_id,
total_distance, %s, start_platform, end_platform
FROM trains WHERE train_id = %s
""", (new_number, new_name, new_date, source_train_id))
new_train_id = [Link]
[Link]("""
INSERT INTO train_routes (train_id, station_id, stop_number, arrival_time, depart
35
day_number, distance_from_start, platform_number, halt_m
SELECT %s, station_id, stop_number, arrival_time, departure_time,
day_number, distance_from_start, platform_number, halt_minutes
FROM train_routes WHERE train_id = %s
""", (new_train_id, source_train_id))
[Link]("""
INSERT INTO train_classes (train_id, class_code, class_name, num_coaches,
total_seats, available_seats, base_fare)
SELECT %s, class_code, class_name, num_coaches,
total_seats, total_seats, base_fare
FROM train_classes WHERE train_id = %s
""", (new_train_id, source_train_id))
[Link]("""
INSERT INTO train_live_status (train_id, current_station_id, current_stop_number)
SELECT %s, current_station_id, 1 FROM train_live_status WHERE train_id = %s
""", (new_train_id, source_train_id))
[Link]()
if get_yes_no("\nModify details?"):
while True:
print("\n1. Edit timings")
print("2. Edit fare")
print("3. Edit coaches")
print("4. Add mid station")
print("5. Delete mid station")
print("0. Done")
if mod == "1":
edit_train_timings(new_train_id)
elif mod == "2":
edit_train_fare_by_id(new_train_id)
elif mod == "3":
edit_train_coaches(new_train_id)
elif mod == "4":
add_mid_station(new_train_id)
elif mod == "5":
delete_mid_station(new_train_id)
elif mod == "0":
break
[Link]()
[Link]()
print_header("TRAIN COPIED!")
print(f"Number: {new_number}")
print(f"Name: {new_name}")
print(f"Date: {new_date}")
def add_mid_station(train_id):
36
conn = connect_with_db()
cursor = [Link]()
[Link]("""
SELECT tr.stop_number, s.station_code, s.station_name,
tr.arrival_time, tr.departure_time, tr.day_number,
tr.station_id, tr.distance_from_start
FROM train_routes tr
JOIN stations s ON tr.station_id = s.station_id
WHERE tr.train_id = %s ORDER BY tr.stop_number
""", (train_id,))
routes = [Link]()
if len(routes) < 2:
print("Route incomplete!")
[Link]()
[Link]()
return
show_train_basic(train_id)
print(f"\n*** Junctions: {current_junction_count}/{MAX_JUNCTIONS} ***")
print_subheader("CURRENT ROUTE")
rows = []
for r in routes:
arr = convert_to_12hr(r[3]) if r[3] else "Origin"
dep = convert_to_12hr(r[4]) if r[4] else "Terminus"
is_junc = "Yes" if "junction" in r[2].lower() else "No"
[Link]((r[0], r[1], r[2], arr, dep, f"Day {r[5]}", f"{r[7]} km", is_junc))
print_table(["Stop", "Code", "Station", "Arrival", "Departure", "Day", "Distance"
after_route = None
for r in routes:
if r[1].upper() == after_code:
after_route = r
break
if not after_route:
print("Not found!")
[Link]()
[Link]()
return
if after_route[0] == routes[-1][0]:
print("Cannot add after terminus!")
[Link]()
[Link]()
return
37
next_route = None
for r in routes:
if r[0] == after_route[0] + 1:
next_route = r
break
while True:
new_station_id = select_station_full()
if not new_station_id:
[Link]()
[Link]()
return
if check_station_in_route(train_id, new_station_id):
print("ERROR: Station already in route!")
continue
break
new_station_name = get_station_name(new_station_id)
while True:
print("\nArrival time:")
arrival_time = get_valid_time_12hr()
arr_min = time_str_to_minutes(arrival_time)
print("Departure time:")
38
departure_time = get_valid_time_12hr()
dep_min = time_str_to_minutes(departure_time)
valid = True
if valid:
break
while True:
distance = get_valid_integer(f"Distance ({after_distance+1} to {next_distance-1}
[Link]("""
UPDATE train_routes SET stop_number = stop_number + 1
WHERE train_id = %s AND stop_number > %s
""", (train_id, after_route[0]))
[Link]("""
INSERT INTO train_routes (train_id, station_id, stop_number, arrival_time, depart
day_number, distance_from_start, platform_number)
VALUES (%s, %s, %s, %s, %s, %s, %s, %s)
""", (train_id, new_station_id, after_route[0] + 1, arrival_time, departure_time,
day_number, distance, platform))
[Link]()
[Link]()
[Link]()
39
print(f"\n✓ {new_station_name} added!")
print(f" Junctions: {new_junction_count}/{MAX_JUNCTIONS}")
def delete_mid_station(train_id):
conn = connect_with_db()
cursor = [Link]()
[Link]("""
SELECT tr.stop_number, s.station_code, s.station_name
FROM train_routes tr
JOIN stations s ON tr.station_id = s.station_id
WHERE tr.train_id = %s ORDER BY tr.stop_number
""", (train_id,))
routes = [Link]()
if len(routes) <= 2:
print("Cannot delete - only 2 stations!")
[Link]()
[Link]()
return
show_train_basic(train_id)
print_subheader("CURRENT ROUTE")
print_table(["Stop", "Code", "Station"], routes)
del_stop = None
for r in routes:
if r[1].upper() == del_code:
del_stop = r[0]
break
if not del_stop:
print("Not found!")
[Link]()
[Link]()
return
if get_yes_no(f"Delete {del_code}?"):
[Link]("DELETE FROM train_routes WHERE train_id = %s AND stop_number = %s
(train_id, del_stop))
[Link]()
print("✓ Deleted!")
[Link]()
[Link]()
def edit_train_timings(train_id):
conn = connect_with_db()
cursor = [Link]()
[Link]("""
SELECT tr.route_id, tr.stop_number, s.station_name, s.station_code,
tr.arrival_time, tr.departure_time, tr.day_number
FROM train_routes tr
JOIN stations s ON tr.station_id = s.station_id
WHERE tr.train_id = %s ORDER BY tr.stop_number
""", (train_id,))
routes = [Link]()
if not routes:
print("No routes!")
[Link]()
[Link]()
return
show_train_basic(train_id)
print_subheader("CURRENT TIMINGS")
rows = []
for r in routes:
arr = convert_to_12hr(r[4]) if r[4] else "Origin"
dep = convert_to_12hr(r[5]) if r[5] else "Terminus"
[Link]((r[1], r[2], r[3], arr, dep, f"Day {r[6]}"))
print_table(["Stop", "Station", "Code", "Arrival", "Departure", "Day"], rows)
selected = None
for r in routes:
if r[1] == stop_no:
selected = r
break
if not selected:
print("Invalid!")
[Link]()
[Link]()
return
if stop_no > 1:
print("\nNew Arrival:")
41
new_arrival = get_valid_time_12hr()
[Link]("UPDATE train_routes SET arrival_time = %s WHERE route_id = %s"
(new_arrival, selected[0]))
[Link]()
[Link]()
[Link]()
print("✓ Updated!")
def edit_train_fare_by_id(train_id):
conn = connect_with_db()
cursor = [Link]()
[Link]("""
SELECT class_code, class_name, base_fare FROM train_classes
WHERE train_id = %s ORDER BY class_code
""", (train_id,))
classes = [Link]()
if not classes:
print("No classes!")
[Link]()
[Link]()
return
show_train_basic(train_id)
print_subheader("FARE DETAILS")
print_table(["Class", "Name", "Fare"], [(c[0], c[1], f"Rs.{c[2]}") for c in classes])
current = None
for c in classes:
if c[0].upper() == class_code.upper():
current = c
class_code = c[0]
break
if not current:
print("Invalid!")
[Link]()
[Link]()
return
42
print(f"Current: Rs.{current[2]}")
new_fare = get_valid_float("New fare: Rs.", 0)
def edit_train_coaches(train_id):
conn = connect_with_db()
cursor = [Link]()
[Link]("""
SELECT class_code, class_name, num_coaches, total_seats, available_seats
FROM train_classes WHERE train_id = %s ORDER BY class_code
""", (train_id,))
classes = [Link]()
if not classes:
print("No classes!")
[Link]()
[Link]()
return
show_train_basic(train_id)
print_subheader("COACH DETAILS")
rows = []
for c in classes:
seats_per = SEATS_PER_COACH.get(c[0], 50)
booked = c[3] - c[4]
[Link]((c[0], c[1], c[2], seats_per, c[3], c[4], booked))
print_table(["Class", "Name", "Coaches", "Seats/Coach", "Total", "Available", "Booked
current = None
for c in classes:
if c[0].upper() == class_code.upper():
current = c
class_code = c[0]
break
if not current:
print("Invalid!")
[Link]()
[Link]()
return
43
print(f"\nCurrent: {current[2]} coaches, {booked} booked")
[Link]("""
UPDATE train_classes SET num_coaches = %s, total_seats = %s, available_seats = %s
WHERE train_id = %s AND class_code = %s
""", (new_coaches, new_total, new_available, train_id, class_code))
[Link]()
[Link]()
[Link]()
print(f"✓ Updated!")
def edit_train_routes():
print_header("EDIT TRAIN ROUTES")
train_number = get_valid_train_number()
train = get_train_by_number(train_number)
if not train:
print("Not found!")
return
train_id = train[0]
while True:
show_train_basic(train_id)
show_train_routes_only(train_id)
if choice == "1":
add_mid_station(train_id)
elif choice == "2":
delete_mid_station(train_id)
elif choice == "3":
edit_train_timings(train_id)
elif choice == "0":
break
press_enter()
def edit_train_fare():
print_header("EDIT TRAIN FARE")
44
train_number = get_valid_train_number()
train = get_train_by_number(train_number)
if not train:
print("Not found!")
return
edit_train_fare_by_id(train[0])
def edit_train_seats():
print_header("EDIT TRAIN COACHES")
train_number = get_valid_train_number()
train = get_train_by_number(train_number)
if not train:
print("Not found!")
return
edit_train_coaches(train[0])
# ============================================================
# BOOKING FUNCTIONS
# ============================================================
def generate_pnr():
conn = connect_with_db()
cursor = [Link]()
max_attempts = 100
attempts = 0
def get_passenger_details(num_passengers):
passengers = []
for i in range(num_passengers):
print(f"\n--- Passenger {i + 1} ---")
45
name = input(" Name: ").strip()
while not name:
print(" Name cannot be empty!")
name = input(" Name: ").strip()
while True:
gender = input(" Gender (M/F/O): ").strip().upper()
if gender in ['M', 'F', 'O']:
gender_full = {'M': 'Male', 'F': 'Female', 'O': 'Other'}[gender]
break
print(" Enter M/F/O!")
[Link]({
'name': name,
'age': age,
'gender': gender_full
})
return passengers
[Link]("""
SELECT num_coaches, total_seats, available_seats FROM train_classes
WHERE train_id = %s AND class_code = %s
""", (train_id, class_code))
class_info = [Link]()
[Link]()
[Link]()
if not class_info:
return "A1", [str(i) for i in range(1, num_seats + 1)]
print("\nAvailable stations:")
for i, r in enumerate(routes[:-1]): # Exclude last station
arr = convert_to_12hr(r[3]) if r[3] else "Origin"
dep = convert_to_12hr(r[4]) if r[4] else "N/A"
print(f" {r[0]}. {r[2]} ({r[1]}) - Dep: {dep}")
while True:
stop_no = get_valid_integer("\nBoarding station (stop number): ", 1, len(routes)
for r in routes[:-1]: # Only check in non-last stations
if r[0] == stop_no:
return r[8], r # station_id and route info
print("Invalid! Cannot board at terminus station.")
print("\nAvailable stations:")
available_destinations = []
for r in routes:
if r[0] > from_stop:
arr = convert_to_12hr(r[3]) if r[3] else "N/A"
print(f" {r[0]}. {r[2]} ({r[1]}) - Arr: {arr}")
available_destinations.append(r)
if not available_destinations:
print("No destination stations available!")
return None, None
while True:
stop_no = get_valid_integer("\nDestination station (stop number): ", from_stop +
for r in available_destinations:
if r[0] == stop_no:
return r[8], r # station_id and route info
print("Invalid!")
47
# Get train info
[Link]("""
SELECT journey_start_date, (SELECT MAX(day_number) FROM train_routes WHERE train_
FROM trains WHERE train_id = %s AND is_active = TRUE
""", (train_id, train_id))
train = [Link]()
if not train:
[Link]()
[Link]()
return False, "Train not active or not found"
start_date = train[0]
max_day = train[1]
if dep_time:
# Calculate actual departure date from boarding station
actual_dep_date = start_date + timedelta(days=day_number - 1)
today = [Link]()
48
# Check if train has departed (only if departure is today or in the past)
if today > actual_dep_date:
[Link]()
[Link]()
return False, "Train already departed"
[Link]()
[Link]()
return True, "Available"
def book_ticket_by_train_no(user=None):
print_header("BOOK BY TRAIN NUMBER")
train_number = get_valid_train_number()
if not train:
# Check if train exists at all
any_train = get_train_by_number(train_number)
if any_train:
print(f"\nTrain {train_number} does not run on {journey_date}.")
print(f"Train runs on: {any_train[8]}")
else:
print("\nTrain not found!")
return
if not train[6]:
print("Train not active!")
return
train_id = train[0]
[Link]("""
SELECT tr.stop_number, s.station_code, s.station_name,
tr.arrival_time, tr.departure_time, tr.day_number,
tr.distance_from_start, tr.platform_number, tr.station_id
FROM train_routes tr
JOIN stations s ON tr.station_id = s.station_id
WHERE tr.train_id = %s ORDER BY tr.stop_number
""", (train_id,))
routes = [Link]()
if len(routes) < 2:
print("Invalid route!")
[Link]()
[Link]()
return
if not get_yes_no("\nProceed?"):
[Link]()
[Link]()
return
if not classes:
print("No seats!")
[Link]()
[Link]()
return
50
print_subheader("AVAILABLE CLASSES")
print_table(["Class", "Name", "Available", "Fare"],
[(c[0], c[1], c[2], f"Rs.{c[3]}") for c in classes])
while True:
class_code = input("\nClass: ").strip().upper()
selected = None
for c in classes:
if c[0].upper() == class_code.upper():
selected = c
class_code = c[0]
break
if selected:
break
print("Invalid!")
# Calculate fare per passenger (base fare is for entire journey, no distance-based di
fare_per_passenger = float(selected[3])
total_fare = fare_per_passenger * num_seats
# Get platform
platform = from_route[7]
pnr = generate_pnr()
print_header("BOOKING SUMMARY")
details = {
"PNR": pnr,
"Train": f"{train[1]} - {train[2]}",
"Class": f"{class_code} ({selected[1]})",
"Date": journey_date,
"Passengers": passenger_details,
"Total Seats": num_seats,
"From": f"{from_route[2]} ({from_route[1]})",
"To": f"{to_route[2]} ({to_route[1]})",
51
"Distance": f"{travel_distance} km",
"Platform": platform,
"Coach": coach_name,
"Seat(s)": ", ".join(seat_numbers),
"Fare per Passenger": f"Rs.{fare_per_passenger:.2f}",
"Total Fare": f"Rs.{total_fare:.2f}"
}
print_dict_table(details)
if not get_yes_no("\nConfirm?"):
print("Cancelled!")
[Link]()
[Link]()
return
# Insert booking
[Link]("""
INSERT INTO bookings (pnr_number, user_id, train_id, class_code, from_station_id,
journey_date, total_seats, total_fare, platform_number, coac
VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, 'Confirmed')
""", (pnr, user_id, train_id, class_code, from_station_id, to_station_id, journey_dat
num_seats, total_fare, platform, coach_name))
booking_id = [Link]
# Insert passengers
for i, passenger in enumerate(passengers):
[Link]("""
INSERT INTO booking_passengers (booking_id, passenger_name, passenger_age, pa
VALUES (%s, %s, %s, %s, %s, 'Confirmed')
""", (booking_id, passenger['name'], passenger['age'], passenger['gender'], seat_
[Link]()
[Link]()
[Link]()
print_header("BOOKING CONFIRMED!")
print(f"\n PNR: {pnr}")
print(" Save this PNR!")
def search_train_and_book(user=None):
print_header("SEARCH & BOOK TRAIN")
if from_station == to_station:
print("Same station!")
return
conn = connect_with_db()
cursor = [Link]()
all_trains = [Link]()
for t in all_trains:
train_date = t[5]
if isinstance(train_date, str):
train_date = [Link](train_date, "%Y-%m-%d").date()
dep_day = t[6]
dep_time = t[3]
53
# Check if train has departed
if today > actual_dep_date:
continue
available_trains.append(t)
if not available_trains:
print(f"\nNo available trains for {journey_date}!")
[Link]()
[Link]()
return
rows = []
for t in available_trains:
dep = convert_to_12hr(t[3]) if t[3] else "N/A"
arr = convert_to_12hr(t[4]) if t[4] else "N/A"
distance = t[11] - t[10] # to_dist - from_dist
[Link]("""
SELECT class_code, available_seats FROM train_classes
WHERE train_id = %s AND available_seats > 0
""", (t[0],))
seats_info = [Link]()
seats_str = ", ".join([f"{s[0]}:{s[1]}" for s in seats_info]) if seats_info else
# Select train
print("\n" + "-" * 50)
train_no = get_valid_train_number("Enter train number to book: ")
selected_train = None
for t in available_trains:
54
if t[1] == train_no:
selected_train = t
break
if not selected_train:
print("Invalid train!")
[Link]()
[Link]()
return
train_id = selected_train[0]
travel_distance = selected_train[11] - selected_train[10]
if not classes:
print("No seats!")
[Link]()
[Link]()
return
print_subheader("AVAILABLE CLASSES")
print_table(["Class", "Name", "Available", "Fare"],
[(c[0], c[1], c[2], f"Rs.{c[3]}") for c in classes])
while True:
class_code = input("\nClass: ").strip().upper()
selected = None
for c in classes:
if c[0].upper() == class_code.upper():
selected = c
class_code = c[0]
break
if selected:
break
print("Invalid!")
# Calculate fare per passenger (base fare is for entire journey, no distance-based di
fare_per_passenger = float(selected[3])
total_fare = fare_per_passenger * num_seats
55
# Get coach and seats
coach_name, seat_numbers = assign_coach_and_seats(train_id, class_code, num_seats)
# Get platform
[Link]("""
SELECT platform_number FROM train_routes
WHERE train_id = %s AND station_id = %s
""", (train_id, from_station))
platform_row = [Link]()
platform = platform_row[0] if platform_row else 1
pnr = generate_pnr()
print_header("BOOKING SUMMARY")
train = get_train_by_id(train_id)
details = {
"PNR": pnr,
"Train": f"{train[1]} - {train[2]}",
"Class": f"{class_code} ({selected[1]})",
"Date": journey_date,
"Passengers": passenger_details,
"Total Seats": num_seats,
"From": get_station_name(from_station),
"To": get_station_name(to_station),
"Distance": f"{travel_distance} km",
"Platform": platform,
"Coach": coach_name,
"Seat(s)": ", ".join(seat_numbers),
"Fare per Passenger": f"Rs.{fare_per_passenger:.2f}",
"Total Fare": f"Rs.{total_fare:.2f}"
}
print_dict_table(details)
if not get_yes_no("\nConfirm?"):
print("Cancelled!")
[Link]()
[Link]()
return
[Link]("""
INSERT INTO bookings (pnr_number, user_id, train_id, class_code, from_station_id,
journey_date, total_seats, total_fare, platform_number, coac
VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, 'Confirmed')
""", (pnr, user_id, train_id, class_code, from_station, to_station, journey_date,
num_seats, total_fare, platform, coach_name))
booking_id = [Link]
[Link]("""
UPDATE train_classes SET available_seats = available_seats - %s
WHERE train_id = %s AND class_code = %s
""", (num_seats, train_id, class_code))
[Link]()
[Link]()
[Link]()
print_header("BOOKING CONFIRMED!")
print(f"\n PNR: {pnr}")
print(" Save this PNR!")
def cancel_booking(user=None):
print_header("CANCEL BOOKING")
conn = connect_with_db()
cursor = [Link]()
booking = [Link]()
if not booking:
print("Booking not found!")
57
[Link]()
[Link]()
return
if booking[7] == 'Cancelled':
print("Booking already cancelled!")
[Link]()
[Link]()
return
booking_id = booking[0]
# Get passengers
[Link]("""
SELECT passenger_id, passenger_name, passenger_age, passenger_gender, seat_number
FROM booking_passengers WHERE booking_id = %s
""", (booking_id,))
passengers = [Link]()
print_subheader("BOOKING DETAILS")
print(f"PNR: {booking[1]}")
print(f"Train: {booking[2]} - {booking[3]}")
print(f"Class: {booking[4]}")
print(f"Date: {booking[6]}")
print(f"From: {booking[9]}")
print(f"To: {booking[10]}")
print(f"Status: {booking[7]}")
print_subheader("PASSENGERS")
rows = []
for i, p in enumerate(passengers, 1):
[Link]((i, p[1], p[2], p[3], p[4], p[5]))
print_table(["#", "Name", "Age", "Gender", "Seat", "Status"], rows)
if len(confirmed_passengers) == 0:
print("\nNo confirmed passengers to cancel!")
[Link]()
[Link]()
return
# Cancellation options
print("\n--- CANCELLATION OPTIONS ---")
print("1. Cancel entire booking (all passengers)")
if len(confirmed_passengers) > 1:
print("2. Cancel specific passenger(s)")
print("0. Back")
if choice == "0":
[Link]()
[Link]()
58
return
if choice == "1":
# Cancel entire booking
if get_yes_no("\nCancel ENTIRE booking?"):
[Link]("UPDATE bookings SET booking_status = 'Cancelled' WHERE bookin
[Link]("UPDATE booking_passengers SET status = 'Cancelled' WHERE book
# Restore seats
[Link]("""
UPDATE train_classes SET available_seats = available_seats + %s
WHERE train_id = %s AND class_code = %s
""", (len(confirmed_passengers), booking[8], booking[4]))
[Link]()
print("\n✓ Entire booking cancelled!")
try:
cancel_nums = [int([Link]()) for x in cancel_input.split(",")]
except:
print("Invalid input!")
[Link]()
[Link]()
return
passengers_to_cancel = []
for num in cancel_nums:
if 1 <= num <= len(passengers):
p = passengers[num - 1]
if p[5] == 'Confirmed':
passengers_to_cancel.append(p)
if not passengers_to_cancel:
print("No valid passengers selected!")
[Link]()
[Link]()
return
print("\nPassengers to cancel:")
for p in passengers_to_cancel:
print(f" - {p[1]} (Seat: {p[4]})")
if get_yes_no("\nConfirm cancellation?"):
for p in passengers_to_cancel:
[Link]("UPDATE booking_passengers SET status = 'Cancelled' WHERE
# Restore seats
59
[Link]("""
UPDATE train_classes SET available_seats = available_seats + %s
WHERE train_id = %s AND class_code = %s
""", (len(passengers_to_cancel), booking[8], booking[4]))
# Update booking
[Link]("""
UPDATE bookings SET total_seats = total_seats - %s
WHERE booking_id = %s
""", (len(passengers_to_cancel), booking_id))
if remaining == 0:
[Link]("UPDATE bookings SET booking_status = 'Cancelled' WHERE bo
else:
[Link]("UPDATE bookings SET booking_status = 'Partial' WHERE book
[Link]()
print(f"\n✓ {len(passengers_to_cancel)} passenger(s) cancelled!")
[Link]()
[Link]()
def my_bookings(user):
print_header("MY BOOKINGS")
conn = connect_with_db()
cursor = [Link]()
[Link]("""
SELECT b.booking_id, b.pnr_number, t.train_number, t.train_name, b.class_code,
b.journey_date, b.total_seats, b.total_fare,
s1.station_name, s2.station_name, b.platform_number,
b.coach_name, b.booking_status
FROM bookings b
JOIN trains t ON b.train_id = t.train_id
JOIN stations s1 ON b.from_station_id = s1.station_id
JOIN stations s2 ON b.to_station_id = s2.station_id
WHERE b.user_id = %s
ORDER BY b.booking_datetime DESC
""", (user['user_id'],))
bookings = [Link]()
if not bookings:
print("No bookings found!")
[Link]()
[Link]()
60
return
print_line("=", 60)
print(f" {status_symbol} BOOKING #{i} - {b[12].upper()}")
print_line("=", 60)
# Get passengers
[Link]("""
SELECT passenger_name, passenger_age, passenger_gender, seat_number, status
FROM booking_passengers WHERE booking_id = %s
""", (booking_id,))
passengers = [Link]()
print(f"\n Passengers:")
for p in passengers:
p_status = "✓" if p[4] == 'Confirmed' else "✗"
print(f" {p_status} {p[0]} ({p[1]}/{p[2][0]}) - Seat: {p[3]} [{p[4]}]"
print()
[Link]()
[Link]()
def track_train():
print_header("TRACK TRAIN")
train_number = get_valid_train_number()
train = get_train_by_number(train_number)
if not train:
61
print("Train not found!")
return
train_id = train[0]
status, current_stop, current_station = calculate_train_status(train_id)
if current_station:
print(f">>> Current/Last Station: {current_station}")
[Link]("""
SELECT tr.stop_number, s.station_code, s.station_name,
tr.arrival_time, tr.departure_time, tr.day_number
FROM train_routes tr
JOIN stations s ON tr.station_id = s.station_id
WHERE tr.train_id = %s ORDER BY tr.stop_number
""", (train_id,))
routes = [Link]()
[Link]()
[Link]()
if routes:
print_subheader("ROUTE STATUS")
rows = []
for r in routes:
arr = convert_to_12hr(r[3]) if r[3] else "Origin"
dep = convert_to_12hr(r[4]) if r[4] else "Terminus"
# ============================================================
# SETTINGS FUNCTIONS
# ============================================================
62
def change_full_name(user):
print_subheader("CHANGE NAME")
print(f"Current: {user['full_name']}")
conn = connect_with_db()
cursor = [Link]()
[Link]("UPDATE users SET full_name = %s WHERE user_id = %s", (new_name, user[
[Link]()
[Link]()
[Link]()
user['full_name'] = new_name
print("✓ Updated!")
def change_username(user):
print_subheader("CHANGE USERNAME")
print(f"Current: {user['username']}")
while True:
new_username = input("New username: ").strip()
valid, msg = validate_username(new_username)
if not valid:
print(f"ERROR: {msg}")
continue
if new_username == user['username']:
print("Same as current!")
continue
if check_username_exists(new_username):
print("Already taken!")
continue
break
conn = connect_with_db()
cursor = [Link]()
[Link]("UPDATE users SET username = %s WHERE user_id = %s", (new_username, us
[Link]()
[Link]()
[Link]()
user['username'] = new_username
print("✓ Updated!")
def change_password(user):
print_subheader("CHANGE PASSWORD")
conn = connect_with_db()
cursor = [Link]()
[Link]("SELECT password FROM users WHERE user_id = %s", (user['user_id'],))
current = [Link]()[0]
63
entered = input("Current password: ").strip()
if entered != current:
print("Wrong!")
[Link]()
[Link]()
return
while True:
new_pass = input("New password: ").strip()
if len(new_pass) < 4:
print("Too short!")
continue
confirm = input("Confirm: ").strip()
if new_pass != confirm:
print("Don't match!")
continue
break
def change_security_qa(user):
print_subheader("CHANGE SECURITY Q&A")
questions = {
1: "What is your mother's maiden name?",
2: "What is your pet's name?",
3: "What is your school name?",
4: "What is your favorite movie?"
}
conn = connect_with_db()
cursor = [Link]()
[Link]("UPDATE users SET security_question = %s, security_answer = %s WHERE u
(question, answer, user['user_id']))
[Link]()
[Link]()
[Link]()
print("✓ Updated!")
64
def settings_menu(user):
while True:
print_header(f"SETTINGS - {user['username']}")
print("1. Change Full Name")
print("2. Change Username")
print("3. Change Password")
print("4. Change Security Q&A")
print("0. Back")
if choice == "1":
change_full_name(user)
elif choice == "2":
change_username(user)
elif choice == "3":
change_password(user)
elif choice == "4":
change_security_qa(user)
elif choice == "0":
break
press_enter()
# ============================================================
# ADMIN USER MANAGEMENT
# ============================================================
def view_user_info():
print_subheader("VIEW USER")
conn = connect_with_db()
cursor = [Link]()
[Link]("""
SELECT user_id, username, full_name, password, security_question, security_answer
FROM users WHERE username = %s
""", (username,))
user = [Link]()
[Link]()
[Link]()
if not user:
print("Not found!")
return
print_dict_table({
"ID": user[0],
65
"Username": user[1],
"Name": user[2],
"Password": user[3],
"Security Q": user[4],
"Security A": user[5],
"Role": user[6]
})
def delete_user():
print_subheader("DELETE USER")
conn = connect_with_db()
cursor = [Link]()
if [Link]() == 'admin':
print("Cannot delete admin!")
[Link]()
[Link]()
return
[Link]("SELECT user_id, full_name, role FROM users WHERE username = %s", (use
user = [Link]()
if not user:
print("Not found!")
[Link]()
[Link]()
return
if user[2] == 'admin':
print("Cannot delete admin!")
[Link]()
[Link]()
return
if get_yes_no(f"Delete {user[1]}?"):
[Link]("DELETE FROM users WHERE user_id = %s", (user[0],))
[Link]()
print("✓ Deleted!")
[Link]()
[Link]()
def add_user_admin():
print_subheader("ADD USER")
signup_user()
def list_all_users():
print_subheader("ALL USERS")
66
conn = connect_with_db()
cursor = [Link]()
[Link]("""
SELECT user_id, username, full_name, role, created_at
FROM users ORDER BY user_id
""")
users = [Link]()
[Link]()
[Link]()
if not users:
print("No users found!")
return
rows = []
for u in users:
[Link]((u[0], u[1], u[2], u[3], str(u[4])[:10] if u[4] else "N/A"))
def user_management_menu():
while True:
print_header("USER MANAGEMENT")
print("1. View All Users")
print("2. View User Details")
print("3. Delete User")
print("4. Add User")
print("0. Back")
if choice == "1":
list_all_users()
elif choice == "2":
view_user_info()
elif choice == "3":
delete_user()
elif choice == "4":
add_user_admin()
elif choice == "0":
break
press_enter()
# ============================================================
# MENU FUNCTIONS
# ============================================================
def train_settings_menu():
while True:
print_header("TRAIN SETTINGS")
print("1. View All Trains")
67
print("2. View Train Details")
print("3. Add Train")
print("4. Edit Routes")
print("5. Edit Fare")
print("6. Edit Coaches")
print("0. Back")
if choice == "1":
view_all_trains()
elif choice == "2":
train_no = get_valid_train_number()
view_train_info(train_no)
elif choice == "3":
print("\n1. Manual")
print("2. Automatic")
print("3. Copy Existing")
print("0. Back")
sub = input("\nChoice: ").strip()
if sub == "1":
add_train_manual()
elif sub == "2":
add_train_automatic()
elif sub == "3":
copy_train()
elif choice == "4":
edit_train_routes()
elif choice == "5":
edit_train_fare()
elif choice == "6":
edit_train_seats()
elif choice == "0":
break
press_enter()
def booking_menu(user=None):
while True:
print_header("BOOKING")
print("1. Book Ticket")
print("2. Cancel Booking")
if user:
print("3. My Bookings")
else:
print("3. View Booking by PNR")
print("4. My Bookings")
print("0. Back")
if choice == "1":
print("\n1. By Train Number")
print("2. Search by Stations")
68
print("0. Back")
sub = input("\nChoice: ").strip()
if sub == "1":
book_ticket_by_train_no(user)
elif sub == "2":
search_train_and_book(user)
elif choice == "2":
cancel_booking(user)
elif choice == "3":
if user:
my_bookings(user)
else:
view_booking_by_pnr()
elif choice == "4" and not user:
my_bookings(user='NULL')
elif choice == "0":
break
press_enter()
def view_booking_by_pnr():
print_subheader("VIEW BOOKING")
conn = connect_with_db()
cursor = [Link]()
[Link]("""
SELECT b.booking_id, b.pnr_number, t.train_number, t.train_name,
b.class_code, b.journey_date, b.total_seats, b.total_fare,
s1.station_name, s2.station_name, b.platform_number,
b.coach_name, b.booking_status
FROM bookings b
JOIN trains t ON b.train_id = t.train_id
JOIN stations s1 ON b.from_station_id = s1.station_id
JOIN stations s2 ON b.to_station_id = s2.station_id
WHERE b.pnr_number = %s
""", (pnr,))
booking = [Link]()
if not booking:
print("Booking not found!")
[Link]()
[Link]()
return
booking_id = booking[0]
print_subheader(f"BOOKING - {booking[12]}")
# Get passengers
[Link]("""
SELECT passenger_name, passenger_age, passenger_gender, seat_number, status
FROM booking_passengers WHERE booking_id = %s
""", (booking_id,))
passengers = [Link]()
print(f"\n Passengers:")
for p in passengers:
p_status = "✓" if p[4] == 'Confirmed' else "✗"
print(f" {p_status} {p[0]} ({p[1]}/{p[2][0]}) - Seat: {p[3]} [{p[4]}]")
[Link]()
[Link]()
def admin_menu(admin_user):
while True:
print_header(f"ADMIN - {admin_user['full_name']}")
print("1. Train Settings")
print("2. Booking")
print("3. User Management")
print("4. My Settings")
print("0. Logout")
if choice == "1":
train_settings_menu()
elif choice == "2":
booking_menu(None)
elif choice == "3":
user_management_menu()
elif choice == "4":
settings_menu(admin_user)
elif choice == "0":
print("Logging out...")
break
70
else:
print_header("WRONG CHOICE")
def user_menu(user):
while True:
print_header(f"USER - {user['full_name']}")
print("1. Booking")
print("2. Track Train")
print("3. Settings")
print("0. Logout")
if choice == "1":
booking_menu(user)
elif choice == "2":
track_train()
press_enter()
elif choice == "3":
settings_menu(user)
elif choice == "0":
print("Logging out...")
break
else:
print_header("WRONG CHOICE")
def admin_login_menu():
while True:
print_header("ADMIN LOGIN")
print("1. Login")
print("2. Forgot Password")
print("0. Back")
if choice == "1":
user = login_with_forgot_option('admin', 'Admin')
if user:
press_enter()
admin_menu(user)
elif choice == "2":
forgot_password('admin')
elif choice == "0":
break
else:
print_header("WRONG CHOICE")
press_enter()
def user_login_menu():
while True:
print_header("USER LOGIN / SIGNUP")
print("1. Login")
print("2. Signup")
71
print("3. Forgot Password")
print("0. Back")
if choice == "1":
user = login_with_forgot_option('user', 'User')
if user:
press_enter()
user_menu(user)
elif choice == "2":
signup_user()
elif choice == "3":
forgot_password('user')
elif choice == "0":
break
else:
print_header("WRONG CHOICE")
press_enter()
def login_menu():
while True:
print_header("LOGIN / SIGNUP")
print("1. Admin Login")
print("2. User Login / Signup")
print("0. Back")
if choice == "1":
admin_login_menu()
elif choice == "2":
user_login_menu()
elif choice == "0":
break
else:
print_header("WRONG CHOICE")
def main_menu():
while True:
print_header("RAILWAY MANAGEMENT SYSTEM")
print("\n1. Login / Signup")
print("0. Exit")
if choice == "1":
login_menu()
elif choice == "0":
print_header("THANK YOU!")
print(" Goodbye!")
break
72
# ============================================================
# MAIN PROGRAM
# ============================================================
if __name__ == "__main__":
print_header("RAILWAY MANAGEMENT SYSTEM")
print(" Starting...")
try:
initialize_database()
main_menu()
except [Link] as err:
print(f"\nDatabase Error: {err}")
print("Please check your MySQL connection settings.")
except KeyboardInterrupt:
print("\n\nProgram interrupted. Goodbye!")
except Exception as e:
print(f"\nError: {e}")
73