Skip to content

Instantly share code, notes, and snippets.

@taylorsmithgg
Last active June 1, 2017 03:56
Show Gist options
  • Save taylorsmithgg/c3d234b37c823be7695e to your computer and use it in GitHub Desktop.
Save taylorsmithgg/c3d234b37c823be7695e to your computer and use it in GitHub Desktop.
// https://github.com/taylorsmithgg
// A few code snippets from a current CMS project that I am developing for Detroit Labs that showcase using Angular
// to interact with RESTful services to populate a map dynamically.
// In lieu of Express, I am currently using Meteor, which supports 3-way data bindings.
// I am also using Angular Material for its directives and Babel for polyfill support
$scope.$on('mapInitialized', function(event, evtMap) {
map = evtMap;
map.singleInfoWindow = true;
});
$scope.mapClick = function(event, showInfoWindow, item) {
var info = item.post_name + '_info';
showInfoWindow(map, info, event.latLng);
$scope.setResult(item);
};
$scope.closeResult = function(){
$scope.showResult = false;
$scope.selectedResult = undefined;
var latLng = new window.google.maps.LatLng(44, -83);
map.setZoom(6);
map.setCenter(latLng);
};
$scope.setResult = function(result){
map.setZoom(15);
var latLng = new window.google.maps.LatLng(result.meta[0].gpsLatitude, result.meta[0].gpsLongitude);
console.log(latLng.lat(), latLng.lng());
console.log(typeof latLng.lat(), typeof latLng.lng());
map.setCenter(latLng);
$scope.selectedResult = result;
$scope.showResult = true;
$location.hash('top');
$anchorScroll();
};
// Simple factory example of CPLEX operations using glpk.js for optimizing daily fantasy football statistics
// I am currently in the process of rewriting this with React + Ionic with the intention of shipping for browser
// and native mobile.
app.factory('optimize', [function(){
return {
run: function(playerList, jsonConfig, salary, prevLineups, teams){
$('.throbber-loader').show();
var self = this;
var order = {QB: 1, RB: 2, WR: 3, TE: 4, FLEX: 5, K: 6,DST: 7};
var chooChoo = myHeartWillGoOn(playerList, prevLineups);
if(chooChoo.length == playerList.length){
return findTeam(jsonConfig.objective, playerList, jsonConfig);
} else {
return self.run(chooChoo, jsonConfig, salary, prevLineups, teams);
}
function findTeam(objective, playerList, config) {
var result = [];
var exclude = ""; // This is important for previous team removal!
var m = buildMaximize(objective, playerList);
var s = buildSubjectTo(salary, jsonConfig, playerList, prevLineups);
var b = buildBounds(playerList);
var g = buildGenerals(playerList);
try {
// This is important for previous team removal!
$.each(prevLineups, function (index, lineup) {
$.each(lineup, function (i, l) {
$.each(l.players, function (num, player) {
exclude += "+1 x" + player.id + "\n";
});
exclude += "<=" + ((l.players.length) - 1) + "\n";
});
});
var cplex = m + s + exclude + b + g;
var prob = glp_create_prob();
glp_read_lp_from_string(prob, null, cplex);
glp_scale_prob(prob, GLP_SF_AUTO);
var simplex = new SMCP({
presolve: GLP_ON
});
glp_simplex(prob, simplex);
glp_intopt(prob);
//var p = glp_mip_obj_val(prob);
// glp_simplex(prob, simplex), glp_intopt(prob), p = glp_mip_obj_val(prob), q = 1;
for (var q = 1; q <= glp_get_num_cols(prob); q++) {
if (glp_mip_col_val(prob, q) > 0) {
var playerResult = playerList.filter(function (player) {
return 'x' + player.id == glp_get_col_name(prob, q);
})[0];
playerResult ? result.push(playerResult) : '';
}
}
} catch(e) {
return {players: [], cplex: cplex};
}
return sortTeam({players: result, cplex: cplex}, config);
}
function sortTeam(team, config) {
var lineup = team.players;
var rosterspots = config.rosterspots;
$.each(lineup, function (i, player) {
if (rosterspots[player.position].min < 0) {
player.position = 'FLEX';
}
});
return {players: lineup, cplex: team.cplex};
}
function myHeartWillGoOn(playerList, prevLineups) {
prevLineups.length > 0 ? $.map(prevLineups, function(lineup){
return $.map(lineup, function(l){
$.each(l.players, function (index, player) {
var freq = frequency(prevLineups, player).number;
if(player.limit <= freq){
playerList.splice(playerList.indexOf(player), 1);
}
});
});
}) : '';
return playerList;
}
function buildMaximize(objective, players) {
var m = "Maximize\n";
$.each(players, function (idx, player) {
var objectiveValue = player[objective.value];
m += (parseFloat(objectiveValue) >= 0 ? '+ ' : '- ') + Math.abs(player[objective.value]).toString() + "\tx" + player.id + "\n";
});
m += '\n';
return m;
}
function buildSubjectTo(salary, config, players, resultSets) {
var s = "Subject To\n";
s += buildSubjectToSalary(salary, players, config);
s += buildSubjectToSpotCount(config, players, resultSets);
s += buildSubjectToTeamLimit(teams, config);
s += '\n';
return s;
}
function buildSubjectToSalary(salary, players, config) {
var sals = "";
var minSalary = salary.min;
var maxSalary = salary.max > config.salarycap ? config.salarycap : salary.max;
$.each(players, function (idx, player) {
sals += '+ ' + player.salary + ' x' + player.id + '\n';
});
return (minSalary > 0 ? sals + "=> " + minSalary + "\n" : "") + sals + "<= " + maxSalary + "\n\n";
}
//pos
function buildSubjectToSpotCount(config, players, resultSets) {
var s = "";
$.each(config.rosterspots, function (spot, info) {
var p = "\\* Position: " + spot + " *\\\n";
$.each(info.Positions, function (i, pos) {
var playersByPos = players.filter(function(player){
return player.position == pos;
});
$.each(playersByPos, function (i, player) {
p += '+ 1 ' + 'x' + player.id + '\n';
});
});
(info.min == info.max) ? s += p + "=" + info.min + "\n\n" : s += p + "=>" + info.min + "\n" + p + "<=" + info.max + "\n\n";
});
return s;
}
function frequency(resultSets, player){
var percentMap = $.map(resultSets, function(resultSet){
var mappedPlayers = $.map(resultSet, function(lineup){
var players = lineup.players || [];
return players.filter(function(resultPlayer){
return resultPlayer.id == player.id;
});
});
return mappedPlayers;
});
var results = {percent: (percentMap.length / (resultSets.length == 0 ? 1 : resultSets.length) * 100).toFixed(1), number: percentMap.length};
return results;
}
//team
function buildSubjectToTeamLimit(teams, config) {
var s = "";
$.each(teams, function (index, team) {
s += "\\* Team: " + team.short + " *\\\n";
var count = 0;
$.each(team.players, function(index, player){
s += '+ 1 ' + 'x' + player.id + '\n';
});
s += "<=" + config.max_per_team + "\n";
});
return s;
}
function buildBounds(players) {
var b = "Bounds\n";
$.each(players, function(idx, player) {
if (player.locked) {
b += 'x' + player.id + ' = 1\n';
} else {
b += "0 <= " + 'x' + player.id + " <= 1\n";
}
});
return b;
}
function buildGenerals(players) {
var g = "Generals\n";
$.each(players, function (idx, player) {
g += 'x' + player.id + "\n";
});
return g + "END\n";
}
}
}
}]);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment