std::vector<double> beatTrack(const AgentParameters ¶ms, const EventList &events, const EventList &beats) { AgentList agents; int count = 0; double beatTime = -1; if (!beats.empty()) { count = beats.size() - 1; EventList::const_iterator itr = beats.end(); --itr; beatTime = itr->time; } if (count > 0) { // tempo given by mean of initial beats double ioi = (beatTime - beats.begin()->time) / count; agents.push_back(new Agent(params, ioi)); } else // tempo not given; use tempo induction agents = Induction::beatInduction(params, events); if (!beats.empty()) { for (AgentList::iterator itr = agents.begin(); itr != agents.end(); ++itr) { (*itr)->beatTime = beatTime; (*itr)->beatCount = count; (*itr)->events = beats; } } agents.beatTrack(events, params, -1); Agent *best = agents.bestAgent(); std::vector<double> resultBeatTimes; if (best) { best->fillBeats(beatTime); for (EventList::const_iterator itr = best->events.begin(); itr != best->events.end(); ++itr) { resultBeatTimes.push_back(itr->time); } } for (AgentList::iterator ai = agents.begin(); ai != agents.end(); ++ai) { delete *ai; } return resultBeatTimes; }
AgentList Induction::beatInduction(const AgentParameters ¶ms, const EventList &events) { int i, j, b, bestCount; bool submult; int intervals = 0; // number of interval clusters std::vector<int> bestn; // count of high-scoring clusters bestn.resize(topN); double ratio, err; int degree; int maxClusterCount = (int) ceil((maxIOI - minIOI) / clusterWidth); std::vector<double> clusterMean; clusterMean.resize(maxClusterCount); std::vector<int> clusterSize; clusterSize.resize(maxClusterCount); std::vector<int> clusterScore; clusterScore.resize(maxClusterCount); EventList::const_iterator ptr1, ptr2; Event e1, e2; ptr1 = events.begin(); while (ptr1 != events.end()) { e1 = *ptr1; ++ptr1; ptr2 = events.begin(); e2 = *ptr2; ++ptr2; while (e2 != e1 && ptr2 != events.end()) { e2 = *ptr2; ++ptr2; } while (ptr2 != events.end()) { e2 = *ptr2; ++ptr2; double ioi = e2.time - e1.time; if (ioi < minIOI) // skip short intervals continue; if (ioi > maxIOI) // ioi too long break; for (b = 0; b < intervals; b++) // assign to nearest cluster if (std::fabs(clusterMean[b] - ioi) < clusterWidth) { if ((b < intervals - 1) && (std::fabs(clusterMean[b + 1] - ioi) < std::fabs(clusterMean[b] - ioi))) { b++; // next cluster is closer } clusterMean[b] = (clusterMean[b] * clusterSize[b] + ioi) / (clusterSize[b] + 1); clusterSize[b]++; break; } if (b == intervals) { // no suitable cluster; create new one if (intervals == maxClusterCount) { // System.err.println("Warning: Too many clusters"); continue; // ignore this IOI } intervals++; for ( ; (b > 0) && (clusterMean[b - 1] > ioi); b--) { clusterMean[b] = clusterMean[b - 1]; clusterSize[b] = clusterSize[b - 1]; } clusterMean[b] = ioi; clusterSize[b] = 1; } } } for (b = 0; b < intervals; b++) // merge similar intervals // TODO: they are now in order, so don't need the 2nd loop // TODO: check BOTH sides before averaging or upper gps don't work for (i = b + 1; i < intervals; i++) if (std::fabs(clusterMean[b] - clusterMean[i]) < clusterWidth) { clusterMean[b] = (clusterMean[b] * clusterSize[b] + clusterMean[i] * clusterSize[i]) / (clusterSize[b] + clusterSize[i]); clusterSize[b] = clusterSize[b] + clusterSize[i]; --intervals; for (j = i + 1; j <= intervals; j++) { clusterMean[j - 1] = clusterMean[j]; clusterSize[j - 1] = clusterSize[j]; } } if (intervals == 0) return AgentList(); for (b = 0; b < intervals; b++) clusterScore[b] = 10 * clusterSize[b]; bestn[0] = 0; bestCount = 1; for (b = 0; b < intervals; b++) { for (i = 0; i <= bestCount; i++) { if (i < topN && (i == bestCount || clusterScore[b] > clusterScore[bestn[i]])) { if (bestCount < topN) bestCount++; for (j = bestCount - 1; j > i; j--) bestn[j] = bestn[j - 1]; bestn[i] = b; break; } } } for (b = 0; b < intervals; b++) { // score intervals for (i = b + 1; i < intervals; i++) { ratio = clusterMean[b] / clusterMean[i]; submult = ratio < 1; if (submult) degree = (int) nearbyint(1 / ratio); else degree = (int) nearbyint(ratio); if ((degree >= 2) && (degree <= 8)) { if (submult) err = std::fabs(clusterMean[b] * degree - clusterMean[i]); else err = std::fabs(clusterMean[b] - clusterMean[i] * degree); if (err < (submult ? clusterWidth : clusterWidth * degree)) { if (degree >= 5) degree = 1; else degree = 6 - degree; clusterScore[b] += degree * clusterSize[i]; clusterScore[i] += degree * clusterSize[b]; } } } } AgentList a; for (int index = 0; index < bestCount; index++) { b = bestn[index]; // Adjust it, using the size of super- and sub-intervals double newSum = clusterMean[b] * clusterScore[b]; int newCount = clusterSize[b]; int newWeight = clusterScore[b]; for (i = 0; i < intervals; i++) { if (i == b) continue; ratio = clusterMean[b] / clusterMean[i]; if (ratio < 1) { degree = (int) nearbyint(1 / ratio); if ((degree >= 2) && (degree <= 8)) { err = std::fabs(clusterMean[b] * degree - clusterMean[i]); if (err < clusterWidth) { newSum += clusterMean[i] / degree * clusterScore[i]; newCount += clusterSize[i]; newWeight += clusterScore[i]; } } } else { degree = (int) nearbyint(ratio); if ((degree >= 2) && (degree <= 8)) { err = std::fabs(clusterMean[b] - degree * clusterMean[i]); if (err < clusterWidth * degree) { newSum += clusterMean[i] * degree * clusterScore[i]; newCount += clusterSize[i]; newWeight += clusterScore[i]; } } } } double beat = newSum / newWeight; // Scale within range ... hope the grouping isn't ternary :( while (beat < minIBI) // Maximum speed beat *= 2.0; while (beat > maxIBI) // Minimum speed beat /= 2.0; if (beat >= minIBI) { a.push_back(new Agent(params, beat)); } } return a; }
void Configuration::readApplicationSettings(xml_node<> *app) { xml_node<> *sess = singleChildElement(app, "session-management"); if (sess) { xml_node<> *dedicated = singleChildElement(sess, "dedicated-process"); xml_node<> *shared = singleChildElement(sess, "shared-process"); std::string tracking = singleChildElementValue(sess, "tracking", ""); if (dedicated && shared) throw WServer::Exception("<application-settings> requires either " "<dedicated-process> or <shared-process>, " "not both"); if (dedicated) { sessionPolicy_ = DedicatedProcess; setInt(dedicated, "max-num-sessions", maxNumSessions_); } if (shared) { sessionPolicy_ = SharedProcess; setInt(shared, "num-processes", numProcesses_); } if (!tracking.empty()) { if (tracking == "Auto") sessionTracking_ = CookiesURL; else if (tracking == "URL") sessionTracking_ = URL; else throw WServer::Exception("<session-tracking>: expecting 'Auto' " "or 'URL'"); } setInt(sess, "timeout", sessionTimeout_); setInt(sess, "bootstrap-timeout", bootstrapTimeout_); setInt(sess, "server-push-timeout", serverPushTimeout_); setBoolean(sess, "reload-is-new-session", reloadIsNewSession_); } std::string maxRequestStr = singleChildElementValue(app, "max-request-size", ""); if (!maxRequestStr.empty()) maxRequestSize_ = boost::lexical_cast< ::int64_t >(maxRequestStr) * 1024; std::string debugStr = singleChildElementValue(app, "debug", ""); if (!debugStr.empty()) { if (debugStr == "stack") errorReporting_ = ErrorMessageWithStack; else if (debugStr == "true") errorReporting_ = NoErrors; else if (debugStr == "false") errorReporting_ = ErrorMessage; else throw WServer::Exception("<debug>: expecting 'true', 'false'," "or 'stack'"); } setInt(app, "num-threads", numThreads_); xml_node<> *fcgi = singleChildElement(app, "connector-fcgi"); if (!fcgi) fcgi = app; // backward compatibility valgrindPath_ = singleChildElementValue(fcgi, "valgrind-path", valgrindPath_); runDirectory_ = singleChildElementValue(fcgi, "run-directory", runDirectory_); setInt(fcgi, "num-threads", numThreads_); // backward compatibility < 3.2.0 xml_node<> *isapi = singleChildElement(app, "connector-isapi"); if (!isapi) isapi = app; // backward compatibility setInt(isapi, "num-threads", numThreads_); // backward compatibility < 3.2.0 std::string maxMemoryRequestSizeStr = singleChildElementValue(isapi, "max-memory-request-size", ""); if (!maxMemoryRequestSizeStr.empty()) { isapiMaxMemoryRequestSize_ = boost::lexical_cast< ::int64_t > (maxMemoryRequestSizeStr) * 1024; } setInt(app, "session-id-length", sessionIdLength_); /* * If a session-id-prefix is defined in the configuration file, then * we loose the prefix defined by the connector (e.g. wthttpd), but who * would do such a thing ? */ connectorSessionIdPrefix_ = singleChildElementValue(app,"session-id-prefix", connectorSessionIdPrefix_); setBoolean(app, "send-xhtml-mime-type", xhtmlMimeType_); if (xhtmlMimeType_) LOG_WARN("ignoring send-xhtml-mime-type setting: HTML5 is now always used"); redirectMsg_ = singleChildElementValue(app, "redirect-message", redirectMsg_); setBoolean(app, "behind-reverse-proxy", behindReverseProxy_); setBoolean(app, "strict-event-serialization", serializedEvents_); setBoolean(app, "web-sockets", webSockets_); setBoolean(app, "inline-css", inlineCss_); setBoolean(app, "persistent-sessions", persistentSessions_); uaCompatible_ = singleChildElementValue(app, "UA-Compatible", ""); setBoolean(app, "progressive-bootstrap", progressiveBoot_); if (progressiveBoot_) setBoolean(app, "split-script", splitScript_); setBoolean(app, "session-id-cookie", sessionIdCookie_); setBoolean(app, "cookie-checks", cookieChecks_); std::string plainAjaxSessionsRatioLimit = singleChildElementValue(app, "plain-ajax-sessions-ratio-limit", ""); if (!plainAjaxSessionsRatioLimit.empty()) maxPlainSessionsRatio_ = boost::lexical_cast<float>(plainAjaxSessionsRatioLimit); setBoolean(app, "ajax-puzzle", ajaxPuzzle_); setInt(app, "indicator-timeout", indicatorTimeout_); setInt(app, "double-click-timeout", doubleClickTimeout_); std::vector<xml_node<> *> userAgents = childElements(app, "user-agents"); for (unsigned i = 0; i < userAgents.size(); ++i) { xml_node<> *userAgentsList = userAgents[i]; std::string type; if (!attributeValue(userAgentsList, "type", type)) throw WServer::Exception("<user-agents> requires attribute 'type'"); std::string mode; attributeValue(userAgentsList, "mode", mode); AgentList *list; if (type == "ajax") { list = &ajaxAgentList_; if (mode == "black-list") ajaxAgentWhiteList_ = false; else if (mode == "white-list") ajaxAgentWhiteList_ = true; else throw WServer::Exception ("<user-agents type=\"ajax\" requires attribute 'mode' with value " "\"white-list\" or \"black-list\""); } else if (type == "bot") list = &botList_; else throw WServer::Exception ("<user-agents> requires attribute 'type' with value " "\"ajax\" or \"bot\""); std::vector<xml_node<> *> agents = childElements(userAgentsList, "user-agent"); for (unsigned j = 0; j < agents.size(); ++j) list->push_back(elementValue(agents[j], "user-agent")); } xml_node<> *properties = singleChildElement(app, "properties"); if (properties) { std::vector<xml_node<> *> nodes = childElements(properties, "property"); for (unsigned i = 0; i < nodes.size(); ++i) { xml_node<> *property = nodes[i]; std::string name; if (!attributeValue(property, "name", name)) throw WServer::Exception("<property> requires attribute 'name'"); std::string value = elementValue(property, "property"); if (name == "approot") name = "appRoot"; if (name == "appRoot" && !appRoot_.empty()) LOG_WARN("ignoring configuration property 'appRoot' (" << value << ") because was already set to " << appRoot_); else properties_[name] = value; } } }