virtual ~Conduct();
virtual void recieve_msg(int msg, IConector *who, void *data);
- virtual void update();
+ virtual void update(int dir=OUT);
virtual void simulate();
protected:
--- /dev/null
+
+#ifndef _H_DRAIN_H
+#define _H_DRAIN_H
+
+#include "control.h"
+
+namespace PlaQui {
+
+namespace Model {
+
+/** Modela objetos que recibe liquido */
+class Drain:public Control {
+public:
+ /// Constructor
+ Drain(const std::string &_name);
+ /// Destructor
+ virtual ~Drain();
+
+ virtual bool get_output();
+
+ virtual void simulate();
+ /// Retorna el flujo que entrega actualmente
+ float get_actual_flow() { return actual_flow; }
+ /// Retorna el flujo máximo capaz de entregar
+ float get_capacity() { return capacity; }
+ /// Asigna el flojo máximo capaz de entregar
+ virtual void set_capacity(float _f) { capacity = _f; }
+protected:
+ float capacity;
+ float actual_flow;
+private:
+ Drain(const Drain &):Control("null") {}
+ Drain &operator = (const Drain &) { return *this; }
+};
+
+}
+}
+#endif // _H_SOURCE_H_
+
--- /dev/null
+
+#ifndef _DRAINAGE_H_
+#define _DRAINAGE_H_
+
+#include "drain.h"
+
+namespace PlaQui {
+
+namespace Model {
+
+/** Dranaje
+ *
+ */
+class Drainage:public Drain {
+public:
+ /// Constructor
+ Drainage(const std::string &_name);
+ /// Destructor
+ virtual ~Drainage();
+
+ virtual void update(int dir=OUT);
+ virtual void simulate();
+
+ virtual void recieve_msg(int msg, IConector *who, void *data);
+
+ virtual void set_capacity(float _f) { /* IGNORO EL CAMBIO DE CAPACIDAD! */ }
+protected:
+private:
+ Drainage(const Drainage &):Drain("null") {}
+ Drainage &operator = (const Drainage &) { return *this; }
+};
+
+}
+}
+
+#endif // _DRAINAGE_H_
* \param where Donde enviar el mensage, IConector::IN o IConector::OUT
* \param msg Mensage a enviar
*/
- void send_msg(int where, int msg);
+ void send_msg(int where, int msg, void *data=NULL);
/** Recibe un mensage
*
* Durante la fase de actualización los objetos se comunican entre
* sí para determinar cual es el flujo que manejan en una iteración.
*/
- virtual void update() = 0;
+ virtual void update(int dir=OUT) = 0;
/** Hace la simulación de esta iteración
*
* Por simulacion se entiende que el modelo debe avisar a las vistas
/// Mensages manejados por los elementos de la planta
enum {
- MSG_QUERY_MAX_FLOW = IConector::MSG_LAST, ///< preguntar por el máximo flujo
+ MSG_QUERY_MAX_FLOW_OUT = IConector::MSG_LAST, ///< flujo maximo a la salida
+ MSG_QUERY_MAX_FLOW_IN, ///< flujo maximo a la entrada
MSG_RESPONSE_MAX_FLOW, ///< responde al mensage QUERY_MAX_FLOW. data == float
MSG_LAST
};
* 0 cuando se le consulta por su flojo máximo.
*
*/
-class Bomb:public Source {
+class Pump:public Source {
public:
/// Constructor
- Bomb(const std::string &_name);
+ Pump(const std::string &_name);
/// Destructor
- virtual ~Bomb();
+ virtual ~Pump();
- virtual void update();
+ virtual void update(int dir=OUT);
virtual void simulate();
virtual bool get_output();
*/
bool active;
private:
- Bomb(const Bomb &):Source("null") {}
- Bomb &operator = (const Bomb &) { return *this; }
+ Pump(const Pump &):Source("null") {}
+ Pump &operator = (const Pump &) { return *this; }
};
}
--- /dev/null
+
+#ifndef _SPLITTER_H
+#define _SPLITTER_H
+
+#include "transport.h"
+
+namespace PlaQui {
+
+namespace Model {
+
+class Splitter:public Transport {
+public:
+ Splitter(const std::string &_name);
+ virtual ~Splitter();
+
+ virtual void recieve_msg(int msg, IConector *who, void *data);
+ virtual void update(int dir=OUT);
+ virtual void simulate();
+protected:
+private:
+ Splitter(const Splitter &):Transport("null") {}
+ Splitter &operator = (const Splitter &) { return *this; }
+};
+
+}
+}
+
+#endif //_SPLITTER_H
virtual ~Union();
virtual void recieve_msg(int msg, IConector *who, void *data);
- virtual void update();
+ virtual void update(int dir=OUT);
virtual void simulate();
protected:
+ int in_on_zero;
+ int in_ready;
private:
Union(const Union &):Transport("null") {}
Union &operator = (const Union &) { return *this; }
// Inicio los parametros de conectores
in_slots = 1;
out_slots = 1;
+ actual_flow = 9999;
}
Conduct::~Conduct()
void Conduct::recieve_msg(int msg, IConector *who, void *data)
{
switch (msg) {
- case MSG_QUERY_MAX_FLOW: {
+ case MSG_QUERY_MAX_FLOW_OUT: {
// Me preguntan por el flujo máximo.
// Primero me actualizo, y luego respondo
- update();
- float tmp = (actual_flow>max_flow)?max_flow:actual_flow;
+ float tmp = *((float *)data);
+ // update();
+ actual_flow = (actual_flow>max_flow)?max_flow:actual_flow;
+ actual_flow = (actual_flow<tmp)?actual_flow:tmp;
+
+ send_msg(OUT, MSG_QUERY_MAX_FLOW_OUT, &actual_flow);
// FIXME : no tiene que ir
if (out_list.size() == 0) tmp = max_flow;
- who->recieve_msg(MSG_RESPONSE_MAX_FLOW, this, &tmp);
+ who->recieve_msg(MSG_RESPONSE_MAX_FLOW, this, &actual_flow);
+ updated = true;
}
break;
case MSG_RESPONSE_MAX_FLOW: {
}
}
-void Conduct::update()
+void Conduct::update(int dir)
{
// Si ya me actualice, no lo tengo que hacer de nuevo
if (updated) return;
// Seteo mi actualizar en true para evitar entrar de nuevo
- actual_flow = 99999;
+// actual_flow = 99999;
updated = true;
- send_msg(OUT, MSG_QUERY_MAX_FLOW);
- send_msg(IN, MSG_QUERY_MAX_FLOW);
+ switch (dir) {
+ case IN:
+ send_msg(IN, MSG_QUERY_MAX_FLOW_IN, (void *)&max_flow);
+ break;
+ case OUT:
+ send_msg(OUT, MSG_QUERY_MAX_FLOW_OUT, (void *)&max_flow);
+ }
}
void Conduct::simulate()
std::cout << name << "::Flujo actual = " << actual_flow << std::endl;
updated = false;
+ actual_flow = 99999;
}
--- /dev/null
+
+#include "drain.h"
+#include <iostream>
+
+using namespace PlaQui::Model;
+
+Drain::Drain(const std::string &_name):Control(_name)
+{
+}
+
+Drain::~Drain()
+{
+}
+
+bool Drain::get_output()
+{
+ // Siempre esta abierta una Fuente, salvo que
+ // se indique lo contrario!
+ return true;
+}
+
+void Drain::simulate()
+{
+ std::cout << name << "::Flujo aceptado : " << actual_flow << std::endl;
+}
+
--- /dev/null
+
+#include "drainage.h"
+#include <iostream>
+
+using namespace PlaQui::Model;
+
+Drainage::Drainage(const std::string &_name):Drain(_name)
+{
+ in_slots = 1;
+ out_slots = 0;
+ // FIXME hacer INFINITO!
+ capacity = 99999;
+ actual_flow = 0.0f;
+}
+
+Drainage::~Drainage()
+{
+}
+
+void Drainage::update(int dir)
+{
+ // El drenaje no tiene que actualizar
+ if (updated) return;
+ actual_flow = 0;
+ updated = true;
+}
+
+void Drainage::simulate()
+{
+ std::cout << name << "::Flujo recibido = " << actual_flow << std::endl;
+ updated = false;
+ actual_flow = 0;
+}
+
+void Drainage::recieve_msg(int msg, IConector *who, void *data)
+{
+ float tmp;
+ switch (msg) {
+ case MSG_QUERY_MAX_FLOW_OUT:
+ // FIXME Hacer INFINITO !!!
+ actual_flow = *((float *)data);
+ std::cout << "DD" << std::endl;
+ tmp = 999999;
+ who->recieve_msg(MSG_RESPONSE_MAX_FLOW, this, &tmp);
+ updated = true;
+ break;
+ default:
+ Drain::recieve_msg(msg, who, data);
+ }
+}
+
out_list.clear();
}
-void IConector::send_msg(int where, int msg)
+void IConector::send_msg(int where, int msg, void *data)
{
// Recorro toda la lista y envío el mensage a cada
// elemento conectado en "where"
switch (where) {
case IN:
for(it=in_list.begin(); it!=in_list.end(); it++)
- (*it)->recieve_msg(msg, this, NULL);
+ (*it)->recieve_msg(msg, this, data);
break;
case OUT:
for(it=out_list.begin(); it!=out_list.end(); it++)
- (*it)->recieve_msg(msg, this, NULL);
+ (*it)->recieve_msg(msg, this, data);
}
}
/* Test pedorro a ver que pasa con lo que esta programado!! */
/* Compilar : g++ -Wall -o test -I../include *.cpp */
-#include "bomb.h"
+#include "pump.h"
#include "conduct.h"
#include "union.h"
+#include "splitter.h"
+#include "drainage.h"
#include <unistd.h>
using namespace std;
int main(int argc, char *argv[])
{
- Bomb *bomba1, *bomba2;
- Conduct *canio1;
- Conduct *canio2;
- Conduct *salida;
- Union *union1;
+ Pump *bomba1;
+ Conduct *salida1;
+ Conduct *salida2;
+ Conduct *entrada;
+ Splitter *split;
+ Drainage *dren1, *dren2;
- bomba1 = new Bomb("bomba1");
- bomba1->set_max_flow(3);
- bomba2 = new Bomb("bomba2");
- bomba2->set_max_flow(5);
- canio1 = new Conduct("cond_1");
- canio1->set_max_flow(5);
- canio2 = new Conduct("cond_2");
- canio2->set_max_flow(5);
+ bomba1 = new Pump("bomba");
+ bomba1->set_max_flow(30);
+ salida1 = new Conduct("salida_1");
+ salida1->set_max_flow(2);
+ salida2 = new Conduct("salida_2");
+ salida2->set_max_flow(5);
- union1 = new Union("union");
- union1->set_max_flow(5);
- salida = new Conduct("salida");
- salida->set_max_flow(10);
+ split = new Splitter("splitter");
+ split->set_max_flow(8);
+ entrada = new Conduct("entrada");
+ entrada->set_max_flow(10);
- bomba1->connect(canio1, IConector::OUT);
- canio1->connect(bomba1, IConector::IN);
- canio1->connect(union1, IConector::OUT);
+ dren1 = new Drainage("drenaje1");
+ dren2 = new Drainage("drenaje2");
- bomba2->connect(canio2, IConector::OUT);
- canio2->connect(bomba2, IConector::IN);
- canio2->connect(union1, IConector::OUT);
-
- union1->connect(canio1, IConector::IN);
- union1->connect(canio2, IConector::IN);
- union1->connect(salida, IConector::OUT);
-
- salida->connect(union1, IConector::IN);
+ bomba1->connect(entrada, IConector::OUT);
+ entrada->connect(bomba1, IConector::IN);
+ entrada->connect(split, IConector::OUT);
+ split->connect(entrada, IConector::IN);
+ split->connect(salida1, IConector::OUT);
+ split->connect(salida2, IConector::OUT);
+ salida1->connect(split, IConector::IN);
+ salida2->connect(split, IConector::IN);
+ salida1->connect(dren1, IConector::OUT);
+ salida2->connect(dren2, IConector::OUT);
int i = 0;
while (i<10) {
bomba1->update();
- bomba2->update();
- canio1->update();
- canio2->update();
- salida->update();
- union1->update();
+ salida1->update();
+ salida2->update();
+ entrada->update();
+ split->update();
+ dren1->update();
+ dren2->update();
bomba1->simulate();
- bomba2->simulate();
- canio1->simulate();
- canio2->simulate();
- salida->simulate();
- union1->simulate();
+ salida1->simulate();
+ salida2->simulate();
+ entrada->simulate();
+ split->simulate();
+ dren1->simulate();
+ dren2->simulate();
sleep(1);
if (i == 5) {
}
delete bomba1;
- delete bomba2;
- delete canio1;
- delete canio2;
- delete salida;
- delete union1;
+ delete salida1;
+ delete salida2;
+ delete entrada;
+ delete split;
return 1;
}
void PlantItem::recieve_msg(int msg, IConector *who, void *data)
{
switch (msg) {
- case MSG_QUERY_MAX_FLOW:
+ case MSG_QUERY_MAX_FLOW_OUT:
// TODO
return;
break;
-#include "bomb.h"
+#include "pump.h"
#include <iostream>
using namespace PlaQui::Model;
-Bomb::Bomb(const std::string &_name):Source(_name)
+Pump::Pump(const std::string &_name):Source(_name)
{
in_slots = 0;
out_slots = 1;
max_flow = actual_flow = 0.0f;
}
-Bomb::~Bomb()
+Pump::~Pump()
{
}
-void Bomb::update()
+void Pump::update(int dir)
{
if (updated) return;
- actual_flow = 99999;
+ if (active && open)
+ actual_flow = max_flow;
+ else
+ actual_flow = 0;
updated = true;
- send_msg(OUT, MSG_QUERY_MAX_FLOW);
+ send_msg(OUT, MSG_QUERY_MAX_FLOW_OUT, (void *)&actual_flow);
}
-void Bomb::simulate()
+void Pump::simulate()
{
std::cout << name << "::Flujo actual = " << ((active && open)?actual_flow:0) \
<< " de " << max_flow;
updated = false;
}
-bool Bomb::get_output()
+bool Pump::get_output()
{
/* Si el corte fue manual, no puedo hacer nada */
if (active == false) return false;
return open;
}
-void Bomb::recieve_msg(int msg, IConector *who, void *data)
+void Pump::recieve_msg(int msg, IConector *who, void *data)
{
switch (msg) {
- case MSG_QUERY_MAX_FLOW: {
+ case MSG_QUERY_MAX_FLOW_OUT: {
// Me preguntan por el flujo máximo.
// Primero me actualizo, y luego respondo
- update();
+ // TODO la bomba nunca deberia ser consultada,pues el flujo sale ella
+ /* update();
float tmp;
- if (active && open) {
- tmp = (actual_flow<max_flow)?actual_flow:max_flow;
- } else {
- tmp = 0.0f;
- }
- who->recieve_msg(MSG_RESPONSE_MAX_FLOW, this, &tmp);
+ tmp = (actual_flow<max_flow)?actual_flow:max_flow;
+ who->recieve_msg(MSG_RESPONSE_MAX_FLOW, this, &tmp);*/
}
break;
case MSG_RESPONSE_MAX_FLOW: {
--- /dev/null
+
+#include "splitter.h"
+#include <iostream>
+
+using namespace PlaQui::Model;
+
+Splitter::Splitter(const std::string &_name):Transport(_name)
+{
+ in_slots = 1;
+ out_slots = 2;
+ max_flow = actual_flow = 0.0f;
+}
+
+Splitter::~Splitter()
+{
+}
+
+void Splitter::recieve_msg(int msg, IConector *who, void *data)
+{
+ int pos = OUT;
+
+ // Verifico si esta conectado a mi entrada
+ std::list<IConector *>::iterator i;
+ for(i=in_list.begin(); i!=in_list.end(); i++) {
+ if ((*i) == who) pos = IN;
+ }
+
+ switch (msg) {
+ case MSG_QUERY_MAX_FLOW_OUT: {
+ // Me preguntan por el flujo máximo.
+ // Primero me actualizo, y luego respondo
+ actual_flow = *((float *)data);
+
+ if (max_flow < actual_flow) actual_flow = max_flow;
+
+ actual_flow /= 2.0f;
+
+ send_msg(OUT, MSG_QUERY_MAX_FLOW_OUT, &actual_flow);
+
+ // Listo, mi flujo ahora es el doble de lo que me pueden
+ // dar las salidas
+ actual_flow *= 2.0f;
+ who->recieve_msg(MSG_RESPONSE_MAX_FLOW, this, &actual_flow);
+ updated = true;
+ }
+ break;
+ case MSG_RESPONSE_MAX_FLOW: {
+ float max = *((float *)data);
+ if (pos == OUT) {
+ if (max < actual_flow) actual_flow = max;
+ if (max_flow < actual_flow) actual_flow = max_flow;
+ } else {
+ if (((2*max) < actual_flow) && (max != 0))
+ actual_flow = 2*max;
+ }
+ }
+ break;
+ default:
+ Transport::recieve_msg(msg, who, data);
+ }
+}
+
+void Splitter::update(int dir)
+{
+ // Si ya me actualice, no lo tengo que hacer de nuevo
+ if (updated) return;
+ // Seteo mi actualizar en true para evitar entrar de nuevo
+ // actual_flow = 99999;
+ updated = true;
+ switch (dir) {
+ case IN:
+ send_msg(IN, MSG_QUERY_MAX_FLOW_IN, (void *)&max_flow);
+ break;
+ case OUT:
+ send_msg(OUT, MSG_QUERY_MAX_FLOW_OUT, (void *)&max_flow);
+ }
+}
+
+void Splitter::simulate()
+{
+ if (!updated) {
+ return;
+ }
+
+ std::cout << name << "::Flujo actual = " << actual_flow << std::endl;
+ updated = false;
+ actual_flow = 99999;
+}
+
in_slots = 2;
out_slots = 1;
max_flow = actual_flow = 0.0f;
+ in_on_zero = 0;
+ in_ready = 0;
}
Union::~Union()
}
switch (msg) {
- case MSG_QUERY_MAX_FLOW: {
+ case MSG_QUERY_MAX_FLOW_OUT: {
// Me preguntan por el flujo máximo.
// Primero me actualizo, y luego respondo
- update();
- float tmp;
+ float m_data = *((float *)data)*2;
- tmp = (actual_flow<max_flow)?actual_flow:max_flow;
- if (pos == IN) {
- // Si esta conectado a mi entrada, le puedo aceptar
- // solo la mitad del flujo maximo
- tmp /= 2;
+ if (m_data == 0) {
+ in_on_zero++;
}
+
+ float tmp;
+ switch (in_on_zero) {
+ case 0:
+ actual_flow = (m_data<max_flow)?m_data:max_flow;
+ break;
+ case 1:
+ actual_flow = max_flow/2.0f;
+ break;
+ case 2:
+ actual_flow = 0;
+ }
+ send_msg(OUT, MSG_QUERY_MAX_FLOW_OUT, &actual_flow);
+
+ // FIXME hay que resolver el problema de avisar a las
+ // entradas el flujo correcto que deben enviar
+ tmp = (in_on_zero==0)?actual_flow/2.0f:actual_flow;
who->recieve_msg(MSG_RESPONSE_MAX_FLOW, this, &tmp);
+ updated = true;
}
break;
case MSG_RESPONSE_MAX_FLOW: {
if (pos == OUT) {
if (max < actual_flow) actual_flow = max;
} else {
- if ((2*max) < actual_flow) actual_flow = 2*max;
+ if (((2*max) < actual_flow) && (max != 0))
+ actual_flow = 2*max;
}
}
break;
}
}
-void Union::update()
+void Union::update(int dir)
{
// Si ya me actualice, no lo tengo que hacer de nuevo
if (updated) return;
// Seteo mi actualizar en true para evitar entrar de nuevo
- actual_flow = 99999;
+// actual_flow = 99999;
updated = true;
- send_msg(OUT, MSG_QUERY_MAX_FLOW);
- send_msg(IN, MSG_QUERY_MAX_FLOW);
+ switch (dir) {
+ case IN:
+ send_msg(IN, MSG_QUERY_MAX_FLOW_IN, (void *)&max_flow);
+ break;
+ case OUT:
+ send_msg(OUT, MSG_QUERY_MAX_FLOW_OUT, (void *)&max_flow);
+ }
}
void Union::simulate()
std::cout << name << "::Flujo actual = " << actual_flow << std::endl;
updated = false;
+ actual_flow = 99999;
+ in_on_zero = 0;
+ in_ready = 0;
}