---
layout: page
title: Robot Code Directory
tags: programming

# This page retrieves data from the generated json present for each team, 
# and renders it. If you want your team's code added to this list, add it
# to your team's wiki page, and it will automatically make it here
#
# To add it to your team's page, you need to add something like this to the
# frontmatter (YAML content between the triple dashes)
#
# robot_code:
#   2016:
#    - Robot: ["https://github.com/myteam/robot_code", "C++/Java/LabVIEW/Python/etc"]
#

---

<style>
    .pre-defined-filter li:not(.picked) .glyphicon-ok {
        display: none;
    }
</style>


<!-- TODO: implement filtering, make it look nicer, add short descriptions? -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.16/d3.min.js"></script>
<script type="text/javascript">
// this hack exists because we cannot gather data from all sub repos in liquid, so do it at runtime instead.. 
var teamdata = [{% for td in site.data.teamdata.teamidx.frc %}'{{ td }}'{% if forloop.last == false %},{% endif %}{% endfor %}];

var codeJson = [];

function teamUrl(n) {
    if (n < 1000)
        t = '0000';
    else
        t = Math.floor(n / 1000) * 1000;
    return '/frc' + t + '/' + n;
}

var filters = {
    year: [],
    language: [],
    team: [],
    codeType: []
};


function preDefinedFilter($filter, filterName) {
    $filter.find('li').on('click', function(ev) {
        var $el = $(this);
        $el.toggleClass('picked');
        var filterValues = [];
        $filter.find('li.picked').each(function(ev) {
            filterValues.push($(this).attr('data-filter-value'));
        });
        filters[filterName] = filterValues;
        renderTable(filters);
    });
    $filter.find('li').each(function() {
        var $el = $(this);
        var filterValue = $el.attr('data-filter-value');
        var filterCountQuery = {};
        filterCountQuery[filterName] = filterValue;
        $el.find('a span').before(' <span class="badge">' + getFilterCount(filterCountQuery) + '</span>');
    });
}


function userDefinedFilter($filter, filterName) {
    var $addFilterValueInput = $filter.find('input[name=addFilterValue]');
    var $addFilterValueForm = $filter.find('.add-filter-value-form');
    $addFilterValueForm.on('submit', function(ev) {
        ev.preventDefault();
        var filterValues = [];

        $filter.find('[data-filter-value]').each(function() {
            filterValues.push($(this).attr('data-filter-value'));  
        });
        var filterValue = $addFilterValueInput.val();
        var filterCountQuery = {};
        filterCountQuery[filterName] = filterValue;
        if (filterValues.indexOf(filterValue) < 0) {
            $('<li data-filter-value="' + filterValue + '" style="margin: 5px 10px;">' +
                '<span>' + filterValue +
                    ' <span class="badge">' + getFilterCount(filterCountQuery) + '</span>' +
                    '<a style="line-height: .8;" class="close">&times;</a></span>' +
            '</li>').appendTo($filter);
            filterValues.push(filterValue);
            $addFilterValueInput.val('');
        }
        filters[filterName] = filterValues;
        renderTable(filters);
    });
    $filter.on('click', '[data-filter-value] .close', function(ev) {
        var $filterValue = $(this).parents('[data-filter-value]');
        var filterValue = $filterValue.attr('data-filter-value');
        $filterValue.remove();
        var valueIndex = filters[filterName].indexOf(filterValue);
        if (valueIndex > -1) {
            filters[filterName].splice(valueIndex, 1);
        }
        renderTable(filters);
    });
}

function filterTeam(filters, year, team, code) {

    function intersection(a, b) {
        a = a.map(function(v) { return v.toLowerCase(); });
        b = b.map(function(v) { if(typeof v !== 'undefined') return v.toLowerCase(); });
        return a.filter(function(v) {
            return b.indexOf(v) > -1;
        });
    }

    code = code || {};
    filters = filters || {};
    ['language', 'year', 'team', 'codeType'].forEach(function(f) {
        if (typeof filters[f] === 'undefined') {
            filters[f] = [];
        } else if (!(filters[f] instanceof Array)) {
            filters[f] = [filters[f]];
        }
    });

    // Filter by year (2003, 2016)
    if (filters.year.length > 0 && filters.year.indexOf(year.toLowerCase()) < 0) return true;

    // Filter by team number
    if (filters.team.length > 0 && filters.team.indexOf(team.team.toString()) < 0) return true;

    // Filter by code type
    var codeType = Object.keys(code);
    if (filters.codeType.length > 0 && intersection(filters.codeType, codeType).length === 0) return true;

    // Filter by language
    var language = codeType
        .map(function(t) { return code[t][1]; })
        .filter(function(t) { return typeof(t) !== 'undefined' && t !== null; });

    if (filters.language.length > 0 && intersection(filters.language, language).length === 0) return true;

    return false;
}

function getFilterCount(filters) {
    var counter = 0;
    var codeData = d3.map();
    for (var i = 0; i < codeJson.length; i++) {
        var json = codeJson[i];
        for (var j = 0; j < json.length; j++) {
            var team = json[j];
            
            d3.entries(team.code).forEach(function(e){

                var year = codeData.get(e.key);
                if (!filterTeam(filters, e.key, team, e.value[0])) {
                    counter++;
                }
            });
        }
    }
    return counter;
} 


function renderTable(filters) {
    $('#codestuff').html('');
    
    // transform the json into something useful
    // bucket it by year
    var codeData = d3.map();
    
    for (var i = 0; i < codeJson.length; i++) {
        var json = codeJson[i];
        for (var j = 0; j < json.length; j++) {
            var team = json[j];
            
            d3.entries(team.code).forEach(function(e){

                var year = codeData.get(e.key);

                if (filterTeam(filters, e.key, team, e.value[0])) {
                    return;
                }

                if (year === undefined) {
                    year = [];
                    codeData.set(e.key, year);
                }
                
                year.push({'team': team.team, 'code': d3.entries(e.value[0])});
            });
        }
    }
    
    // for each bucket
    var buckets = codeData.entries().sort(function(a, b) { return b.key - a.key});
    
    for (var i = 0; i < buckets.length; i++) {
        var bucket = buckets[i];
        $('#codestuff').append('<h3>' + bucket.key + ' <span class="badge">' + bucket.value.length + '</span></h3>');
        
        var table = $('<table></table>').addClass('table');
        var tbody = $('<tbody></tbody>');
        var content = '';
        
        bucket.value.sort(function(a, b) { return a.team - b.team });
        
        bucket.value.forEach(function(team) {
            
            content += '<tr><td><a href="' + teamUrl(team.team) + '">' + team.team + '</a></td>';
            content += '<td><ul>';
            
            team.code.forEach(function(e) {
                content += '<li><a href="' + e.value[0] + '">' + e.key + ' (' + e.value[1] + ')</a></li>'
            });
            
            content += '</ul></td></tr>';
        });
        
        tbody.append(content);
        table.append(tbody);
        
        $('#codestuff').append(table);
    }    
}

$(document).ready(function(){
    // load all of the robot code data from JSON files in the various repos..
    for (var i = 0; i < teamdata.length; i++) {
        $.getJSON("/frc" + teamdata[i] + "/robotcode.json", function(data){
            codeJson.push(data);
        }).fail(function() {
            codeJson.push([]);
            $('#codestuff').append('<div class="alert alert-danger" role="alert">Error loading data!</div>');
        }).always(function(){
            var progress = (codeJson.length/teamdata.length)*100;
            $('#loading').css('width', progress + '%');
            
            if (codeJson.length == teamdata.length) {
                renderTable();
                $('#loadcontainer').hide();
                preDefinedFilter($('.language-filter'), 'language');
                preDefinedFilter($('.code-type-filter'), 'codeType');
                userDefinedFilter($('.year-filter'), 'year');
                userDefinedFilter($('.team-filter'), 'team');
            }
        });
    }
});

</script>


<script>
$(document).ready(function(){
    $('.dropdown-menu').on('click', function(ev){
        ev.stopPropagation();
    });
});
</script>


<span>Filter By: </span>

<!-- Year Filter -->
<div class="btn-group">
  <button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
    Year <span class="caret"></span>
  </button>
  <ul class="dropdown-menu user-defined-filter year-filter">
    <li style="margin: 0 5px 0 6px;">
        <div class="input-group">
            <form class="add-filter-value-form">
                <input type="input" class="form-control" name="addFilterValue" placeholder="Add Year" style="width: 105px;">
                <span class="input-group-btn">
                    <button class="btn btn-default add-filter-value-button" type="submit">
                        <span class="glyphicon glyphicon-plus" aria-hidden="true"></span>
                    </button>
                </span>
            </form>
        </div>
    </li>
  </ul>
</div>

<!-- Language Filter -->
<div class="btn-group">
  <button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
    Language <span class="caret"></span>
  </button>
  <ul class="dropdown-menu pre-defined-filter language-filter">
    <li class="" data-filter-value="java">
        <a href="#">
            Java<span style="float: right" class="glyphicon glyphicon-ok" aria-hidden="true"></span>
        </a>
    </li>
    <li class="" data-filter-value="kotlin">
        <a href="#">
            Kotlin<span style="float: right" class="glyphicon glyphicon-ok" aria-hidden="true"></span>
        </a>
    </li>
    <li class="" data-filter-value="c++">
        <a href="#">
            C++<span style="float: right" class="glyphicon glyphicon-ok" aria-hidden="true"></span>
        </a>
    </li>
    <li class="" data-filter-value="labview">
        <a href="#">
            LabVIEW<span style="float: right" class="glyphicon glyphicon-ok" aria-hidden="true"></span>
        </a>
    </li>
    <li class="" data-filter-value="python">
        <a href="#">
            Python<span style="float: right" class="glyphicon glyphicon-ok" aria-hidden="true"></span>
        </a>
    </li>
    <li class="" data-filter-value="javascript">
        <a href="#">
            JavaScript<span style="float: right" class="glyphicon glyphicon-ok" aria-hidden="true"></span>
        </a>
    </li>
    <li class="" data-filter-value="arduino">
        <a href="#">
            Arduino<span style="float: right" class="glyphicon glyphicon-ok" aria-hidden="true"></span>
        </a>
    </li>
    <li class="" data-filter-value="c">
        <a href="#">
            C<span style="float: right" class="glyphicon glyphicon-ok" aria-hidden="true"></span>
        </a>
    </li>
  </ul>
</div>

<!-- Team Number Filter -->
<div class="btn-group">
  <button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
    Team <span class="caret"></span>
  </button>
  <ul class="dropdown-menu user-defined-filter team-filter">
    <li style="margin: 0 5px 0 6px;">
        <div class="input-group">
            <form class="add-filter-value-form">
                <input type="input" class="form-control" name="addFilterValue" placeholder="Add Team" style="width: 105px;">
                <span class="input-group-btn">
                    <button class="btn btn-default add-filter-value-button" type="submit">
                        <span class="glyphicon glyphicon-plus" aria-hidden="true"></span>
                    </button>
                </span>
            </form>
        </div>
    </li>
  </ul>
</div>

<div class="btn-group">
  <button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
    Code Type <span class="caret"></span>
  </button>
  <ul class="dropdown-menu pre-defined-filter code-type-filter">
    <li class="" data-filter-value="robot">
        <a href="#">
            Robot<span style="float: right" class="glyphicon glyphicon-ok" aria-hidden="true"></span>
        </a>
    </li>
    <li class="" data-filter-value="vision">
        <a href="#">
            Vision<span style="float: right" class="glyphicon glyphicon-ok" aria-hidden="true"></span>
        </a>
    </li>
    <li class="" data-filter-value="dashboard">
        <a href="#">
            Dashboard<span style="float: right" class="glyphicon glyphicon-ok" aria-hidden="true"></span>
        </a>
    </li>
    <li class="" data-filter-value="scouting">
        <a href="#">
            Scouting<span style="float: right" class="glyphicon glyphicon-ok" aria-hidden="true"></span>
        </a>
    </li>
  </ul>
</div>


<div id="loadcontainer" class="progress progress-striped active">
   <div id="loading" class="progress-bar" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100">
       Loading...
    </div>
</div>

<div id="codestuff">
</div>