0% found this document useful (0 votes)
2 views36 pages

Ip Project

Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
2 views36 pages

Ip Project

Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 36

Acknowledgement

__________________________
I would like to express my heartfelt gratitude to my teacher,
Mrs. Rakhi Parmar for their invaluable guidance, support, and
encouragement throughout the development of the Railway
Reservation System project. Their expert advice and constant
motivation were instrumental in completing this project
successfully.
I also appreciate the resources and knowledge provided by
various open-source communities, which helped me tackle
challenges during the project.
Thank you once again for your unwavering support and
mentorship.
About Python
__________________________
In the vast landscape of programming languages, Python stands as a
beacon of versatility, simplicity, and power. Developed by Guido van
Rossum in the late 1980s, Python has evolved into one of the most
popular and widely-used programming languages worldwide. Its appeal
lies in its readability, ease of use, and comprehensive standard libraries,
making it a top choice for beginners and seasoned developers alike.
At its core, Python embodies a philosophy of code readability and
simplicity. Its clean and easily understandable syntax allows developers
to express concepts in fewer lines of code compared to other
languages. It finds applications across diverse fields, from web
development and data analysis to artificial intelligence and scientific
computing. The language's extensive libraries, including but not limited
to Pandas, NumPy, Matplotlib, and TensorFlow, empower developers to
tackle various challenges efficiently. For instance, Pandas, a powerful
data manipulation library, simplifies the process of data analysis and
manipulation, allowing users to work with structured data seamlessly.
In conclusion, Python's simplicity, versatility, extensive libraries, and
community support position it as a cornerstone of modern
programming. Its impact spans from novice programmers to industry
experts, making it a driving force in technological advancements across
numerous fields.
About My SQL
__________________________
MySQL is an open-source relational database management system
(RDBMS) that has become a cornerstone in the world of databases. It
was developed by Michael Widenius, MySQL was initially released in
1995.
MySQL is open-source, allowing users to modify and redistribute the
software, contributing to its wide adoption and continuous
development. MySQL runs on various operating systems, making it a
versatile choice for diverse environments.
It empowers numerous web-based applications and content
management systems due to its speed, reliability, and compatibility
with popular web development stacks. It is widely used in enterprises
for managing critical business data, customer information, and
analytics.it is embedded due to its lightweight nature, it's utilized in
embedded applications, IoT devices, and other resource-constrained
environments.
Despite the emergence of newer databases, MySQL remains a popular
choice due to its stability, performance, and wide adoption. MySQL
continues to be a leading relational database, catering to diverse needs
across industries and application domains, fostering innovation, and
supporting the growth of robust and scalable data solutions.
Introduction of the Project
__________________________
Railways serve as one of the most vital modes of transportation,
connecting cities and regions across vast distances efficiently and
economically. With the increasing reliance on technology in daily life,
the need for a digital solution to streamline railway ticket bookings has
become more critical than ever. This project focuses on the
development of a Railway Reservation System, designed to simplify and
automate the process of booking, managing, and canceling railway
tickets.
The primary objective of this system is to enhance user experience by
reducing manual processes and eliminating the complexities associated
with traditional booking systems. The Railway Reservation System will
provide features like seat availability checks, passenger details
management, and real-time ticket reservation functionalities. By
leveraging technology, this system aims to minimize errors, save time,
and improve accessibility for users.
This project serves as a practical application of programming concepts,
database management, and system design, offering insights into real-
world problem-solving while addressing a significant need in the
transportation sector. Through this initiative, the project showcases the
potential of digital solutions to transform traditional systems into more
efficient and user-friendly alternatives.
Software and Hardware
Requirements
__________________________
Software Specifications:-
▪ Operating system: Windows 10/8/7
▪ Platform
➢ Python IDLE 3.7
▪ Database
➢ MySQL
▪ Languages
➢ Python

Hardware Specifications:-
▪ Processor: Dual core or above
▪ Hard Disk: 40 GB
▪ RAM
➢ 1024 MB
Module
__________________________

Following modules of python have been used in this


project:-

❖ Pandas [Panel data system]


❖ MySql.connector
Program Code
__________________________
from datetime import datetime, timedelta
import random

class RailwayReservation:
def __init__(self):
self.available_seats = 50 # Available seats in the train
self.booked_seats = 0 # Initially no seats are booked
self.passenger_details = {} # Dictionary to store passenger details

# Simulated train schedule with routes and their departure/arrival times (Real
Train Names)
self.train_routes = {
'Mumbai': {
'Delhi': {
'Rajdhani Express': {
'departure': '16:30', 'arrival': '08:00', 'seats': 50, 'base_price': 2500,
'train_type': 'Express',
'coaches': {
'AC': {'seats': 20, 'position': '1-10', 'seating': []},
'Sleeper': {'seats': 30, 'position': '11-20', 'seating': []}
}
},
'Shatabdi Express': {
'departure': '06:00', 'arrival': '14:00', 'seats': 50, 'base_price': 1500,
'train_type': 'Superfast',
'coaches': {
'AC': {'seats': 30, 'position': '1-15', 'seating': []},
'Sleeper': {'seats': 20, 'position': '16-20', 'seating': []}
}
}
},
'Bangalore': {
'Karnataka Express': {
'departure': '22:30', 'arrival': '18:30', 'seats': 50, 'base_price': 2000,
'train_type': 'Express',
'coaches': {
'AC': {'seats': 20, 'position': '1-10', 'seating': []},
'Sleeper': {'seats': 30, 'position': '11-20', 'seating': []}
}
},
'Mumbai-Bangalore Superfast': {
'departure': '11:30', 'arrival': '07:00', 'seats': 50, 'base_price': 1800,
'train_type': 'Superfast',
'coaches': {
'AC': {'seats': 20, 'position': '1-10', 'seating': []},
'Sleeper': {'seats': 30, 'position': '11-20', 'seating': []}
}
}
},
'Hyderabad': {
'Godavari Express': {
'departure': '19:15', 'arrival': '11:00', 'seats': 50, 'base_price': 2200,
'train_type': 'Express',
'coaches': {
'AC': {'seats': 20, 'position': '1-10', 'seating': []},
'Sleeper': {'seats': 30, 'position': '11-20', 'seating': []}
}
},
'Telangana Express': {
'departure': '09:00', 'arrival': '22:30', 'seats': 50, 'base_price': 2000,
'train_type': 'Superfast',
'coaches': {
'AC': {'seats': 20, 'position': '1-10', 'seating': []},
'Sleeper': {'seats': 30, 'position': '11-20', 'seating': []}
}
}
}
},
'Delhi': {
'Kolkata': {
'Howrah Rajdhani': {
'departure': '17:00', 'arrival': '08:00', 'seats': 50, 'base_price': 2700,
'train_type': 'Express',
'coaches': {
'AC': {'seats': 20, 'position': '1-10', 'seating': []},
'Sleeper': {'seats': 30, 'position': '11-20', 'seating': []}
}
},
'Shatabdi Express': {
'departure': '08:00', 'arrival': '18:00', 'seats': 50, 'base_price': 1800,
'train_type': 'Superfast',
'coaches': {
'AC': {'seats': 20, 'position': '1-10', 'seating': []},
'Sleeper': {'seats': 30, 'position': '11-20', 'seating': []}
}
}
},
'Pune': {
'Deccan Queen': {
'departure': '12:30', 'arrival': '23:30', 'seats': 50, 'base_price': 2100,
'train_type': 'Express',
'coaches': {
'AC': {'seats': 20, 'position': '1-10', 'seating': []},
'Sleeper': {'seats': 30, 'position': '11-20', 'seating': []}
}
},
'Gitanjali Express': {
'departure': '10:30', 'arrival': '20:00', 'seats': 50, 'base_price': 2000,
'train_type': 'Superfast',
'coaches': {
'AC': {'seats': 20, 'position': '1-10', 'seating': []},
'Sleeper': {'seats': 30, 'position': '11-20', 'seating': []}
}
}
},
'Mumbai': { # Delhi to Mumbai Route added here
'Rajdhani Express': {
'departure': '15:30', 'arrival': '06:00', 'seats': 50, 'base_price': 2400,
'train_type': 'Express',
'coaches': {
'AC': {'seats': 20, 'position': '1-10', 'seating': []},
'Sleeper': {'seats': 30, 'position': '11-20', 'seating': []}
}
},
'Shatabdi Express': {
'departure': '05:30', 'arrival': '14:00', 'seats': 50, 'base_price': 1500,
'train_type': 'Superfast',
'coaches': {
'AC': {'seats': 30, 'position': '1-15', 'seating': []},
'Sleeper': {'seats': 20, 'position': '16-20', 'seating': []}
}
},
'August Kranti Rajdhani': {
'departure': '23:00', 'arrival': '10:30', 'seats': 50, 'base_price': 2200,
'train_type': 'Express',
'coaches': {
'AC': {'seats': 20, 'position': '1-10', 'seating': []},
'Sleeper': {'seats': 30, 'position': '11-20', 'seating': []}
}
}
}
},
'Chennai': {
'Bangalore': {
'Karnataka Express': {
'departure': '20:45', 'arrival': '06:00', 'seats': 50, 'base_price': 1900,
'train_type': 'Express',
'coaches': {
'AC': {'seats': 20, 'position': '1-10', 'seating': []},
'Sleeper': {'seats': 30, 'position': '11-20', 'seating': []}
}
}
},
'Hyderabad': {
'Huzurabad Express': {
'departure': '14:30', 'arrival': '06:30', 'seats': 50, 'base_price': 2100,
'train_type': 'Express',
'coaches': {
'AC': {'seats': 20, 'position': '1-10', 'seating': []},
'Sleeper': {'seats': 30, 'position': '11-20', 'seating': []}
}
}
}
}
}

self.GST_RATE = 0.18 # GST rate (18%)

# Method to calculate price based on train type


def calculate_price(self, base_price, ticket_type):
if ticket_type.lower() == 'ac':
return base_price * 1.5 # AC tickets are 50% more expensive than the base
price
else:
return base_price # Sleeper tickets are at base price

# Method to calculate GST on the price


def calculate_gst(self, price):
return price * self.GST_RATE
# Method to check availability of seats in the selected train route
def check_availability(self, boarding_station, destination, train_name):
try:
available_trains = self.train_routes[boarding_station][destination]
if train_name in available_trains:
available_train = available_trains[train_name]
coaches = available_train['coaches']
available_seats = 0
for coach_type in coaches:
available_seats += coaches[coach_type]['seats'] -
len(coaches[coach_type]['seating'])
return available_seats
else:
print(f"No such train {train_name} between {boarding_station} and
{destination}.")
except KeyError:
print(f"No route found between {boarding_station} and {destination}.")

# Method to book a ticket


def book_ticket(self):
print("Enter your details to book a ticket:")

name = input("Enter Name: ")


age = input("Enter Age: ")
boarding_station = input("Enter Boarding Station: ")
destination = input("Enter Destination: ")
ticket_type = input("Enter Ticket Type (AC / Sleeper): ").lower()

print("\nAvailable Trains:")
try:
available_trains = self.train_routes[boarding_station][destination]
for train in available_trains:
print(f"- {train}")
except KeyError:
print("No route found.")

train_name = input("Enter Train Name: ")

# Proceed with booking


try:
if boarding_station in self.train_routes and destination in
self.train_routes[boarding_station]:
available_trains = self.train_routes[boarding_station][destination]
if train_name in available_trains and available_trains[train_name]
['seats'] > 0:
# Get the base price of the selected train
base_price = available_trains[train_name]['base_price']
coaches = available_trains[train_name]['coaches']

# Calculate final price based on ticket type


final_price = self.calculate_price(base_price, ticket_type)

# Calculate GST
gst_amount = self.calculate_gst(final_price)

# Calculate total bill


total_bill = final_price + gst_amount

# Determine the coach and seat number based on ticket type


if ticket_type.lower() == 'ac':
coach_name = 'AC'
coach = coaches['AC']
else:
coach_name = 'Sleeper'
coach = coaches['Sleeper']

# Assign a seat number


seat_no = self.assign_seat(coach_name, coach)
if seat_no:
coach['seating'].append(seat_no) # Mark seat as booked

# Store the passenger details


departure_time = available_trains[train_name]['departure']
arrival_time = available_trains[train_name]['arrival']
self.passenger_details[name] = {
'Age': age,
'Ticket Type': ticket_type,
'Boarding Station': boarding_station,
'Destination': destination,
'Train Name': train_name,
'Departure Time': departure_time,
'Arrival Time': arrival_time,
'Coach Name': coach_name,
'Seat No': seat_no,
'Base Price': base_price,
'Final Price': final_price,
'GST Amount': gst_amount,
'Total Bill': total_bill
}

self.booked_seats += 1
self.available_seats -= 1
print(f"Ticket booked successfully for {name} on {train_name}!")

# Print formatted ticket


self.print_ticket(name, boarding_station, destination, train_name,
departure_time, arrival_time,
base_price, final_price, gst_amount, total_bill,
coach_name, seat_no)

print(f"Seats Left in {coach_name} Coach: {coaches[coach_name]


['seats'] - len(coach['seating'])}")
else:
print(f"Sorry, no available seats in {coach_name} coach.")
else:
print(f"Sorry, the train {train_name} is fully booked.")
else:
print("Invalid train or route.")
except Exception as e:
print(f"Error during booking: {str(e)}")

# Method to assign a seat number in the given coach


def assign_seat(self, coach_name, coach):
# Check for an available seat in the coach
if len(coach['seating']) < coach['seats']:
seat_no = random.randint(1, coach['seats'])
# Ensure that seat is not already booked
while seat_no in coach['seating']:
seat_no = random.randint(1, coach['seats'])
return seat_no
else:
return None
# Method to print the formatted ticket
def print_ticket(self, name, boarding_station, destination, train_name,
departure_time, arrival_time,
base_price, final_price, gst_amount, total_bill, coach_name, seat_no):
print("\n********** TICKET **********")
print(f"Passenger Name: {name}")
print(f"Age: {self.passenger_details[name]['Age']}")
print(f"Boarding Station: {boarding_station}")
print(f"Destination: {destination}")
print(f"Train: {train_name}")
print(f"Departure Time: {departure_time}")
print(f"Arrival Time: {arrival_time}")
print(f"Coach: {coach_name} (Position: {self.train_routes[boarding_station]
[destination][train_name]['coaches'][coach_name]['position']})")
print(f"Seat Number: {seat_no}")

print(f"\n----- Price Breakdown -----")


print(f"Base Price: ₹{base_price}")
print(f"Final Price (After Ticket Type Adjustment): ₹{final_price}")
print(f"GST (18%): ₹{gst_amount}")
print(f"---------------------------")
print(f"Total Bill: ₹{total_bill}")
print("\n***************************")
# Method to cancel a ticket
def cancel_ticket(self):
if self.booked_seats > 0:
print("Enter Passenger Name to cancel the ticket:")
name_to_cancel = input()

if name_to_cancel in self.passenger_details:
train_name = self.passenger_details[name_to_cancel]['Train Name']
boarding_station = self.passenger_details[name_to_cancel]['Boarding
Station']
destination = self.passenger_details[name_to_cancel]['Destination']
coach_name = self.passenger_details[name_to_cancel]['Coach Name']

# Free up the seat in the selected coach


seat_no = self.passenger_details[name_to_cancel]['Seat No']
self.train_routes[boarding_station][destination][train_name]['coaches']
[coach_name]['seating'].remove(seat_no)

del self.passenger_details[name_to_cancel]
self.booked_seats -= 1
self.available_seats += 1
print(f"Ticket for {name_to_cancel} cancelled successfully!")
else:
print("No booking found for the given name.")
else:
print("No bookings to cancel.")

# Method to show all bookings


def show_bookings(self):
if self.booked_seats > 0:
print("\nCurrent Bookings:")
for name, details in self.passenger_details.items():
print(f"Name: {name}, Age: {details['Age']}, Ticket Type: {details['Ticket
Type']}, "
f"Train: {details['Train Name']}, Boarding Station: {details['Boarding
Station']}, "
f"Destination: {details['Destination']}, Departure: {details['Departure
Time']}, "
f"Arrival: {details['Arrival Time']}, Coach: {details['Coach Name']}, "
f"Seat No: {details['Seat No']}, Price: ₹{details['Final Price']}, "
f"GST: ₹{details['GST Amount']}, Total Bill: ₹{details['Total Bill']}")
else:
print("No current bookings.")

# Main function to interact with the system


def main():
system = RailwayReservation()

while True:
print("\nRailway Reservation System")
print("1. Book Ticket")
print("2. Cancel Ticket")
print("3. Show All Bookings")
print("4. Exit")
print("Enter your choice: ", end="")
choice = input()

try:
choice = int(choice)
except ValueError:
print("Invalid input! Please enter a number.")
continue

if choice == 1:
system.book_ticket()
elif choice == 2:
system.cancel_ticket()
elif choice == 3:
system.show_bookings()
elif choice == 4:
print("Exiting system...")
break
else:
print("Invalid choice! Please try again.")
if __name__ == "__main__":
main()
Sample Output
__________________________
Railway Reservation System
1. Book Ticket
2. Cancel Ticket
3. Show All Bookings
4. Exit
Enter your choice: 1
Enter your details to book a ticket:
Enter Name: Adarsh Tripathi
Enter Age: 16
Enter Boarding Station: Mumbai
Enter Destination: Delhi
Enter Ticket Type (AC / Sleeper): Sleeper

Available Trains:
- Rajdhani Express
- Shatabdi Express
Enter Train Name: Rajdhani Express
Ticket booked successfully for Adarsh Tripathi on Rajdhani Express!
********** TICKET **********
Passenger Name: Adarsh Tripathi
Age: 16
Boarding Station: Mumbai
Destination: Delhi
Train: Rajdhani Express
Departure Time: 16:30
Arrival Time: 08:00
Coach: Sleeper (Position: 11-20)
Seat Number: 12

----- Price Breakdown -----


Base Price: ₹2500
Final Price (After Ticket Type Adjustment): ₹2500
GST (18%): ₹450.0
---------------------------
Total Bill: ₹2950.0

***************************
Seats Left in Sleeper Coach: 29

Railway Reservation System


1. Book Ticket
2. Cancel Ticket
3. Show All Bookings
4. Exit
Enter your choice: 1
Enter your details to book a ticket:
Enter Name: Satyam Singh
Enter Age: 17
Enter Boarding Station: Delhi
Enter Destination: Pune
Enter Ticket Type (AC / Sleeper): AC

Available Trains:
- Deccan Queen
- Gitanjali Express
Enter Train Name: Gitanjali Express
Ticket booked successfully for Satyam Singh on Gitanjali Express!

********** TICKET **********


Passenger Name: Satyam Singh
Age: 17
Boarding Station: Delhi
Destination: Pune
Train: Gitanjali Express
Departure Time: 10:30
Arrival Time: 20:00
Coach: AC (Position: 1-10)
Seat Number: 15

----- Price Breakdown -----


Base Price: ₹2000
Final Price (After Ticket Type Adjustment): ₹3000.0
GST (18%): ₹540.0
---------------------------
Total Bill: ₹3540.0

***************************
Seats Left in AC Coach: 19

Railway Reservation System


1. Book Ticket
2. Cancel Ticket
3. Show All Bookings
4. Exit
Enter your choice: 1
Enter your details to book a ticket:
Enter Name: Aniket Prasad
Enter Age: 17
Enter Boarding Station: Chennai
Enter Destination: Bangalore
Enter Ticket Type (AC / Sleeper): AC
Available Trains:
- Karnataka Express
Enter Train Name: Karnataka Express
Ticket booked successfully for Aniket Prasad on Karnataka Express!

********** TICKET **********


Passenger Name: Aniket Prasad
Age: 17
Boarding Station: Chennai
Destination: Bangalore
Train: Karnataka Express
Departure Time: 20:45
Arrival Time: 06:00
Coach: AC (Position: 1-10)
Seat Number: 2

----- Price Breakdown -----


Base Price: ₹1900
Final Price (After Ticket Type Adjustment): ₹2850.0
GST (18%): ₹513.0
---------------------------
Total Bill: ₹3363.0
***************************
Seats Left in AC Coach: 19
Railway Reservation System
1. Book Ticket
2. Cancel Ticket
3. Show All Bookings
4. Exit
Enter your choice: 1
Enter your details to book a ticket:
Enter Name: Sandhesh Vishwakarma
Enter Age: 17
Enter Boarding Station: Delhi
Enter Destination: Kolkata
Enter Ticket Type (AC / Sleeper): AC

Available Trains:
- Howrah Rajdhani
- Shatabdi Express
Enter Train Name: Howrah Rajdhani
Ticket booked successfully for Sandhesh Vishwakarma on Howrah Rajdhani!

********** TICKET **********


Passenger Name: Sandhesh Vishwakarma
Age: 17
Boarding Station: Delhi
Destination: Kolkata
Train: Howrah Rajdhani
Departure Time: 17:00
Arrival Time: 08:00
Coach: AC (Position: 1-10)
Seat Number: 10

----- Price Breakdown -----


Base Price: ₹2700
Final Price (After Ticket Type Adjustment): ₹4050.0
GST (18%): ₹729.0
---------------------------
Total Bill: ₹4779.0

***************************
Seats Left in AC Coach: 19

Railway Reservation System


1. Book Ticket
2. Cancel Ticket
3. Show All Bookings
4. Exit
Enter your choice: 1
Enter your details to book a ticket:
Enter Name: Naina Vishwakarma
Enter Age: 17
Enter Boarding Station: Delhi
Enter Destination: Pune
Enter Ticket Type (AC / Sleeper): AC

Available Trains:
- Deccan Queen
- Gitanjali Express
Enter Train Name: Deccan Queen
Ticket booked successfully for Naina Vishwakarma on Deccan Queen!

********** TICKET **********


Passenger Name: Naina Vishwakarma
Age: 17
Boarding Station: Delhi
Destination: Pune
Train: Deccan Queen
Departure Time: 12:30
Arrival Time: 23:30
Coach: AC (Position: 1-10)
Seat Number: 6
----- Price Breakdown -----
Base Price: ₹2100
Final Price (After Ticket Type Adjustment): ₹3150.0
GST (18%): ₹567.0
---------------------------
Total Bill: ₹3717.0

***************************
Seats Left in AC Coach: 19

Railway Reservation System


1. Book Ticket
2. Cancel Ticket
3. Show All Bookings
4. Exit
Enter your choice: 2
Enter Passenger Name to cancel the ticket:
Adarsh Tripathi
Ticket for Adarsh Tripathi cancelled successfully!
Railway Reservation System
1. Book Ticket
2. Cancel Ticket
3. Show All Bookings
4. Exit
Enter your choice: 3

Current Bookings:
Name: Satyam Singh, Age: 17, Ticket Type: ac, Train: Gitanjali Express, Boarding
Station: Delhi, Destination: Pune, Departure: 10:30, Arrival: 20:00, Coach: AC, Seat
No: 15, Price: ₹3000.0, GST: ₹540.0, Total Bill: ₹3540.0
Name: Aniket Prasad, Age: 17, Ticket Type: ac, Train: Karnataka Express, Boarding
Station: Chennai, Destination: Bangalore, Departure: 20:45, Arrival: 06:00, Coach:
AC, Seat No: 2, Price: ₹2850.0, GST: ₹513.0, Total Bill: ₹3363.0
Name: Sandhesh Vishwakarma, Age: 17, Ticket Type: ac, Train: Howrah Rajdhani,
Boarding Station: Delhi, Destination: Kolkata, Departure: 17:00, Arrival: 08:00,
Coach: AC, Seat No: 10, Price: ₹4050.0, GST: ₹729.0, Total Bill: ₹4779.0
Name: Naina Vishwakarma, Age: 17, Ticket Type: ac, Train: Deccan Queen,
Boarding Station: Delhi, Destination: Pune, Departure: 12:30, Arrival: 23:30,
Coach: AC, Seat No: 6, Price: ₹3150.0, GST: ₹567.0, Total Bill: ₹3717.0

Railway Reservation System


1. Book Ticket
2. Cancel Ticket
3. Show All Bookings
4. Exit
Enter your choice: 4
Exiting system...
Conclusion
__________________________
By this project we learn many new things and learnt
to do practical of programs that we learnt. We
learned how to:
▪ Write programs utilizing modern software tools.
▪ Apply object oriented programming principles
effectively.
▪ Write procedural programs to solved small to
medium sized problems.
Bibliography
__________________________

❖Informatics Practices with Sumita Arora class 12


Textbook.
❖www.wikipedia.org
❖www.scribd.com
❖www.studocu.com
❖www.chatgpt.com

You might also like