//----------------------------------------------------------------------------- bool datareader_c::read_joint( model_ptr owner, xml_element_ptr top, std::string key ) { xml_attribute_ptr attribute = top->attribute( "id" ); if( !attribute ) return false; std::string name = attribute->get_value(); xml_element_ptr element; std::string tag; joint_ptr joint = joint_ptr( new joint_c() ); component_ptr component = boost::dynamic_pointer_cast<component_c>( joint ); if( key != "" ) key += "::"; key += name; joint->id = name; for( unsigned i = 0; i < top->elements(); i++ ) { element = top->element( i ); tag = element->get_name(); if( tag == "Field" ) { read_field( component, element, key ); } } owner->insert( joint ); return true; }
city::city(size_t height, size_t weight) : _height(height), _weight(weight), _car_no(0), _flow_stat(STOP), _time_step(1), _cluster_delay_milliseconds(20) { this->_blocks = new joint_ptr*[this->_height]; // init joints FOR(i,0,this->_height,++) this->_blocks[i] = new joint_ptr[this->_weight]; FOR(i,0,this->_height,++) FOR(j,0,this->_weight,++) this->_blocks[i][j] = joint_ptr(new joint("J["+std::to_string(i)+","+std::to_string(j)+"]")); // adding streets to joints // topology: // +--+--+ // | | | // +--+--+ // | | | // +--+--+ // joint's street indexing: // RIGHT: 0 // DOWN: 1 // LEFT: 2 // UP: 3 vector<street_ptr> streets; FOR(i,0,this->_height,++) { FOR(j,0,this->_weight,++) { // @ every instance at max create 2 streets [ RIGHT / DOWN ] // > the last row only creates [ RIGHT ] street // > the last column only creates [ DOWN ] street // > the last(bottom right) joint don't creates anything! // > streets are joint by their HEADs while creating // @ every joint at max uses the previous [ LEFT / UP ] joint's streets // > the first row only uses the [ LEFT ] joint's [ RIGHT ] street // > the first column only uses the [ UP ] joint's [ DOWN ] street // > the first(top left) joint don't uses anything! // > streets are joint by their TAILs while using // for not available branches `nullptr` will be assigned instead bool is_first_row = (i == 0), is_last_row = ((i + 1) == this->_height), is_first_col = (j == 0), is_last_col = ((j + 1) == this->_weight); // fetch the joint joint_ptr& cj = this->_blocks[i][j]; // add outgoing street to joint { // flags the condition that we can create a street bool flags[2] = { !is_last_col, !is_last_row }; string postfix[2] = { "-R", "-D" }; FOR(k,0,2,++) { if(flags[k]) { // random capacity between [ 1km, 8km ] size_t cap = ((1000 / CONST_AVG_CAR_LONG) + rand() % int(7000 / CONST_AVG_CAR_LONG)); street_ptr s = street_ptr(new street(cap, "S-"+cj->name() + postfix[k])); s->event_add() (street::AFTER_EXIT, [](vector<const void*> args) { assert(args.size() == 3); const car* c = reinterpret_cast<const car*>(args[0]); const street *s = reinterpret_cast<const street*>(args[1]), *t = reinterpret_cast<const street*>(args[2]); // making it thread safe stringstream ss; ss<<"$ Car# «" << c->getID() <<"» going to «" << ::to_string(c->direction()) << "» with max speed of «"<<c->max_speed()<<" m/s» exited from «" << s->name() << " @ " << c->line() << "» to «" << t->name() << "»" << endl; cout << ss.str(); }); // random traffic weight between [ 1, 10 ] s->traffic_weight((1 + rand() % 10)); // add the branch cj->add_branch() (s, HEAD); // add the street to cluster streets.push_back(s); // check for cluster packing? if(streets.size() >= CONST_CLUSTER_STREET_MAX_SIZE) { this->_cluster_streets.push_back(streets); streets.clear(); } } else // not valid branch? cj->add_branch()(street_ptr(nullptr), NILL); } } // add incoming streets to joint { // flags the condition that we can use a street bool flags[2] = { !is_first_col, !is_first_row }; branch br[2] = { BRANCH_RIGHT, BRANCH_DOWN }; vector<size_t> ind[2] = { { i, j-1 }, { i - 1, j } }; FOR(k,0,2,++) { if(flags[k]) cj->add_branch()(this->_blocks[ind[k][0]][ind[k][1]]->branches()[br[k]], TAIL); else // not valid branch? cj->add_branch()(street_ptr(nullptr), NILL); } } assert(cj->size() == 4); } } // put the last remaining street cluster to pack! if(streets.size()) { assert(streets.size() < CONST_CLUSTER_STREET_MAX_SIZE); this->_cluster_streets.push_back(streets); } }