Skip to content

Instantly share code, notes, and snippets.

@mforando
Last active August 24, 2019 14:37
Show Gist options
  • Save mforando/d3c72b1ccde46bc630bb5987ae38e4f2 to your computer and use it in GitHub Desktop.
Save mforando/d3c72b1ccde46bc630bb5987ae38e4f2 to your computer and use it in GitHub Desktop.
Fantasy Info
license: mit
<!DOCTYPE html>
<head>
<meta charset="utf-8">
<meta property="og:title" content="2019 Fantasy Football Information">
<meta property="og:description" content="Keeper Costs, Rules, and Draft Time Info">
<script src="https://d3js.org/d3.v4.min.js"></script>
<style>
body {
font-family:Helvetica;
margin:0;
top:0;right:0;bottom:0;left:0;
background:rgb(30,30,30);
font-size:.85rem;
}
h1{
padding-bottom:.5rem;
border-bottom:1px solid rgba(0,0,0,.7);
}
p{
}
#main{
max-width:1000px;
min-height:100vh;
margin:1rem auto;
padding:1rem;
padding-top:1rem;
outline:1px solid black;
-webkit-box-shadow: 0 0 20px 3px rgba(255,255,255,0.54);
-moz-box-shadow: 0 0 20px 3px rgba(255,255,255,0.55);
box-shadow: 0 0 20px 3px rgba(255,255,255,0.55);
background:rgba(245,245,245);
}
table
{
font-family:Helvetica;
font-size:1rem;
border-collapse: collapse;
width:100%;
margin:0 auto;
}
table th
{
border-bottom: 1px solid rgb(0,40,80);
border-right: none;
border-left: none;
padding: 4px;
text-align: left;
background-color: none;
color: black;
}
table td
{
border-bottom: 1px solid #ddd;
padding: 4px;
padding-top: 4px;
padding-bottom: 4px;
}
table tr:nth-child(even)
{
background-color: #f2f2f2;
}
#trophy1{
color: transparent;
text-shadow: 0 0 0 gold;
font-size:5rem;
width:5rem;
text-align:center;
display:inline-block;
vertical-align: middle;
}
#trophy2{
color: transparent;
text-shadow: 0 0 0 orange;
font-size:3rem;
height:4rem;
width:5rem;
text-align:center;
display:inline-block;
vertical-align: middle;
}
#trophy3{
color: transparent;
text-shadow: 0 0 0 brown;
font-size:2rem;
height:4rem;
width:5rem;
text-align:center;
vertical-align: middle;
display:inline-block;
}
}
.tropycont{
vertical-align: middle;
display:block;
width:100%;
}
.trophyLabel{
vertical-align: middle;
display:inline-block;
}
.wrapper {
position: relative;
}
[class|="confetti"] {
position: absolute;
}
.red {
background-color: #E94A3F;
}
.yellow {
background-color: #FAA040;
}
.blue {
background-color: #5FC9F5;
}
#teamselect{
margin-left:15px;
}
#chart{
width: 800px;
margin: 0 auto;
}
.background {
fill: #eee;
}
line {
stroke: #fff;
}
text.active {
fill: red;
}
.day {
fill: black;
stroke: black;
}
.month {
fill: none;
stroke: #fff;
stroke-width: 4px;
}
.year-title {
font-size: 1.5em;
}
/* color ranges */
.RdYlGn .q0-11{fill:rgb(165,0,38)}
.RdYlGn .q1-11{fill:rgb(215,48,39)}
.RdYlGn .q2-11{fill:rgb(244,109,67)}
.RdYlGn .q3-11{fill:rgb(253,174,97)}
.RdYlGn .q4-11{fill:rgb(254,224,139)}
.RdYlGn .q5-11{fill:rgb(255,255,191)}
.RdYlGn .q6-11{fill:rgb(217,239,139)}
.RdYlGn .q7-11{fill:rgb(166,217,106)}
.RdYlGn .q8-11{fill:rgb(102,189,99)}
.RdYlGn .q9-11{fill:rgb(26,152,80)}
.RdYlGn .q10-11{fill:rgb(0,104,55)}
.keeper{
border:2px solid rgb(100,0,0);
background:rgb(200,0,0);
color:white;
z-index:9999999;
background-color: rgb(200,0,0)!important;
}
</style>
</head>
<div id="main">
<h1 style="text-align:center;">2019 Fantasy Football</h1>
<h2>2018 League Winners</h2>
<div class="wrapper">
<div class="tropycont" id="firstplace"><span id="trophy1">&#127942;</span><span style="font-size:2rem" class="trophyLabel">1st Place: Ridley Me This</span></div>
<div class="tropycont" id="secondplace"><span id="trophy2">&#127942;</span><span style="font-size:1.5rem" class="trophyLabel">2nd Place: Gurley County</span></div>
<div class="tropycont" id="thirdplace"><span id="trophy3">&#127942;</span><span style="font-size:1rem" class="trophyLabel">3rd Place: Wentzylvania</span></div>
<br>
</div>
<p>Go to League Homepage: <a target="_blank" href="https://football.fantasysports.yahoo.com/f1/25991">https://football.fantasysports.yahoo.com/f1/25991</a></p>
<div id="lastyearsstandings">
</div>
<div id="keeperrules">
<h3>Keeper Rules:</h3>
<ul>
<li>Each team must keep 3 players</li>
<li>Lose the draft pick for the round you picked the player last year</li>
<li>Waiver wire pickups = lose last pick of the draft (No Penalty)</li>
<li>Keeper deadline = 1 week prior to live draft (Update - please send ASAP even though its prior to 1 week to the draft)</li>
<li>Draft pick trade deadline = 1 hr prior to live draft</li>
</ul>
</div>
<div id="draftdates">
<h3>Draft Date:</h>
<div><a target="_blank" href="https://doodle.com/poll/g3w7a6p2dzm256t6">Vote on a Draft Date</a>
</div>
<br>
<div>
<span>Select A Team:</span>
<select id="teamselect">
</select>
</div>
<br>
<h3>Keeper Cost Calculation</h3>
<p>Keeper costs are based on the draft round the player was drafted on in the prior year as well as the current ADP for a PRR, 14-team league on <a target="_blank" href="https://fantasyfootballcalculator.com/adp/ppr/14-team/all">Fantasy Football Calculator</a>. The calculations shown below are based on ADP data from 8-2-2019 and will be adjusted before the draft. Click the link to Fantasy Football Calculator to view the latest ADP data.</p>
<div id="keeperSelection">
</div>
<br>
<p>To select your keepers, <a id="googlesheetsLink" href="https://docs.google.com/spreadsheets/d/1anYR_XncubB6XvXNs7bwjfRH5xwuOm-xgzhsOna86-4/edit#gid=434476128" target="_blank">click this this link</a>. The keeper pool and information on this page will update shortly.</p>
<br>
<div id="finalRostersContainer">
</div>
<br>
<h3>ADP vs Current Keepers</h3>
<p>Players in bold red shown below have been selected to be kept.</p>
<div id="adpkeepers">
</div>
</div>
<script src='https://cdnjs.cloudflare.com/ajax/libs/tabletop.js/1.5.1/tabletop.min.js'></script>
<body>
<script>
function tabulate() {
//configure the table function for desired columns.
table.columns = function(value) {
//default in case a specification is not provided.
if (!arguments.length) return null;
columns = value;
//return the charting function with the new specifications.
return table;
};
table.showHeaders = function(value){
//if not specified, show headers by default
if (!arguments.length) return true;
showHeaders = value;
//return the charting function with the new specifications.
return table;
}
//this is the configurable charting function
function table(selection){
var columns = table.columns;
if(table.columns == null){
columns = Object.keys(selection.data()[0].values[0])
}
var tablecont = selection.append('table')
if(table.showHeaders){
var thead = tablecont.append('thead')
}
var tbody = tablecont.append('tbody');
var data = selection.data();
console.log(data)
var headers = selection.select("thead")
.append('tr')
.selectAll('th')
.data(columns)
headers.enter()
.append('th')
.merge(headers)
.text(function (column) {return column;});
var rows = tbody.selectAll('tr')
.data(function(d){return d.values})
.enter()
.append('tr');
var cells = rows.selectAll('td')
.data(function (row) {
return columns.map(function (column,i) {
return {column: column, value: row[column]};
});
})
.enter()
.append('td')
.text(function (d) { return d.value; });
}
//return the configured table function.
return table;
}
var public_spreadsheet_url = 'https://docs.google.com/spreadsheets/d/1anYR_XncubB6XvXNs7bwjfRH5xwuOm-xgzhsOna86-4/edit?usp=sharing';
function renderSpreadsheetData() {
Tabletop.init( { key: public_spreadsheet_url,
callback: draw,
simpleSheet: false } )
}
function draw(data, tabletop) {
// draw chart
//parse results
data.DraftOrder.elements.forEach(function(d){
d.Moves = +d.Moves;
d.Pick = +d.Pick;
d.PtsFor = +d.PtsFor;
})
console.log(data.adp.elements)
//adp
//parse results
data.adp.elements.forEach(function(d){
d.Overall = +d.Overall;
})
//DraftOrder
updateDraftOrder(data.DraftOrder.elements.sort(function(a,b){return d3.ascending(a.Pick,b.Pick)}))
//parse results
data.PickData.elements.forEach(function(d){
d.DraftPick = +d.DraftPick;
d.DraftRound = +d.DraftRound;
d.TeamPick = +d.TeamPick;
})
var nested = d3.nest().key(function(d){return d.Team}).entries(data.PickData.elements)
var teamnames = nested.map(function(d){return d.key})
var options = d3.select("#teamselect").selectAll("option").data(teamnames)
options.enter()
.append("option")
.attr("value",function(d){return d})
.text(function(d){return d})
d3.select("#teamselect").on("change",function(){
var selected = d3.select(this).property("value")
updatePickTable(nested.filter(function(d){return d.key == selected})[0])
updateKeepersTable(rosternest.filter(function(d){return d.key == selected})[0])
updateLink(data.DraftOrder.elements.filter(function(d){return d.Team == selected})[0])
})
data.finalrosters.elements.forEach(function(d){
d.DraftRound = +d.DraftRound;
d.ADPRound = +d.ADPRound;
d.FinalCost = +d.FinalCost;
d.Adjustment = +d.Adjustment;
d.CurrentADP = +d.CurrentADP;
if(d.CurrentADP == 0){
d.CurrentADP = null
}
d.KeeperCost = +d.KeeperCost;
})
var rosternest = d3.nest().key(function(d){return d.Team}).entries(data.finalrosters.elements)
updatePickTable(nested[0])
updateKeepersTable(rosternest[0])
updateADP(data.adp.elements)
updateLink(data.DraftOrder.elements[0])
}
function updateLink(draftorder){
d3.select("#googlesheetsLink")
.attr("href","https://docs.google.com/spreadsheets/d/1anYR_XncubB6XvXNs7bwjfRH5xwuOm-xgzhsOna86-4/edit#gid=" + draftorder.GoogleID)
}
function updateADP(draftorder){
var draftOrderTable = tabulate();
draftOrderTable.columns = ["ADP","Overall","Name","Position","Team"];
draftOrderTable.showHeaders = true;
var nest = d3.nest().key(function(d){return "ADP & Keeper Status"}).entries(draftorder)[0]
var containers = d3.select("#adpkeepers").selectAll(".containers").data([nest],function(d){return d.key})
containers.enter()
.append("div")
.attr("class","containers")
.merge(containers)
.call(draftOrderTable)
containers.exit().remove();
d3.select("#adpkeepers").selectAll(".containers").selectAll("tr").classed("keeper",function(d){
if(d.KeeperFlag=="True"){
return true
}
})
}
function updateDraftOrder(draftorder){
var draftOrderTable = tabulate();
draftOrderTable.columns = ["Pick","Rank","Team","WLT","PtsAgainst","PtsFor","Moves"];
draftOrderTable.showHeaders = true;
var nest = d3.nest().key(function(d){return "2019 Draft Order"}).entries(draftorder)[0]
var containers = d3.select("#lastyearsstandings").selectAll(".containers").data([nest],function(d){return d.key})
containers.enter()
.append("div")
.attr("class","containers")
.merge(containers)
.html(function(d){return "<h2>" + d.key + "</h2>"})
.call(draftOrderTable)
containers.exit().remove();
}
function updatePickTable(teamdata){
teamdata.values = teamdata.values.sort(function(a,b){return d3.ascending(a.FinalCost,b.FinalCost)})
var teamPickTable = tabulate();
teamPickTable.columns = ["DraftRound","DraftPick","Keeper","Notes"];
teamPickTable.showHeaders = true;
var containers = d3.select("#finalRostersContainer").selectAll(".containers").data([teamdata],function(d){return d.key})
containers.enter()
.append("div")
.attr("class","containers")
.merge(containers)
// .html(function(d){return "<h2>" + d.key + "</h2>"})
.call(teamPickTable)
containers.exit().remove();
}
function updateKeepersTable(teamdata){
var teamKeeperTable = tabulate();
teamKeeperTable.columns = ["Player","DraftRound","KeeperCost","CurrentADP","ADPRound","Adjustment","FinalCost"];
teamKeeperTable.showHeaders = true;
var containers = d3.select("#keeperSelection").selectAll(".containers").data([teamdata],function(d){
console.log(d)
return d.key})
containers.enter()
.append("div")
.attr("class","containers")
.merge(containers)
// .html(function(d){return "<h2>" + d.key + "</h2>"})
.call(teamKeeperTable)
containers.exit().remove();
}
renderSpreadsheetData();
for (var i = 0; i < 200; i++) {
create(i);
}
function create(i) {
var width = Math.random() * 8;
var height = width * 0.4;
var colourIdx = Math.ceil(Math.random() * 3);
var colour = "red";
switch(colourIdx) {
case 1:
colour = "yellow";
break;
case 2:
colour = "blue";
break;
default:
colour = "red";
}
d3.select(".wrapper")
.append("div")
.attr("class",function(d){return "confetti-" + i + " " + colour})
.style("width",width + "px")
.style("height",height + "px")
.style("top",Math.random()*100+"%")
.style("left",Math.random()*100+"%")
.style("opacity",Math.random()+0.5)
.style("transform","rotate(" + Math.random()*360 + "deg")
drop(i);
}
function drop(x) {
d3.selectAll('.confetti-'+x)
.transition()
.delay(function(d){
return Math.random()*100})
.duration(function(d){
var startingPoint = +d3.select(this).style("top").replace("%", "")
var duration = 3000 * (100-startingPoint)/100
return Math.random()*duration + duration
})
.ease(d3.easeCubicIn)
.style("top","100%")
.style("left",function(){
var startingPoint = +d3.select(this).style("left").replace("%", "")
return +(Math.random()-.5)*15 + startingPoint+"%";
})
.on("end",function(){
reset(x)
})
}
function reset(x) {
d3.selectAll('.confetti-'+x)
.style("top",Math.random()*40+"%")
.style("left",Math.random()*100+"%")
drop(x);
}
</script>
</body>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment