// Adds an object to the database; checks to ensure object is not added twice. // Private function void GridDatabase::addToDatabase(DatabaseObject *object) { TNLAssert(object->mDatabase != this, "Already added to database, trying to add to same database again!"); TNLAssert(!object->mDatabase, "Already added to database, trying to add to different database!"); TNLAssert(object->getExtentSet(), "Object extents were never set!"); TNLAssert(!object->mBucketList, "BucketList must be NULL"); // WallItems should not be added to the database during a regular game, but the editor will add them... //TNLAssert(object->getObjectTypeNumber() != WallItemTypeNumber, "Should not add wall items to the database!"); if(object->mDatabase) // Should never happen return; object->mDatabase = this; static IntRect bins; fillBins(object->getExtent(), bins); for(S32 x = bins.minx; bins.maxx - x >= 0; x++) for(S32 y = bins.miny; bins.maxy - y >= 0; y++) { DatabaseBucketEntry *be = mChunker->alloc(); DatabaseBucketEntryBase *base = &mBuckets[x & BucketMask][y & BucketMask]; be->theObject = object; if(base->nextInBucket) base->nextInBucket->prevInBucket = be; be->nextInBucket = base->nextInBucket; be->prevInBucket = base; base->nextInBucket = be; be->nextInBucketForThisObject = object->mBucketList; object->mBucketList = be; } // Add the object to our non-spatial "database" as well mAllObjects.push_back(object); U8 type = object->getObjectTypeNumber(); if(type == GoalZoneTypeNumber) mGoalZones.push_back(object); else if(type == FlagTypeNumber) mFlags.push_back(object); else if(type == SpyBugTypeNumber) mSpyBugs.push_back(object); else if(type == PolyWallTypeNumber) mPolyWalls.push_back(object); else if(type == WallItemTypeNumber) mWallitems.push_back(object); //sortObjects(mAllObjects); // problem: Barriers in-game don't have mGeometry (it is NULL) }
// Delete by object void GridDatabase::removeFromDatabase(DatabaseObject *object, bool deleteObject) { TNLAssert(object->mDatabase == this || object->mDatabase == NULL, "Trying to remove Object from wrong database"); if(object->mDatabase != this) return; const Rect &extents = object->mExtent; object->mDatabase = NULL; static IntRect bins; fillBins(extents, bins); while(object->mBucketList) { DatabaseBucketEntry *b = object->mBucketList; TNLAssert(b->theObject == object, "Object mismatch"); TNLAssert(b->prevInBucket->nextInBucket == b, "Broken linked list"); if(b->nextInBucket) b->nextInBucket->prevInBucket = b->prevInBucket; b->prevInBucket->nextInBucket = b->nextInBucket; object->mBucketList = b->nextInBucketForThisObject; mChunker->free(b); } // Find and delete object from our non-spatial databases for(S32 i = 0; i < mAllObjects.size(); i++) if(mAllObjects[i] == object) { mAllObjects.erase(i); // mAllObjects is sorted, so we can't use erase_fast break; } U8 type = object->getObjectTypeNumber(); if(type == GoalZoneTypeNumber) eraseObject_fast(&mGoalZones, object); else if(type == FlagTypeNumber) eraseObject_fast(&mFlags, object); else if(type == SpyBugTypeNumber) eraseObject_fast(&mSpyBugs, object); else if(type == PolyWallTypeNumber) eraseObject_fast(&mPolyWalls, object); else if(type == WallItemTypeNumber) eraseObject_fast(&mWallitems, object); if(deleteObject) object->deleteThyself(); }
void smoothCompletedHour(IPResponseTimes &ipResponseTimes, SmoothedValues &smoothedValues, PrevBinTime &prevBinTime, const size_t &, const uint32_t &hourStartTime, SmoothedReadings &smoothedReadings){ /*Variables that maintain bin states for each IP*/ uint32_t currentInterval, binReadingCount, binStartTime, currentTime, binIndex, firstBinTime=0; std::vector <double> bins; double minBinReading=0, previousBinReading=0; std::set <uint32_t> processedIPs; std::vector<std::pair <uint32_t, double> > filteredDelta; std::vector<std::pair <uint32_t, double> >::iterator rTimingsLastElement; std::map<uint32_t, SmoothedReadings>::iterator smoothedValuesItr(smoothedValues.end()); /*Looping through completed hour's data*/ for(std::map <uint32_t, ResponseTimings>::const_iterator ipRTimesItr = ipResponseTimes.begin(); ipRTimesItr != ipResponseTimes.end(); ++ipRTimesItr) { smoothedValuesItr = smoothedValues.end(); binIndex=0;firstBinTime=0;binReadingCount=0; processedIPs.insert(ipRTimesItr->first); filteredDelta.clear(); /*applying median filter with 5 spatial moments*/ filteredDelta = medianFilter(ipRTimesItr->second, MEDIAN_FILTER_MAX_SIZE); /*If IP is new add it to smoothed timings and set bin start time as current hours start time*/ if(!isSeenIP(ipRTimesItr->first, prevBinTime)) { smoothedValuesItr = smoothedValues.insert(std::make_pair(ipRTimesItr->first, SmoothedReadings())).first; binStartTime = hourStartTime; minBinReading = previousBinReading = filteredDelta.begin()->second; firstBinTime = binStartTime; } /*If IP already exists in smoothed timings map read out the last bin time from prevBinTime map, move the bin offset to current hour*/ else{ smoothedValuesItr = smoothedValues.find(ipRTimesItr->first); if(smoothedValuesItr == smoothedValues.end()) smoothedValuesItr = smoothedValues.insert(std::make_pair(ipRTimesItr->first, SmoothedReadings())).first; binStartTime = getLastBinEndTime(ipRTimesItr->first, prevBinTime); if(binStartTime > hourStartTime) binStartTime = hourStartTime; while(binStartTime < hourStartTime){ binStartTime += BIN_SIZE; } previousBinReading = getLastBinValue(ipRTimesItr->first, prevBinTime); minBinReading = filteredDelta.begin()->second; if(!firstBinTime){ firstBinTime = binStartTime; } } rTimingsLastElement = filteredDelta.end(); --rTimingsLastElement; for(std::vector <std::pair <uint32_t, double> >::const_iterator rTimingsItr = filteredDelta.begin(); rTimingsItr != filteredDelta.end(); ++rTimingsItr) { currentTime = rTimingsItr->first; /*This bucket was already closed last hour, pushing value to new bucket*/ if(binStartTime > currentTime ){ currentTime = binStartTime; } /*Detemining bin interval*/ currentInterval = (currentTime - binStartTime)/BIN_SIZE; /*Either a value in a new bin was seen OR we know no further readings exist for this IP*/ if(currentInterval > 0 || rTimingsItr == rTimingsLastElement){ if(rTimingsItr == rTimingsLastElement){ /*Still in current interval, just close open bin*/ if(currentInterval == 0){ bins.push_back(rTimingsItr->second); minBinReading = *(bins.begin() + bins.size()/2) ; ++binReadingCount; fillBins(smoothedValuesItr, ipRTimesItr->first, smoothedReadings, binIndex, minBinReading, firstBinTime, 1, binReadingCount); binStartTime += BIN_SIZE; } /*Fill all missed intervals and current interval*/ else{ if(binReadingCount){ fillBins(smoothedValuesItr, ipRTimesItr->first, smoothedReadings, binIndex, minBinReading, firstBinTime, currentInterval, binReadingCount); } else{ fillBins(smoothedValuesItr, ipRTimesItr->first, smoothedReadings, binIndex, previousBinReading, firstBinTime, currentInterval, binReadingCount); } /*Also write current new bin since no more values will be seen*/ minBinReading = rTimingsItr->second; /*Additional +1 since we also close current bin*/ binStartTime += (currentInterval+1) * BIN_SIZE; fillBins(smoothedValuesItr, ipRTimesItr->first, smoothedReadings, binIndex, minBinReading, firstBinTime, 1, 1); previousBinReading = minBinReading; } /*Now lets make sure we pad empty bins for this hour*/ if(binIndex < BINS_IN_HOUR){ fillBins(smoothedValuesItr, ipRTimesItr->first, smoothedReadings, binIndex, previousBinReading, firstBinTime, BINS_IN_HOUR-binIndex, 0); binStartTime += (BINS_IN_HOUR-binIndex-1) * BIN_SIZE; } bins.clear(); } /*Close open bin, fill missing intervals and open new bin*/ else{ if(binReadingCount){ fillBins(smoothedValuesItr, ipRTimesItr->first, smoothedReadings, binIndex, minBinReading, firstBinTime, currentInterval, binReadingCount); binReadingCount = 1; previousBinReading = minBinReading; minBinReading = rTimingsItr->second; binStartTime += currentInterval * BIN_SIZE; } else{ fillBins(smoothedValuesItr, ipRTimesItr->first, smoothedReadings, binIndex, previousBinReading, firstBinTime, currentInterval, binReadingCount); binReadingCount = 1; minBinReading = rTimingsItr->second; binStartTime += currentInterval * BIN_SIZE; } bins.clear(); } } /*Current bin value was read, Just updating minimum bin reading and count */ else{ bins.push_back(rTimingsItr->second); minBinReading = *(bins.begin() + bins.size()/2) ; ++binReadingCount; } } /*Done with current IP, store last bin time and last bin value*/ storePrevBinTime(ipRTimesItr->first, binStartTime, previousBinReading, prevBinTime); filteredDelta.clear(); } ipResponseTimes.clear(); /*Padding bins for IP's seen in previous hours but not in the current hour*/ for(std::map <uint32_t, std::pair<uint32_t, double> >::iterator prevBinTimeItr = prevBinTime.begin(); prevBinTimeItr != prevBinTime.end(); ++prevBinTimeItr) { smoothedValuesItr = smoothedValues.find(prevBinTimeItr->first); if(smoothedValuesItr == smoothedValues.end()) smoothedValuesItr = smoothedValues.insert(std::make_pair(prevBinTimeItr->first, SmoothedReadings())).first; if(processedIPs.find(prevBinTimeItr->first) == processedIPs.end()){ binIndex=0; firstBinTime = prevBinTimeItr->second.first; if(firstBinTime > hourStartTime){ firstBinTime = hourStartTime; } while(firstBinTime < hourStartTime){ firstBinTime += BIN_SIZE; } fillBins(smoothedValuesItr, prevBinTimeItr->first, smoothedReadings, binIndex, prevBinTimeItr->second.second, firstBinTime, BINS_IN_HOUR, 0); prevBinTimeItr->second.first += BIN_SIZE * BINS_IN_HOUR; } } processedIPs.clear(); }