- missing more tests
- indented all other exercises
This commit is contained in:
2024-05-04 20:17:02 +02:00
parent 3f8dab2808
commit 109c19a085
7 changed files with 199 additions and 97 deletions

View File

@@ -1,10 +1,9 @@
#![allow(dead_code)]
use super::es02_rational::Rational;
use std::ops::Add;
use std::ops::Mul;
use super::es02_rational::Rational;
/** Es.4
* Per la struttura dei numeri razionali implementare i traits Add e Mul sia per fare
* somma e moltiplicazione di numeri razionali che per fare somma e moltiplicazione di un numero razionale e un intero (i32).

View File

@@ -1,8 +1,7 @@
#![allow(dead_code)]
use std::{fmt::Debug, rc::Rc};
use self::states::AccountState;
use std::{fmt::Debug, rc::Rc};
/**
* Dovete implementare un ContoBancario che ha come informazioni

View File

@@ -160,7 +160,6 @@ impl<T> LinkedList<T> {
None
}
pub fn get(&mut self, n: i32) -> Option<T> {
if self.size == 0 {
return None;

View File

@@ -28,16 +28,16 @@ pub struct NumVocali {
u: i32,
}
impl NumVocali {
pub fn new(a:i32, e:i32, i:i32, o:i32, u:i32) -> Self {
Self {a, e, i, o, u}
pub fn new(a: i32, e: i32, i: i32, o: i32, u: i32) -> Self {
Self { a, e, i, o, u }
}
}
#[derive(Debug, PartialEq, Default)]
pub struct TuplaVocali(i32, i32, i32, i32, i32);
impl TuplaVocali {
pub fn new(a:i32, e:i32, i:i32, o:i32, u:i32) -> Self {
Self (a, e, i, o, u)
pub fn new(a: i32, e: i32, i: i32, o: i32, u: i32) -> Self {
Self(a, e, i, o, u)
}
}

View File

@@ -1,15 +1,18 @@
#![allow(unused)]
use rand::{Rng, SeedableRng};
use rand_pcg::Pcg32;
use std::{
collections::HashMap,
collections::{HashMap, HashSet, VecDeque},
rc::Rc,
sync::{
mpsc::{self, Receiver, Sender},
Arc,
Arc, Mutex,
},
thread,
time::Duration,
};
/**
* Implementare il protocollo English Auction.
* Un banditore attende n partecipanti ad unasta per un prodotto che ha un prezzo iniziale ed un prezzo di
@@ -37,109 +40,220 @@ pub struct Product {
name: String,
price: f32,
reserve: f32,
owner: Option<String>,
}
#[derive(Clone, Debug)]
enum AuctionRequest {
NewProduct(String, f32),
AuctionStart(String, f32),
AuctionOver(Arc<Product>),
UpdatedPrice(f32),
YouWon,
EndProduct(Arc<Product>),
AuctionOver,
YouAreWinning(f32),
YouWon(Product),
Stop,
}
#[derive(Clone, Debug)]
enum AuctionResponse {
NotInterested,
NotInterested(String),
WantForPrice(String, f32),
}
type SendRequest = Sender<AuctionRequest>;
type ReciveRequest = Receiver<AuctionRequest>;
type SendResponse = Sender<AuctionResponse>;
type ReciveResponse = Receiver<AuctionResponse>;
#[derive(Debug)]
struct Auctioneer {
products: Vec<Product>,
sender: HashMap<String, Sender<AuctionRequest>>,
recive: Receiver<AuctionResponse>,
products: VecDeque<Product>,
currents: HashSet<String>,
participants: HashMap<String, SendRequest>,
recive: ReciveResponse,
}
#[derive(Debug)]
struct Participant {
name: String,
money: f32,
rng: Arc<Mutex<Pcg32>>,
products_won: Vec<Product>,
sender: Sender<AuctionResponse>,
recive: Receiver<AuctionRequest>,
sender: SendResponse,
recive: ReciveRequest,
}
#[derive(Debug)]
struct Auction {
pub struct Auction {
auctioneer: Auctioneer,
participants: Vec<Participant>,
sender: Sender<AuctionResponse>,
sender: SendResponse,
rng: Arc<Mutex<Pcg32>>,
}
impl Product {
pub fn new(name: &str, price: f32, reserve: f32) -> Self {
Self {
name: name.to_string(),
price,
reserve,
}
}
}
impl Participant {
pub fn get_next_move(&self, price:f32) {
let diff = 10.0_f32.min(price - self.money);
if diff > 0.0 {
pub fn auction_loop(&mut self) {
while let Ok(result) = self.recive.recv() {
match result {
AuctionRequest::AuctionStart(_, price) => self.updated_price(price),
AuctionRequest::UpdatedPrice(price) => self.updated_price(price),
AuctionRequest::YouAreWinning(price) => self.winning_for(price),
AuctionRequest::YouWon(prod) => self.won_product(prod),
AuctionRequest::AuctionOver(prod) => println!(
"Participant {:?} money:{:?}, won: {:?}",
self.name, self.money, self.products_won
),
AuctionRequest::Stop => return,
}
}
}
fn updated_price(&self, price: f32) {
let name = self.name.clone();
let response = if price <= self.money {
let up = self.rng.lock().unwrap().gen_range(price..self.money);
AuctionResponse::WantForPrice(name, up)
} else {
AuctionResponse::NotInterested(name)
};
self.sender.send(response);
}
fn winning_for(&self, price: f32) {
self.sender
.send(AuctionResponse::WantForPrice(self.name.clone(), price));
}
fn won_product(&mut self, product: Product) {
self.money -= product.price;
self.products_won.push(product);
}
}
impl Auctioneer {
fn send(&self, message: AuctionRequest) {
for (_, channel) in &self.sender {
channel.send(message.clone());
}
}
pub fn auction_loop(&mut self) {
while let Some(mut product) = self.products.pop_front() {
self.new_product(product.name.clone(), product.price);
let mut winner = None;
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))
}
loop {
let response = self.wait_for_responses();
if response.len() > 1 {
let (name, price) = response
.iter()
.reduce(|acc, curr| if curr.1 > acc.1 { curr } else { acc })
.unwrap();
winner = Some(name.clone());
product.price = *price;
self.update_price(name.clone(), *price);
} else {
break;
}
Ok(AuctionResponse::NotInterested) => (),
_ => break,
};
}
if product.price < product.reserve {
winner = None
}
self.end_product(winner, product);
}
price
self.end_auction();
}
fn new_product(&mut self, name: String, price: f32) {
let iter = self.participants.keys().map(|part| part.clone());
self.currents.clear();
self.currents.extend(iter);
self.send(false, AuctionRequest::AuctionStart(name, price));
}
fn update_price(&mut self, owner: String, price: f32) {
self.currents.remove(&owner);
self.send_only(&owner, AuctionRequest::YouAreWinning(price));
self.send(false, AuctionRequest::UpdatedPrice(price));
self.currents.insert(owner);
}
fn end_product(&mut self, winner: Option<String>, product: Product) {
if let Some(winner) = winner {
self.currents.remove(&winner);
self.send_only(&winner, AuctionRequest::YouWon(product.clone()));
}
self.send(true, AuctionRequest::AuctionOver(Arc::new(product)));
}
fn end_auction(&self) {
self.send(true, AuctionRequest::Stop);
}
fn wait_for_responses(&mut self) -> Vec<(String, f32)> {
let mut responses = vec![];
let mut count = 0;
let total = self.currents.len();
while count < total {
if let Some(response) = self.recive() {
responses.push(response);
}
count += 1;
}
responses
}
fn recive(&mut self) -> Option<(String, f32)> {
match self.recive.recv() {
Ok(response) => {
println!("Response -> {:?}", response);
match response {
AuctionResponse::NotInterested(name) => {
self.currents.remove(&name);
None
}
AuctionResponse::WantForPrice(name, price) => Some((name, price)),
}
}
Err(err) => panic!("Channel with the partecipants is interrupted!\n{}", err),
}
}
fn send(&self, all: bool, message: AuctionRequest) {
let recipients: Vec<&String> = if all {
self.participants.iter().map(|(k, v)| k).collect()
} else {
self.currents.iter().map(|x| x).collect()
};
let mut count = 0;
for recipient in recipients {
self.send_only(recipient, message.clone());
count += 1;
}
}
fn send_only(&self, recipient: &String, message: AuctionRequest) {
if let Some(channel) = self.participants.get(recipient) {
println!("Sending to {:?} -> {:?}", recipient, message);
channel.send(message);
}
}
}
impl Auction {
pub fn new(products: Vec<Product>) -> Self {
pub fn new(products: VecDeque<Product>, seed: u64) -> Self {
let channel_participant = mpsc::channel();
let auctioneer = Auctioneer {
products,
sender: HashMap::new(),
currents: HashSet::new(),
participants: HashMap::new(),
recive: channel_participant.1,
};
Self {
auctioneer,
rng: Arc::new(Mutex::new(Pcg32::seed_from_u64(seed))),
participants: vec![],
sender: channel_participant.0,
}
@@ -150,12 +264,13 @@ impl Auction {
let participant = Participant {
name: name.clone(),
money,
rng: self.rng.clone(),
products_won: vec![],
sender: self.sender.clone(),
recive: channel.1,
};
self.auctioneer.sender.insert(name, channel.0);
self.auctioneer.participants.insert(name, channel.0);
self.participants.push(participant);
}
@@ -169,40 +284,12 @@ impl Auction {
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
}
}
part.auction_loop();
});
}
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();
});
let mut auct = auctioneer;
auct.auction_loop();
}
}

View File

@@ -7,4 +7,3 @@ pub mod es06_list;
pub mod es07_list_generic;
pub mod es08_folds;
pub mod es09_auction;

19
tests/es09_auction.rs Normal file
View File

@@ -0,0 +1,19 @@
use esercizi::es09_auction::{Auction, Product};
use std::collections::VecDeque;
#[test]
fn test_auction() {
let products = VecDeque::from([
Product::new("bau", 10.0, 1000.0),
Product::new("woof", 321.0, 18554.0),
Product::new("woof2", 31.0, 1854.0),
]);
let mut auction = Auction::new(products, 0);
auction.add_participant("th1".to_string(), 4520.0);
auction.add_participant("th2".to_string(), 6500.0);
auction.add_participant("th3".to_string(), 15020.0);
auction.add_participant("th4".to_string(), 8520.0);
auction.start();
}