Skip to content

Commit

Permalink
add 2 action & reset action
Browse files Browse the repository at this point in the history
  • Loading branch information
pumpCarl committed Oct 11, 2024
1 parent a7759f0 commit 46109f7
Show file tree
Hide file tree
Showing 6 changed files with 328 additions and 2 deletions.
2 changes: 1 addition & 1 deletion config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ address = "0.0.0.0:8888"
loss_rate = 0.4

[client]
timeout = 10
timeout = 1
retry = 8
#invocation_semantic = "at-least-once"
invocation_semantic = "at-most-once"
106 changes: 106 additions & 0 deletions src/bin/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,62 @@ fn send_request(request: Request, socket: &UdpSocket) -> Result<Response, io::Er
Ok(Response::MonitoringStarted(Err(result.get("message").unwrap().to_owned())))
}
}
Request::ReserveSeatsCheapestPrice { source, destination } => {
// 构建预订最便宜座位的请求
map.insert("request_id".to_string(), request_id);
map.insert("invocation_semantic".to_string(), invocation_semantic);
map.insert("action".to_string(), 6.to_string());
map.insert("source".to_string(), source);
map.insert("destination".to_string(), destination);

// 序列化并发送请求
let result = send_request_and_receive_response(map, socket).unwrap();

// 处理响应数据
let status = result.get("status").unwrap();
if status == "200" {
Ok(Response::Reservation(Ok(())))
} else {
Ok(Response::Reservation(Err(result.get("message").unwrap().to_owned())))
}
}
Request::ReserveSeatsBelowPrice { source, destination, max_price } => {
// 构建预订低于指定价格的座位的请求
map.insert("request_id".to_string(), request_id);
map.insert("invocation_semantic".to_string(), invocation_semantic);
map.insert("action".to_string(), 7.to_string());
map.insert("source".to_string(), source);
map.insert("destination".to_string(), destination);
map.insert("max_price".to_string(), max_price.to_string());

// 序列化并发送请求
let result = send_request_and_receive_response(map, socket).unwrap();

// 处理响应数据
let status = result.get("status").unwrap();
if status == "200" {
Ok(Response::Reservation(Ok(())))
} else {
Ok(Response::Reservation(Err(result.get("message").unwrap().to_owned())))
}
}
Request::ResetFlights => {
// 构建重置航班的请求
map.insert("request_id".to_string(), request_id);
map.insert("invocation_semantic".to_string(), invocation_semantic);
map.insert("action".to_string(), 8.to_string());

// 序列化并发送请求
let result = send_request_and_receive_response(map, socket).unwrap();

// 处理响应数据
let status = result.get("status").unwrap();
if status == "200" {
Ok(Response::ResetFlights(Ok(())))
} else {
Ok(Response::ResetFlights(Err(result.get("message").unwrap().to_owned())))
}
}
}
}

Expand All @@ -214,6 +270,9 @@ fn main() -> io::Result<()> {
println!(" 2 - query flight details");
println!(" 3 - reserve seats");
println!(" 4 - monitor flight");
println!(" 6 - reserve seats cheapest price");
println!(" 7 - reserve seats below price");
println!(" 8 - reset flights");
print!("Enter command: ");
io::stdout().flush()?;
io::stdin().read_line(&mut input)?;
Expand Down Expand Up @@ -299,6 +358,53 @@ fn main() -> io::Result<()> {
let result = value.as_map().unwrap();
println!("Received: {:?}", result);
}
} else if message == "8" {
// 重置航班
let request = Request::ResetFlights;
let response = send_request(request, &socket)?;
println!("Result: {:?}", response);
} else if message == "6" {
// 预订最便宜座位
let mut input2 = String::new();
print!("Enter source: ");
io::stdout().flush()?;
io::stdin().read_line(&mut input2)?;
let source = input2.trim();
let mut input3 = String::new();
print!("Enter destination: ");
io::stdout().flush()?;
io::stdin().read_line(&mut input3)?;
let destination = input3.trim();
let request = Request::ReserveSeatsCheapestPrice {
source: source.to_string(),
destination: destination.to_string(),
};
let response = send_request(request, &socket)?;
println!("Result: {:?}", response);
} else if message == "7" {
// 预订低于指定价格的座位
let mut input2 = String::new();
print!("Enter source: ");
io::stdout().flush()?;
io::stdin().read_line(&mut input2)?;
let source = input2.trim();
let mut input3 = String::new();
print!("Enter destination: ");
io::stdout().flush()?;
io::stdin().read_line(&mut input3)?;
let destination = input3.trim();
let mut input4 = String::new();
print!("Enter max_price: ");
io::stdout().flush()?;
io::stdin().read_line(&mut input4)?;
let max_price = input4.trim();
let request = Request::ReserveSeatsBelowPrice {
source: source.to_string(),
destination: destination.to_string(),
max_price: max_price.parse().unwrap(),
};
let response = send_request(request, &socket)?;
println!("Result: {:?}", response);
}
}

Expand Down
39 changes: 39 additions & 0 deletions src/bin/demo_flight_controller.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,10 @@ fn main() {
let response = controller.handle_request(request, &socket, Some(client_addr) );
println!("ReserveSeats (flight_id: 1, seats: 2) response: {:?}", response);

// let request = controller::Request::ReserveSeats { flight_id: 0, seats: 50 };
// let response = controller.handle_request(request, &socket, Some(client_addr) );
// println!("ReserveSeats (flight_id: 0, seats: 50) response: {:?}", response);

// Test QueryFlightDetails
let request = controller::Request::QueryFlightDetails { flight_id: 1 };
let response = controller.handle_request(request, &socket, Some(client_addr) );
Expand Down Expand Up @@ -116,4 +120,39 @@ fn main() {
for (id, flight) in controller.flights() {
println!("Flight {}: {:?}", id, flight);
}


let request = controller::Request::ReserveSeatsCheapestPrice {
source: "New York".to_string(),
destination: "London".to_string(),
};
let response = controller.handle_request(request, &socket, Some(client_addr));
println!("ReserveSeatsCheapestPrice (New York->London) response: {:?}", response);

println!("Final state of flights:");
for (id, flight) in controller.flights() {
println!("Flight {}: {:?}", id, flight);
}


let request = controller::Request::ReserveSeatsBelowPrice {
source: "New York".to_string(),
destination: "London".to_string(),
max_price: 600.0,
};
let response = controller.handle_request(request, &socket, Some(client_addr));
println!("ReserveSeatsBelowPrice (New York->London) response: {:?}", response);

println!("Final state of flights:");
for (id, flight) in controller.flights() {
println!("Flight {}: {:?}", id, flight);
}

controller.reset_flights();

println!("Final state of flights:");
for (id, flight) in controller.flights() {
println!("Flight {}: {:?}", id, flight);
}

}
40 changes: 40 additions & 0 deletions src/bin/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,9 @@ fn handle_request(data: &[u8], mut controller: &mut FlightController, src: Sock
"2" => query_flight_details(&payload, controller, socket),
"3" => reserve_seats(payload, &mut controller, socket),
"4" => monitor_flight(payload, &mut controller, src, socket),
"6" => reserve_seats_cheapest_price(payload, &mut controller, socket),
"7" => reserve_seats_below_price(payload, &mut controller, socket),
"8" => reset_flights(payload, &mut controller, socket),
_ => Err("Invalid action".into()),
}?;

Expand Down Expand Up @@ -325,6 +328,43 @@ fn reserve_seats(payload: &HashMap<String, Value>, controller: &mut FlightContro
}
}

fn reset_flights(payload: &HashMap<String, Value>, controller: &mut FlightController, socket: &UdpSocket) -> Result<HashMap<String, String>, Box<dyn Error>> {
let request = controller::Request::ResetFlights;
let response = controller.handle_request(request, &socket, None);
tracing::info!("response: {:?}", response);

let mut data = HashMap::new();
data.insert("status".to_string(), "200".to_string());
Ok(data)
}

fn reserve_seats_cheapest_price(payload: &HashMap<String, Value>, controller: &mut FlightController, socket: &UdpSocket) -> Result<HashMap<String, String>, Box<dyn Error>> {
let source = payload.get("source").unwrap().as_string().unwrap();
let destination = payload.get("destination").unwrap().as_string().unwrap();

let request = controller::Request::ReserveSeatsCheapestPrice { source: source.to_string(), destination: destination.to_string() };
let response = controller.handle_request(request, &socket, None);
tracing::info!("response: {:?}", response);

let mut data = HashMap::new();
data.insert("status".to_string(), "200".to_string());
Ok(data)
}

fn reserve_seats_below_price(payload: &HashMap<String, Value>, controller: &mut FlightController, socket: &UdpSocket) -> Result<HashMap<String, String>, Box<dyn Error>> {
let source = payload.get("source").unwrap().as_string().unwrap();
let destination = payload.get("destination").unwrap().as_string().unwrap();
let max_price = payload.get("max_price").unwrap().as_string().unwrap();

let request = controller::Request::ReserveSeatsBelowPrice { source: source.to_string(), destination: destination.to_string(), max_price: max_price.parse::<f32>().unwrap() };
let response = controller.handle_request(request, &socket, None);
tracing::info!("response: {:?}", response);

let mut data = HashMap::new();
data.insert("status".to_string(), "200".to_string());
Ok(data)
}

/// 监控航班
fn monitor_flight(payload: &HashMap<String, Value>, controller: &mut FlightController, client_addr: SocketAddr, socket: &UdpSocket) -> Result<HashMap<String, String>, Box<dyn Error>> {
let flight_id = payload.get("flight_id").unwrap().as_string().unwrap().parse::<i32>().unwrap();
Expand Down
123 changes: 122 additions & 1 deletion src/controller.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
use std::collections::{HashMap, HashSet};
use std::time::{Duration, Instant};

use chrono::NaiveDateTime;
use std::net::UdpSocket;
mod serialization;
use serialization::{ByteOrder, Serializer};

mod flight_models;
pub use flight_models::{Flight, Request, Response, FlightUpdate, MonitoringClient};
use tracing_subscriber::filter;

/// FlightController manages all flight-related operations and client monitoring
pub struct FlightController {
Expand Down Expand Up @@ -89,6 +90,18 @@ impl FlightController {
Err(e) => Response::MonitoringStarted(Err(e))
}
}
Request::ReserveSeatsCheapestPrice { source, destination } => {
let result = self.reserve_seats_cheapest_price(&source, &destination);
Response::ReserveSeatsCheapestPrice(result)
}
Request::ReserveSeatsBelowPrice { source, destination, max_price } => {
let result = self.reserve_seats_below_price(&source, &destination, max_price);
Response::ReserveSeatsBelowPrice(result)
}
Request::ResetFlights => {
self.reset_flights();
Response::ResetFlights(Ok(()))
}
}
}

Expand Down Expand Up @@ -160,6 +173,68 @@ impl FlightController {
self.monitoring_clients.retain(|_, clients| !clients.is_empty());
}

fn reserve_seats_cheapest_price(&mut self, source: &str, destination: &str) -> Result<(), String> {
let flight_ids: Vec<i32> = self.flights
.iter()
.filter(|(_, flight)| flight.source == source && flight.destination == destination)
.map(|(id, _)| *id)
.collect();

if flight_ids.is_empty() {
return Err("No matching flights found".to_string());
}

let available_flight_ids: Vec<i32> = flight_ids.into_iter().filter(|id| self.flights[id].seats_available > 0).collect();

if available_flight_ids.is_empty() {
return Err("No seats available found".to_string());
}

let cheapest_flight_id = *available_flight_ids.iter().min_by_key(|id| (self.flights[*id].airfare *100.0) as i32).unwrap();

// Reserve the seat for the cheapest flight
if let Some(flight) = self.flights.get_mut(&cheapest_flight_id) {
if flight.seats_available > 0 {
flight.seats_available -= 1;
Ok(())
} else {
return Err("No seats available found".to_string());
}
} else {
Err("Flight not found".to_string())
}
}


fn reserve_seats_below_price(&mut self, source: &str, destination: &str, max_price: f32) -> Result<(), String> {
let flight_ids: Vec<i32> = self.flights
.iter()
.filter(|(_, flight)| flight.source == source && flight.destination == destination)
.map(|(id, _)| *id)
.collect();

if flight_ids.is_empty() {
return Err("No matching flights found".to_string());
}

let price_below_max_flight_ids: Vec<i32> = flight_ids.into_iter().filter(|id| self.flights[id].airfare <= max_price).collect();

if price_below_max_flight_ids.is_empty() {
return Err("No seats available found".to_string());
}

for id in price_below_max_flight_ids {
if let Some(flight) = self.flights.get_mut(&id) {
if flight.seats_available > 0 {
flight.seats_available = 0;
}
}
}

Ok(())
}


/// Returns a reference to the flights HashMap
pub fn flights(&self) -> &HashMap<i32, Flight> {
&self.flights
Expand All @@ -170,6 +245,52 @@ impl FlightController {
self.flights.insert(flight.flight_id, flight);
}

pub fn remove_flight(&mut self, flight_id: i32) {
self.flights.remove(&flight_id);
}

pub fn clear_flights(&mut self) {
self.flights.clear();
}


pub fn reset_flights(&mut self) {
self.flights.clear();
self.monitoring_clients.clear();

// 添加一些示例航班
let flight0 = Flight {
flight_id: 0,
source: "New York".to_string(),
destination: "London".to_string(),
departure_time: NaiveDateTime::parse_from_str("2024-08-30 10:00:00", "%Y-%m-%d %H:%M:%S").unwrap(),
airfare: 200.0,
seats_available: 50,
};
self.add_flight(flight0);

let flight1 = Flight {
flight_id: 1,
source: "New York".to_string(),
destination: "London".to_string(),
departure_time: NaiveDateTime::parse_from_str("2024-09-01 10:00:00", "%Y-%m-%d %H:%M:%S").unwrap(),
airfare: 500.0,
seats_available: 100,
};
self.add_flight(flight1);

let flight2 = Flight {
flight_id: 2,
source: "London".to_string(),
destination: "Paris".to_string(),
departure_time: NaiveDateTime::parse_from_str("2024-09-02 14:00:00", "%Y-%m-%d %H:%M:%S").unwrap(),
airfare: 300.0,
seats_available: 150,
};
self.add_flight(flight2);

}

// Commented out as it's not currently used
// /// Queries details for a specific flight
// fn query_flight_details(&self, flight_id: i32) -> Option<&Flight> {
Expand Down
Loading

0 comments on commit 46109f7

Please sign in to comment.