RequestBall* Logstalgia::findNearest(Paddle* paddle, const std::string& paddle_token) { float min_dist = -1.0f; RequestBall* nearest = 0; for(std::list<RequestBall*>::iterator it = balls.begin(); it != balls.end(); it++) { RequestBall* ball = *it; //special case if failed response code if(!ball->le->successful) { continue; } if(ball->le->successful && !ball->hasBounced() && (gPaddleMode <= PADDLE_SINGLE || gPaddleMode == PADDLE_VHOST && ball->le->vhost == paddle_token || gPaddleMode == PADDLE_PID && ball->le->pid == paddle_token ) ) { float dist = (paddle->getX() - ball->getX())/ball->speed; if(min_dist<0.0f || dist<min_dist) { min_dist = dist; nearest = ball; } } } return nearest; }
void Logstalgia::addBall(LogEntry* le, float start_offset) { gHighscore++; std::string hostname = le->hostname; std::string pageurl = le->path; //find appropriate summarizer for url int nogroups = summGroups.size(); Summarizer* pageSummarizer= 0; for(int i=0;i<nogroups;i++) { if(summGroups[i]->supportedString(pageurl)) { pageSummarizer = summGroups[i]; break; } } if(pageSummarizer==0) return; Paddle* entry_paddle = 0; if(gPaddleMode > PADDLE_SINGLE) { std::string paddle_token = (gPaddleMode == PADDLE_VHOST) ? le->vhost : le->pid; entry_paddle = paddles[paddle_token]; if(entry_paddle == 0) { vec2f paddle_pos = vec2f(display.width-(display.width/3), rand() % display.height); Paddle* paddle = new Paddle(paddle_pos, paddle_colour, paddle_token); entry_paddle = paddles[paddle_token] = paddle; } } else { entry_paddle = paddles[""]; } if(gHideURLPrefix) pageurl = filterURLHostname(pageurl); float dest_y = pageSummarizer->getMiddlePosY(pageurl); float pos_y = ipSummarizer->getMiddlePosY(hostname); float start_x = -(entry_paddle->getX()/ 5.0f); vec2f ball_start = vec2f(start_x, pos_y); vec2f ball_dest = vec2f(entry_paddle->getX(), dest_y); const std::string& match = ipSummarizer->getBestMatchStr(hostname); vec3f colour = pageSummarizer->isColoured() ? pageSummarizer->getColour() : colourHash(match); RequestBall* ball = new RequestBall(le, &fontMedium, balltex, colour, ball_start, ball_dest, simu_speed); ball->setElapsed( start_offset ); balls.push_back(ball); }
void Logstalgia::logic(float t, float dt) { float sdt = dt * settings.simulation_speed; //increment clock elapsed_time += sdt; currtime = starttime + (long)(elapsed_time); if(settings.stop_time && currtime > settings.stop_time) { currtime = settings.stop_time; } if(mousehide_timeout>0.0f) { mousehide_timeout -= dt; if(mousehide_timeout<0.0f) { SDL_ShowCursor(false); } } infowindow.hide(); if(end_reached && balls.empty()) { appFinished = true; return; } //if paused, dont move anything, only check what is under mouse if(paused) { for(auto& it: paddles) { Paddle* paddle = it.second; if(paddle->mouseOver(infowindow, mousepos)) { break; } } for(RequestBall* ball : balls) { if(ball->mouseOver(infowindow, mousepos)) { break; } } if(!ipSummarizer->mouseOver(infowindow,mousepos)) { for(Summarizer* s: summarizers) { if(s->mouseOver(infowindow, mousepos)) break; } } return; } //next will fast forward clock to the time of the next entry, //if the next entry is in the future if(next || (!settings.disable_auto_skip && balls.empty())) { if(!queued_entries.empty()) { LogEntry* le = queued_entries.front(); long entrytime = le->timestamp; if(entrytime > currtime) { elapsed_time = entrytime - starttime; currtime = starttime + (long)(elapsed_time); } } next = false; } //recalc spawn speed each second by if(currtime != lasttime) { //dont bother reading the log if we dont need to if(queued_entries.empty() || queued_entries.back()->timestamp <= currtime) { readLog(); } profile_start("determine new entries"); int items_to_spawn=0; for(LogEntry* le : queued_entries) { if(le->timestamp > currtime) break; items_to_spawn++; addStrings(le); } profile_stop(); //debugLog("items to spawn %d\n", items_to_spawn); if(items_to_spawn > 0) { profile_start("add new strings"); //re-summarize ipSummarizer->summarize(); for(Summarizer* s : summarizers) { s->summarize(); } profile_stop(); profile_start("add new entries"); float item_offset = 1.0 / (float) (items_to_spawn); int item_no = 0; while(!queued_entries.empty()) { LogEntry* le = queued_entries.front(); if(le->timestamp > currtime) break; float pos_offset = item_offset * (float) item_no++; float start_offset = std::min(1.0f, pos_offset); addBall(le, start_offset); queued_entries.pop_front(); } } //update date if(total_entries>0) { char datestr[256]; char timestr[256]; struct tm* timeinfo = localtime ( &currtime ); strftime(datestr, 256, "%A, %B %d, %Y", timeinfo); strftime(timestr, 256, "%X", timeinfo); displaydate = datestr; displaytime = timestr; } else { displaydate = ""; displaytime = ""; } lasttime=currtime; profile_stop(); } else { //do small reads per frame if we havent buffered the next second if(queued_entries.empty() || queued_entries.back()->timestamp <= currtime+1) { readLog(50); } } std::list<Paddle*> inactivePaddles; //update paddles for(auto& it: paddles) { std::string paddle_token = it.first; Paddle* paddle = it.second; if(settings.paddle_mode > PADDLE_SINGLE && !paddle->moving() && !paddle->visible()) { bool token_match = false; //are there any requests that will match this paddle? for(RequestBall* ball : balls) { if( (settings.paddle_mode == PADDLE_VHOST && ball->le->vhost == paddle_token) || (settings.paddle_mode == PADDLE_PID && ball->le->pid == paddle_token)) { token_match = true; break; } } //mark this paddle for deletion, continue if(!token_match) { inactivePaddles.push_back(paddle); continue; } } // find nearest ball to this paddle if( (retarget || !paddle->getTarget())) { RequestBall* ball = findNearest(paddle, paddle_token); if(ball != 0) { paddle->setTarget(ball); } else if(!paddle->moving()) { paddle->setTarget(0); } } paddle->logic(sdt); } retarget = false; profile_start("check ball status"); // NOTE: special handling for this iterator as items are being removed for(auto it = balls.begin(); it != balls.end();) { RequestBall* ball = *it; highscore += ball->logic(sdt); if(ball->isFinished()) { it = balls.erase(it); removeBall(ball); } else { it++; } } profile_stop(); profile_start("ipSummarizer logic"); ipSummarizer->logic(dt); profile_stop(); profile_start("updateGroups logic"); updateGroups(dt); profile_stop(); screen_blank_elapsed += dt; if(screen_blank_elapsed-screen_blank_interval > screen_blank_period) screen_blank_elapsed = 0.0f; //update font alpha font_alpha = 1.0f; if(screen_blank_elapsed>screen_blank_interval) { font_alpha = std::min(1.0f, (float) fabs(1.0f - (screen_blank_elapsed-screen_blank_interval)/(screen_blank_period*0.5))); font_alpha *= font_alpha; } }
void Logstalgia::draw(float t, float dt) { if(appFinished) return; if(!settings.disable_progress) slider.logic(dt); display.setClearColour(background); display.clear(); glDisable(GL_FOG); display.mode2D(); glDisable(GL_DEPTH_TEST); glDisable(GL_CULL_FACE); glDisable(GL_LIGHTING); profile_start("draw ip summarizer"); ipSummarizer->draw(dt, font_alpha); profile_stop(); profile_start("draw groups"); drawGroups(dt, font_alpha); profile_stop(); profile_start("draw balls"); glEnable(GL_BLEND); glEnable(GL_TEXTURE_2D); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glBindTexture(GL_TEXTURE_2D, balltex->textureid); for(RequestBall* ball : balls) { ball->draw(); } profile_stop(); profile_start("draw response codes"); for(std::list<RequestBall*>::iterator it = balls.begin(); it != balls.end(); it++) { RequestBall* r = *it; if(!settings.hide_response_code && r->hasBounced()) { r->drawResponseCode(); } } profile_stop(); glDisable(GL_TEXTURE_2D); glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_BLEND); if(settings.paddle_mode != PADDLE_NONE) { //draw paddles shadows for(auto& it: paddles) { it.second->drawShadow(); } //draw paddles for(auto& it: paddles) { it.second->draw(); } } if(settings.paddle_mode > PADDLE_SINGLE && !settings.hide_paddle_tokens) { glEnable(GL_TEXTURE_2D); //draw paddle tokens for(auto& it: paddles) { it.second->drawToken(); } } if(!settings.disable_glow) { glBlendFunc (GL_ONE, GL_ONE); glEnable(GL_BLEND); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, glowtex->textureid); for(std::list<RequestBall*>::iterator it = balls.begin(); it != balls.end(); it++) { (*it)->drawGlow(); } } infowindow.draw(); glEnable(GL_BLEND); glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_TEXTURE_2D); if(!take_screenshot && uimessage_timer>0.1f) { fontLarge.setColour(vec4(1.0f,1.0f,uimessage_timer/3.0f,uimessage_timer/3.0f)); int mwidth = fontLarge.getWidth(uimessage.c_str()); fontLarge.draw(display.width/2 - mwidth/2, display.height/2 - 20, uimessage.c_str()); uimessage_timer-=dt; } if(settings.splash > 0.0f) { int logowidth = fontLarge.getWidth("Logstalgia"); int logoheight = 105; int cwidth = fontMedium.getWidth("Website Access Log Viewer"); int awidth = fontMedium.getWidth("(C) 2008 Andrew Caudwell"); vec2 corner(display.width/2 - logowidth/2 - 30.0f, display.height/2 - 45); float logo_alpha = std::min(1.0f, settings.splash/3.0f); float logo_bg = std::min(0.2f, settings.splash/10.0f); glDisable(GL_TEXTURE_2D); glColor4f(0.0f, 0.5f, 1.0f, logo_bg); glBegin(GL_QUADS); glVertex2f(0.0f, corner.y); glVertex2f(0.0f, corner.y + logoheight); glVertex2f(display.width, corner.y + logoheight); glVertex2f(display.width, corner.y); glEnd(); glEnable(GL_TEXTURE_2D); fontLarge.alignTop(true); fontLarge.dropShadow(true); fontLarge.setColour(vec4(1.0f,1.0f,1.0f,logo_alpha)); fontLarge.draw(display.width/2 - logowidth/2,display.height/2 - 30, "Logstalgia"); fontLarge.setColour(vec4(0.0f,1.0f,1.0f,logo_alpha)); fontLarge.draw(display.width/2 - logowidth/2,display.height/2 - 30, "Log"); fontMedium.setColour(vec4(1.0f,1.0f,1.0f,logo_alpha)); fontMedium.draw(display.width/2 - cwidth/2,display.height/2 + 17, "Website Access Log Viewer"); fontMedium.draw(display.width/2 - awidth/2,display.height/2 + 37, "(C) 2008 Andrew Caudwell"); settings.splash -= dt; } fontMedium.setColour(vec4(1.0f,1.0f,1.0f,font_alpha)); if(info) { fontMedium.print(2,2, "FPS %d", (int) fps); fontMedium.print(2,19,"Balls: %d", balls.size()); fontMedium.print(2,36,"Queue: %d", queued_entries.size()); fontMedium.print(2,53,"Paddles: %d", paddles.size()); fontMedium.print(2,70,"Simulation Speed: %.2f", settings.simulation_speed); fontMedium.print(2,87,"Pitch Speed: %.2f", settings.pitch_speed); } else { fontMedium.draw(2,2, displaydate.c_str()); fontMedium.draw(2,19, displaytime.c_str()); } fontLarge.setColour(vec4(1.0f,1.0f,1.0f,font_alpha)); int counter_width = fontLarge.getWidth("00000000"); fontLarge.alignTop(false); fontLarge.print(display.width-10-counter_width,display.height-10, "%08d", highscore); if(!settings.disable_progress) slider.draw(dt); if(take_screenshot) { takeScreenshot(); take_screenshot = false; } }
void Logstalgia::draw(float t, float dt) { if(appFinished) return; if(!gDisableProgress) slider.logic(dt); display.setClearColour(background); display.clear(); glDisable(GL_FOG); display.mode2D(); glDisable(GL_DEPTH_TEST); glDisable(GL_CULL_FACE); glDisable(GL_LIGHTING); profile_start("draw ip summarizer"); ipSummarizer->draw(dt, font_alpha); profile_stop(); profile_start("draw groups"); drawGroups(dt, font_alpha); profile_stop(); profile_start("draw balls"); glEnable(GL_BLEND); glEnable(GL_TEXTURE_2D); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glBindTexture(GL_TEXTURE_2D, balltex->textureid); for(std::list<RequestBall*>::iterator it = balls.begin(); it != balls.end(); it++) { (*it)->draw(dt); } profile_stop(); profile_start("draw response codes"); for(std::list<RequestBall*>::iterator it = balls.begin(); it != balls.end(); it++) { RequestBall* r = *it; if(gResponseCode && r->hasBounced()) { r->drawResponseCode(); } } profile_stop(); glDisable(GL_TEXTURE_2D); glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_BLEND); if(gPaddleMode != PADDLE_NONE) { //draw paddles shadows for(std::map<std::string, Paddle*>::iterator it= paddles.begin(); it!=paddles.end();it++) { it->second->drawShadow(); } //draw paddles for(std::map<std::string, Paddle*>::iterator it= paddles.begin(); it!=paddles.end();it++) { it->second->draw(); } } if(!gDisableGlow) { glBlendFunc (GL_ONE, GL_ONE); glEnable(GL_BLEND); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, glowtex->textureid); for(std::list<RequestBall*>::iterator it = balls.begin(); it != balls.end(); it++) { (*it)->drawGlow(); } } infowindow.draw(); glEnable(GL_BLEND); glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_TEXTURE_2D); if(uimessage_timer>0.1f) { glColor4f(1.0,1.0,uimessage_timer/3.0f,uimessage_timer/3.0f); int mwidth = fontLarge.getWidth(uimessage.c_str()); fontLarge.draw(display.width/2 - mwidth/2, display.height/2 - 20, uimessage.c_str()); uimessage_timer-=dt; } if(gSplash>0.0f) { int logowidth = fontLarge.getWidth("Logstalgia"); int logoheight = 105; int cwidth = fontMedium.getWidth("Website Access Log Viewer"); int awidth = fontMedium.getWidth("(C) 2008 Andrew Caudwell"); vec2f corner(display.width/2 - logowidth/2 - 30.0f, display.height/2 - 45); float logo_alpha = std::min(1.0f, gSplash/3.0f); float logo_bg = std::min(0.2f, gSplash/10.0f); glDisable(GL_TEXTURE_2D); glColor4f(0.0f, 0.5f, 1.0f, logo_bg); glBegin(GL_QUADS); glVertex2f(0.0f, corner.y); glVertex2f(0.0f, corner.y + logoheight); glVertex2f(display.width, corner.y + logoheight); glVertex2f(display.width, corner.y); glEnd(); glEnable(GL_TEXTURE_2D); fontLarge.alignTop(true); fontLarge.dropShadow(true); glColor4f(1,1,1,logo_alpha); fontLarge.draw(display.width/2 - logowidth/2,display.height/2 - 30, "Logstalgia"); glColor4f(0,1,1,logo_alpha); fontLarge.draw(display.width/2 - logowidth/2,display.height/2 - 30, "Log"); glColor4f(1,1,1,logo_alpha); fontMedium.draw(display.width/2 - cwidth/2,display.height/2 + 17, "Website Access Log Viewer"); fontMedium.draw(display.width/2 - awidth/2,display.height/2 + 37, "(C) 2008 Andrew Caudwell"); gSplash-=dt; } if(!gDisableProgress) slider.draw(dt); glColor4f(1,1,1,font_alpha); if(info) { fontMedium.print(2,2, "FPS %d", (int) fps); fontMedium.print(2,19,"Balls %03d", balls.size()); fontMedium.print(2,36,"Queue %03d", queued_entries.size()); fontMedium.print(2,53,"Paddles %03d", paddles.size()); } else { fontMedium.draw(2,2, displaydate.c_str()); fontMedium.draw(2,19, displaytime.c_str()); } glColor4f(1,1,1,font_alpha); int counter_width = fontLarge.getWidth("00000000"); fontLarge.alignTop(false); fontLarge.print(display.width-10-counter_width,display.height-10, "%08d", highscore); }