<commit_before>var Nico = (function() {
    
    var streamDicts = null;
    var videoDicts = null;
    
    var $coTableContainer = null;
    var $coEditArea = null;
    var $coEditButton = null;
    var $coConfirmArea = null;
    var $coConfirmButton = null;
    
    var coRegex = /^co[0-9]+$/;
    
    var errorIndicator = "There was an error previously";
    
    // Max number of streams we can get in a single API call.
    // For search.solr, http://www59.atwiki.jp/nicoapi/pages/48.html says
    // the max is 149, but it's actually 100.
    var MAX_STREAMS_IN_CALL = 100;
    // Max number of times we'll try a particular API call before giving up.
    var MAX_CALL_ATTEMPTS = 2;
    // Proxy request server: hardcoded for now. May be a config thing later
    // if we stick with this proxy-request plan.
    var PROXY_REQUEST_SERVER = 'http://127.0.0.1:8080/';
    
    // Max number of API calls to have active in parallel. Too few and it may
    // take too long for everything to finish. Too many and some calls might
    // time out since they waited too long (since Nico seems to throttle
    // multiple calls to some extent).
    var MAX_ACTIVE_CALLS = 6;
    var numActiveCalls = 0;
    var callQueue = [];
    
    // Stream search keywords: hardcoded for now. May make this a setting later.
    var searchKeywords = ["rta", "ゲーム+練習"];
    //var searchKeywords = ["ゲーム"];
    
    var allLiveStreams = [];
    var liveStreamsCallsExpected = 0;
    var liveStreamsCallsCompleted = 0;
    var numTotalCalls = 0;
    var numFailedCalls = 0;
    
    
    function proxyAjax(url, callback, attemptNum) {
        
        if (numActiveCalls >= MAX_ACTIVE_CALLS) {
            callQueue.push(Util.curry(proxyAjax, url, callback, attemptNum));
            return;
        }
        
        var options = {
            type: 'GET',
            dataType: 'json',
            url: PROXY_REQUEST_SERVER + url,
            success: Util.curry(
                function(callback_, response){
                    numActiveCalls--;
                    if (callQueue.length > 0) {
                        var waitingAjaxCall = callQueue.shift();
                        waitingAjaxCall();
                    }
                    
                    callback_(response);
                },
                callback
            ),
            error: Util.curry(
                function(url_, callback_, attemptNum_, response){
                    numActiveCalls--;
                    if (callQueue.length > 0) {
                        var waitingAjaxCall = callQueue.shift();
                        waitingAjaxCall();
                    }
                    
                    // Try again if we haven't reached the max attempts.
                    if (attemptNum_ < MAX_CALL_ATTEMPTS) {
                        proxyAjax(url_, callback_, attemptNum_+1);
                    }
                    else {
                        callback(errorIndicator);
                    }
                },
                url, callback, attemptNum
            )
        };
        $.ajax(options);
        
        numActiveCalls++;
    }
    
    
    function startGettingAllLiveStreams() {
        
        searchKeywords.forEach(function(keyword){
                
            // Make an API call to get the first 'page' of live streams under
            // this keyword.
            var url =
                'http://api.ce.nicovideo.jp/liveapi/v1/video.search.solr'
                + '?__format=json'
                + '&word=' + keyword
                + '&limit=' + MAX_STREAMS_IN_CALL.toString();
            
            // To call Nico's API without getting a Cross Origin error, use CORS
            // via proxy.
            liveStreamsCallsExpected++;
            proxyAjax(
                url,
                Util.curry(
                    Main.getFunc('Nico.continueGettingLiveStreams'), keyword
                ),
                1
            );
        });
    }
    
    function continueGettingLiveStreams(keyword, response) {
        
        numTotalCalls++;
        
        if (response === errorIndicator) {
            numFailedCalls++;
            Main.showNotification(
                "Nicovideo requests failed after "
                + MAX_CALL_ATTEMPTS.toString()
                + " tries: "
                + numFailedCalls.toString() + " of "
                + numTotalCalls.toString());
            // TODO: This doesn't maximize the number of streams we can
            // get in this error case.
            Main.getFunc('Nico.setStreams')();
            return;
        }
        
        var nlvResponse = response.nicolive_video_response;
        var totalCount = parseInt(nlvResponse.total_count.filtered);
        
        if (totalCount <= MAX_STREAMS_IN_CALL) {
            // Oh, we've already retrieved all the live streams.
            // Skip to the next step then.
            addToAllLiveStreams(response);
            return;
        }
        
        // So far we've made one call and obtained the total stream count.
        // Build the rest of the calls, using the total count to know when
        // to stop.
        //
        // (Note: currentIndex isn't the same as the number of streams
        // so far. For some reason the API may not give any streams at
        // indices 0 to 2.)
        var currentIndex = MAX_STREAMS_IN_CALL;
        var urls = [];
        
        while (currentIndex < totalCount) {
            urls.push(
                'http://api.ce.nicovideo.jp/liveapi/v1/video.search.solr'
                + '?__format=json'
                + '&word=' + keyword
                + '&from=' + currentIndex.toString()
                + '&limit=' + MAX_STREAMS_IN_CALL.toString()
            );
            
            currentIndex += MAX_STREAMS_IN_CALL;
        }
        
        $.each(urls, function(i, url){
            liveStreamsCallsExpected++;
            proxyAjax(url, Main.getFunc('Nico.addToAllLiveStreams'), 1);
        });
        
        // Add the streams obtained from our first call.
        // (Should be done AFTER increasing the calls expected, or the
        // calls completed will match up with the calls expected too soon.)
        addToAllLiveStreams(response);
    }
    
    function addToAllLiveStreams(response) {
        
        numTotalCalls++;
        
        if (response === errorIndicator) {
            numFailedCalls++;
            Main.showNotification(
                "Nicovideo requests failed after "<commit_msg>Nico: Use data parameter of $.ajax() instead of manually building URLs.<commit_after>var Nico = (function() {
    
    var streamDicts = null;
    var videoDicts = null;
    
    var $coTableContainer = null;
    var $coEditArea = null;
    var $coEditButton = null;
    var $coConfirmArea = null;
    var $coConfirmButton = null;
    
    var coRegex = /^co[0-9]+$/;
    
    var errorIndicator = "There was an error previously";
    
    // Max number of streams we can get in a single API call.
    // For search.solr, http://www59.atwiki.jp/nicoapi/pages/48.html says
    // the max is 149, but it's actually 100.
    var MAX_STREAMS_IN_CALL = 100;
    // Max number of times we'll try a particular API call before giving up.
    var MAX_CALL_ATTEMPTS = 2;
    // Proxy request server: hardcoded for now. May be a config thing later
    // if we stick with this proxy-request plan.
    var PROXY_REQUEST_SERVER = 'http://127.0.0.1:8080/';
    
    // Max number of API calls to have active in parallel. Too few and it may
    // take too long for everything to finish. Too many and some calls might
    // time out since they waited too long (since Nico seems to throttle
    // multiple calls to some extent).
    var MAX_ACTIVE_CALLS = 6;
    var numActiveCalls = 0;
    var callQueue = [];
    
    // Stream search keywords: hardcoded for now. May make this a setting later.
    //var searchKeywords = ["rta", "ゲーム+練習"];
    var searchKeywords = ["ゲーム"];
    
    var allLiveStreams = [];
    var liveStreamsCallsExpected = 0;
    var liveStreamsCallsCompleted = 0;
    var numTotalCalls = 0;
    var numFailedCalls = 0;
    
    
    function proxyAjax(url, params, callback, attemptNum) {
        
        if (numActiveCalls >= MAX_ACTIVE_CALLS) {
            callQueue.push(Util.curry(proxyAjax, url, params, callback, attemptNum));
            return;
        }
        
        var options = {
            type: 'POST',
            dataType: 'json',
            url: PROXY_REQUEST_SERVER + url,
            data: params,
            success: Util.curry(
                function(callback_, response){
                    numActiveCalls--;
                    if (callQueue.length > 0) {
                        var waitingAjaxCall = callQueue.shift();
                        waitingAjaxCall();
                    }
                    
                    callback_(response);
                },
                callback
            ),
            error: Util.curry(
                function(url_, params_, callback_, attemptNum_, response){
                    numActiveCalls--;
                    if (callQueue.length > 0) {
                        var waitingAjaxCall = callQueue.shift();
                        waitingAjaxCall();
                    }
                    
                    // Try again if we haven't reached the max attempts.
                    if (attemptNum_ < MAX_CALL_ATTEMPTS) {
                        proxyAjax(url_, params_, callback_, attemptNum_+1);
                    }
                    else {
                        callback(errorIndicator);
                    }
                },
                url, params, callback, attemptNum
            )
        };
        $.ajax(options);
        
        numActiveCalls++;
    }
    
    
    function startGettingAllLiveStreams() {
        
        searchKeywords.forEach(function(keyword){
                
            // Make an API call to get the first 'page' of live streams under
            // this keyword.
            //
            // To call Nico's API without getting a Cross Origin error, use CORS
            // via proxy.
            var params = {
                '__format': 'json',
                'word': keyword,
                'limit': MAX_STREAMS_IN_CALL.toString()
            };
            
            liveStreamsCallsExpected++;
            proxyAjax(
                'http://api.ce.nicovideo.jp/liveapi/v1/video.search.solr',
                params,
                Util.curry(
                    Main.getFunc('Nico.continueGettingLiveStreams'), keyword
                ),
                1
            );
        });
    }
    
    function continueGettingLiveStreams(keyword, response) {
        
        numTotalCalls++;
        
        if (response === errorIndicator) {
            numFailedCalls++;
            Main.showNotification(
                "Nicovideo requests failed after "
                + MAX_CALL_ATTEMPTS.toString()
                + " tries: "
                + numFailedCalls.toString() + " of "
                + numTotalCalls.toString());
            // TODO: This doesn't maximize the number of streams we can
            // get in this error case.
            Main.getFunc('Nico.setStreams')();
            return;
        }
        
        var nlvResponse = response.nicolive_video_response;
        var totalCount = parseInt(nlvResponse.total_count.filtered);
        
        if (totalCount <= MAX_STREAMS_IN_CALL) {
            // Oh, we've already retrieved all the live streams.
            // Skip to the next step then.
            addToAllLiveStreams(response);
            return;
        }
        
        // So far we've made one call and obtained the total stream count.
        // Build the rest of the calls, using the total count to know when
        // to stop.
        //
        // (Note: currentIndex isn't the same as the number of streams
        // so far. For some reason the API may not give any streams at
        // indices 0 to 2.)
        var currentIndex = MAX_STREAMS_IN_CALL;
        var paramSets = [];
        
        while (currentIndex < totalCount) {
            paramSets.push({
                '__format': 'json',
                'word': keyword,
                'from': currentIndex.toString(),
                'limit': MAX_STREAMS_IN_CALL.toString()
            });
            
            currentIndex += MAX_STREAMS_IN_CALL;
        }
        
        $.each(paramSets, function(i, paramSet){
            liveStreamsCallsExpected++;
            proxyAjax(
                'http://api.ce.nicovideo.jp/liveapi/v1/video.search.solr',
                paramSet,
                Main.getFunc('Nico.addToAllLiveStreams'),
                1
            );
        });
        
        // Add the streams obtained from our first call.
        // (Should be done AFTER increasing the calls expected, or the
        // calls completed will match up with the calls expected too soon.)
        addToAllLiveStreams(response);
    }
    
    function addToAllLiveStreams(response) {
        
        numTotalCalls++;
        
        if (response === errorIndicator) {
            numFailedCalls++;
            Main.showNotification(
                "Nicovideo requests failed after "
{'fraction_non_alphanumeric': 0.08818011257035648, 'fraction_numerical': 0.006153846153846154, 'mean_word_length': 1.4180729450190528, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 2, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3771553', 'n_tokens_mistral': 3617, 'n_tokens_neox': 3455, 'n_words': 990}