explain line by line
require ‘time’

class Api::V1::SchedulesController < ApplicationController
def index

# convert the dep and des station names to uppercase and replace underscores with spaces
departure_station = params[:departure]&.upcase
destination_station = params[:destination]&.upcase

time = params[:time].present? ? Time.parse(params[:time]) : nil
exclude = params[:restrict]&.downcase == ‘true’

# select all schedules that have the departure and destination stations
# and also starting with station name
# eg : if searching for pala it also return pala private stand , pala ksrtc stand, pala old stand

if departure_station && destination_station
schedules = Schedule.joins(:stations)
.where(“stations.name LIKE ? OR stations.name LIKE ? OR stations.name = ? OR stations.name = ?”, “#{departure_station} %”, “#{destination_station} %”, “#{departure_station}”, “#{destination_station}”)
.select(‘schedules.*’)
.group(‘schedules.id’)
.having(‘COUNT(DISTINCT stations.name) = 2’)
.distinct
trips = schedules.map do |schedule|
stations = schedule.stations.order(:id)
station_names = stations.map(&:name)

# find the index of the departure and destination stations
departure_index = station_names.index { |name| name =~ /#{departure_station}/i }
destination_index = station_names.index { |name| name =~ /#{destination_station}/i }

# this is used to exclude return trip , if the user is searching for a trip from pala to kottayam
# it will exclude the trip from kottayam to pala (since database has both trips)

if departure_index && destination_index && departure_index < destination_index
departure_station_data = stations[departure_index]
departure_time = Time.parse(departure_station_data.departure_time)

next if time && departure_time < time

trip_data = {
vehicle_number: schedule.route.bus_schedule.vehicle_number,
trip: schedule.trip,
stations: stations.map do |station|
{
station: station.name,
arrivalTime: station.arrival_time,
departureTime: station.departure_time
}
end
}

trip_data[:stations] = trip_data[:stations][departure_index…destination_index] if exclude
trip_data
end
end.compact

# sort the trips by departure time of the departure station
sorted_trips = trips.sort_by do |trip|
time_str = trip[:stations].find { |station| station[:station] =~ /#{departure_station}/i }[:departureTime]
Time.parse(time_str)
end

render json: sorted_trips, status: :ok
else
render json: { error: 'Departure and destination stations are required. ’ }, status: :unprocessable_entity
end
end
end



here is the schema of database
CREATE TABLE IF NOT EXISTS "bus_schedules" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "vehicle_number" varchar, "created_at" datetime(6) NOT NULL, "updated_at" datetime(6) NOT NULL);
CREATE TABLE sqlite_sequence(name,seq);
CREATE TABLE IF NOT EXISTS "routes" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "bus_schedule_id" integer NOT NULL, "name" varchar, "created_at" datetime(6) NOT NULL, "updated_at" datetime(6) NOT NULL, CONSTRAINT "fk_rails_bbd7cf2ceb"
FOREIGN KEY ("bus_schedule_id")
  REFERENCES "bus_schedules" ("id")
);
CREATE INDEX "index_routes_on_bus_schedule_id" ON "routes" ("bus_schedule_id");
CREATE TABLE IF NOT EXISTS "schedules" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "route_id" integer NOT NULL, "trip" integer, "created_at" datetime(6) NOT NULL, "updated_at" datetime(6) NOT NULL, CONSTRAINT "fk_rails_f99af144df"
FOREIGN KEY ("route_id")
  REFERENCES "routes" ("id")
);
CREATE INDEX "index_schedules_on_route_id" ON "schedules" ("route_id");
CREATE TABLE IF NOT EXISTS "stations" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "schedule_id" integer NOT NULL, "name" varchar, "arrival_time" varchar, "departure_time" varchar, "created_at" datetime(6) NOT NULL, "updated_at" datetime(6) NOT NULL, CONSTRAINT "fk_rails_c6f63b8a09"
FOREIGN KEY ("schedule_id")
  REFERENCES "schedules" ("id")
);
CREATE INDEX "index_stations_on_schedule_id" ON "stations" ("schedule_id");