--- 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">×</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>