



Identifico a un actor por cada invitado y otro actor coordinador para el pool compartido. La idea es que los invitados envíen mensajes de solicitud de consumo al pool al momento de querer pagar un juego, si hay saldo disponible en el mismo para que el invitado juegue entonces la respuesta del pool será afirmativa (true) y en caso contrario negativa (false). Si el saldo es mayor o igual al monto de la solicitud puede jugar y el saldo disminuye en función de tal monto pero en caso contrario le comunica que no puede jugar y el saldo permanece igual. Al comenzar la ejecución un invitado se envía a sí mismo el mensaje ElegirJuego, de esta forma inicia el ciclo donde tras elegir un juego (supongamos que esta función hace un sleep y devuelve un monto) se envía una solicitud al pool para ver si ese invitado puede o no jugar, en ambos casos termina nuevamente enviándose el mismo mensaje ElegirJuego para continuar el ciclo.
Se pueden pensar las siguiente mejoras (que entiendo exceden al objetivo del ejercicio):
const INVITADOS: usize = N;
/* Tipos de actores */
struct Invitado {
id: usize;
fn started(&mut self, _ctx: &mut Context<Self>) {
println!("[INVITADO {}] ¡ A jugar !", self.id);
_ctx.address().try_send(ElegirJuego());
}
}
impl Actor for Invitado {
type Context = Context<Self>;
}
struct Pool {
saldo: f64
pool: Recipient<Result>
}
impl Actor for Pool {
type Context = Context<Self>
}
/* Tipos de mensajes */
struct SolicitudConsumo {
id_invitado: usize,
monto: f64,
invitado: Recipient<Result>
}
struct RespuestaConsumo {
resultado: bool
}
struct ElegirJuego {
}
/* Manejo de mensajes */
impl Handler<SolicitudConsumo> for Pool {
type Result = ();
fn handle(&mut self, msg: SolicitudConsumo, _ctx: &mut Context<Self>) -> Self::Result {
let id_invitado = msg.0;
let monto_solicitado = msg.1;
let invitado = msg.2;
println!("[POOL] Recibo una solicitud de {} por un monto de {}.", id_invitado, monto_solicitado);
if self.saldo >= monto_solicitado {
self.saldo -= monto_solicitado;
println!("[POOL] Hay saldo suficiente, saldo restante {}.", self.saldo);
invitado.try_send(RespuestaConsumo{ resultado: true }).unwrap();
} else {
println!("[POOL] Sin saldo suficiente, saldo restante {}.", self.saldo);
invitado.try_send(RespuestaConsumo{ resultado: false }).unwrap();
}
}
}
impl Handler<RespuestaConsumo> for Invitado {
type Result = ();
fn handle(&mut self, msg: RespuestaConsumo, _ctx: &mut Context<Self>) -> Self::Result {
let puedo_jugar = msg.0;
if (!puedo_jugar) {
println!("[INVITADO {}] No puedo jugar, elijo otro juego.", self.id_invitado);
} else {
println!("[INVITADO {}] A jugar !!!", self.id_invitado);
simular_juego();
}
_ctx.address().try_send(ElegirJuego());
}
}
impl Handler<ElegirJuego> for Invitado {
type Result = ();
fn handle(&mut self, msg: ElegirJuego, _ctx: &mut Context<Self>) -> Self::Result {
println!("[INVITADO {}] ¿Ahora a qué juego?", self.id_invitado);
let nuevo_monto = simular_eleccion_juego();
println!("[INVITADO {}] Sé a qué quiero jugar ahora !!!", self.id_invitado);
self.pool.try_send(
SolicitudConsumo {
id_invitado: self.id,
monto: nuevo_monto,
invitado: _ctx.address().recipient()
}
)
}
fn main() {
let system = System::new();
system.block_on(async {
let mut invitados = vec!();
for id in 0..INVITADOS {
invitados.push(Invitado { id }.start().recipient())
}
Pool {
saldo: 1000000.0,
invitados
}.start();
});
system.run().unwrap();
println!("No hay más saldo disponible.");
}
