Es 09 Auction
- not done - not done tests
This commit is contained in:
208
src/es09_auction.rs
Normal file
208
src/es09_auction.rs
Normal file
@@ -0,0 +1,208 @@
|
|||||||
|
#![allow(unused)]
|
||||||
|
|
||||||
|
use std::{
|
||||||
|
collections::HashMap,
|
||||||
|
rc::Rc,
|
||||||
|
sync::{
|
||||||
|
mpsc::{self, Receiver, Sender},
|
||||||
|
Arc,
|
||||||
|
},
|
||||||
|
thread,
|
||||||
|
time::Duration,
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* Implementare il protocollo English Auction.
|
||||||
|
* Un banditore attende n partecipanti ad un’asta per un prodotto che ha un prezzo iniziale ed un prezzo di
|
||||||
|
* riserva al di sotto del quale non puo’ essere venduto.
|
||||||
|
* Dopo aver ricevuto un messaggio da gli n partecipanti, invia loro la descrizione del prodotto che viene
|
||||||
|
* bandito e il suo prezzo minimo.
|
||||||
|
* I partecipanti possono rispondere: dicendo che non vogliono partecipare all’asta oppure che offrono un valore
|
||||||
|
* che deve essere maggiore o uguale al prezzo minimo.
|
||||||
|
*
|
||||||
|
* Il banditore se riceve da un partecipante il messaggio di uscita dall’asta lo elimina dalle successive
|
||||||
|
* interazioni, se invece riceve un messaggio con un prezzo, invia a tutti i partecipanti ancora interessati un
|
||||||
|
* nuovo prezzo (maggiore di quello che ha ricevuto da un partecipante).
|
||||||
|
* Il protocollo va avanti così fino a che il banditore non ha ricevuto da tutti i partecipanti il messaggio che non
|
||||||
|
* vogliono partecipare.
|
||||||
|
*
|
||||||
|
* A questo punto se il prezzo e’ maggiore del prezzo di riserva informa il partecipante che ha ottenuto il
|
||||||
|
* prodotto che e’ il vincitore e gli altri che l’asta e’ finita.
|
||||||
|
*
|
||||||
|
* Infine ill banditore mette in una struttura condivisa dai partecipanti l’indicazione del prodotto venduto a quale
|
||||||
|
* cifra e’ statto venduto e a quale partecipante e’ stato assegnato.
|
||||||
|
* I partecipanti leggono questa informazione.
|
||||||
|
*/
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct Product {
|
||||||
|
name: String,
|
||||||
|
price: f32,
|
||||||
|
reserve: f32,
|
||||||
|
owner: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
enum AuctionRequest {
|
||||||
|
NewProduct(String, f32),
|
||||||
|
UpdatedPrice(f32),
|
||||||
|
YouWon,
|
||||||
|
EndProduct(Arc<Product>),
|
||||||
|
AuctionOver,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
enum AuctionResponse {
|
||||||
|
NotInterested,
|
||||||
|
WantForPrice(String, f32),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct Auctioneer {
|
||||||
|
products: Vec<Product>,
|
||||||
|
sender: HashMap<String, Sender<AuctionRequest>>,
|
||||||
|
recive: Receiver<AuctionResponse>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct Participant {
|
||||||
|
name: String,
|
||||||
|
money: f32,
|
||||||
|
products_won: Vec<Product>,
|
||||||
|
sender: Sender<AuctionResponse>,
|
||||||
|
recive: Receiver<AuctionRequest>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct Auction {
|
||||||
|
auctioneer: Auctioneer,
|
||||||
|
participants: Vec<Participant>,
|
||||||
|
sender: Sender<AuctionResponse>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Participant {
|
||||||
|
pub fn get_next_move(&self, price:f32) {
|
||||||
|
let diff = 10.0_f32.min(price - self.money);
|
||||||
|
if diff > 0.0 {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Auctioneer {
|
||||||
|
fn send(&self, message: AuctionRequest) {
|
||||||
|
for (_, channel) in &self.sender {
|
||||||
|
channel.send(message.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new_product(&self, name: String, price:f32) {
|
||||||
|
self.send(AuctionRequest::NewProduct(name, price));
|
||||||
|
}
|
||||||
|
pub fn update_price(&self, price:f32) {
|
||||||
|
self.send(AuctionRequest::UpdatedPrice(price));
|
||||||
|
}
|
||||||
|
pub fn end_product(&self, product: Arc<Product>) {
|
||||||
|
self.send(AuctionRequest::EndProduct(product));
|
||||||
|
}
|
||||||
|
pub fn end_auction(&self) {
|
||||||
|
self.send(AuctionRequest::AuctionOver);
|
||||||
|
}
|
||||||
|
pub fn wait_for_responses(&self, timeout: u64) -> Option<(String, f32)> {
|
||||||
|
let mut price = None;
|
||||||
|
loop {
|
||||||
|
let timeout = Duration::from_millis(timeout);
|
||||||
|
match self.recive.recv_timeout(timeout) {
|
||||||
|
Ok(AuctionResponse::WantForPrice(name, proposed)) => {
|
||||||
|
if let Some((n, p)) = &price {
|
||||||
|
if proposed > *p {
|
||||||
|
price = Some((name, proposed))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
price = Some((name, proposed))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(AuctionResponse::NotInterested) => (),
|
||||||
|
_ => break,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
price
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Auction {
|
||||||
|
pub fn new(products: Vec<Product>) -> Self {
|
||||||
|
let channel_participant = mpsc::channel();
|
||||||
|
let auctioneer = Auctioneer {
|
||||||
|
products,
|
||||||
|
sender: HashMap::new(),
|
||||||
|
recive: channel_participant.1,
|
||||||
|
};
|
||||||
|
|
||||||
|
Self {
|
||||||
|
auctioneer,
|
||||||
|
participants: vec![],
|
||||||
|
sender: channel_participant.0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn add_participant(&mut self, name: String, money: f32) {
|
||||||
|
let channel = mpsc::channel();
|
||||||
|
let participant = Participant {
|
||||||
|
name: name.clone(),
|
||||||
|
money,
|
||||||
|
products_won: vec![],
|
||||||
|
sender: self.sender.clone(),
|
||||||
|
recive: channel.1,
|
||||||
|
};
|
||||||
|
|
||||||
|
self.auctioneer.sender.insert(name, channel.0);
|
||||||
|
self.participants.push(participant);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn start(mut self) {
|
||||||
|
while let Some(participant) = self.participants.pop() {
|
||||||
|
Self::start_participant(participant);
|
||||||
|
}
|
||||||
|
Self::start_auctioneer(self.auctioneer);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn start_participant(participant: Participant) {
|
||||||
|
thread::spawn(|| {
|
||||||
|
let mut part = participant;
|
||||||
|
|
||||||
|
while let Ok(result) = part.recive.recv() {
|
||||||
|
match result {
|
||||||
|
AuctionRequest::NewProduct(_, price) => (),
|
||||||
|
AuctionRequest::UpdatedPrice(_) => todo!(),
|
||||||
|
AuctionRequest::EndProduct(_) => todo!(),
|
||||||
|
AuctionRequest::YouWon => todo!(),
|
||||||
|
AuctionRequest::AuctionOver => return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
fn start_auctioneer(auctioneer: Auctioneer) {
|
||||||
|
thread::spawn(|| {
|
||||||
|
let mut auct = auctioneer;
|
||||||
|
while let Some(mut product) = auct.products.pop() {
|
||||||
|
auct.new_product(product.name.clone(), product.price);
|
||||||
|
|
||||||
|
while let Some(response) = auct.wait_for_responses(300) {
|
||||||
|
let (name, price) = response;
|
||||||
|
auct.update_price(price);
|
||||||
|
product.owner = Some(name);
|
||||||
|
product.price = price;
|
||||||
|
}
|
||||||
|
|
||||||
|
if product.price < product.reserve {
|
||||||
|
product.owner = None
|
||||||
|
}
|
||||||
|
|
||||||
|
auct.end_product(Arc::new(product));
|
||||||
|
}
|
||||||
|
|
||||||
|
auct.end_auction();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,4 +6,5 @@ pub mod es05_bank;
|
|||||||
pub mod es06_list;
|
pub mod es06_list;
|
||||||
pub mod es07_list_generic;
|
pub mod es07_list_generic;
|
||||||
pub mod es08_folds;
|
pub mod es08_folds;
|
||||||
|
pub mod es09_auction;
|
||||||
|
|
||||||
|
|||||||
6
tests/esercizi.rs
Normal file
6
tests/esercizi.rs
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
pub mod es01_anagram;
|
||||||
|
pub mod es02_rational;
|
||||||
|
pub mod es04_rational_traits;
|
||||||
|
pub mod es05_bank;
|
||||||
|
pub mod es06_list;
|
||||||
|
pub mod es08_folds;
|
||||||
Reference in New Issue
Block a user