幫你把立委在國會表決的結果畫成一目了然的圖表! Generated with http://bl.ocks.org/4248542
-
-
Save clkao/4290860 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
html, body { | |
width: 100%; | |
height:100% | |
} | |
.mly-seat { | |
/*stroke: #f00*/ | |
cursor: pointer; | |
} | |
.mly-vote { | |
font-family: arial; | |
} | |
.mly-name { | |
font-size: 15px; | |
cursor: pointer; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<meta charset="utf-8"> | |
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> | |
<meta name="viewport" content="width=device-width"> | |
<title>立法委員投票結果</title> | |
<link rel="shortcut icon" href="favicon.ico"> | |
<script type="text/javascript" src="http://crypto-js.googlecode.com/svn/tags/3.0.2/build/rollups/md5.js"></script> | |
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script> | |
<script type="text/javascript" src="http://d3js.org/d3.v3.min.js"></script> | |
<link rel="stylesheet" type="text/css" href="index.css"> | |
<script type="text/javascript" src="lyvote.js"></script> | |
<script type="text/javascript" src="index.js"></script> | |
</head> | |
<body> | |
<div id="nuke" class="twlyvote ad-8 session-2 sitting-13"><span class="approval">許忠信 蔡煌瑯 李俊俋 葉宜津 鄭麗君 林岱樺 黃文玲 薛凌 蔡其昌 張曉風 許智傑 吳秉叡 陳唐山 林世嘉 黃偉哲 柯建銘 陳其邁 高志鵬 林淑芬 陳亭妃 何欣純 潘孟安 魏明谷 趙天麟 劉櫂豪 林佳龍 楊曜 姚文智 李應元 劉建國 李昆澤 陳歐珀 邱志偉 管碧玲 陳節如 蘇震清 蕭美琴 段宜康 陳明文 吳宜臻 丁守中 許添財 邱議瑩 尤美女 田秋堇</span><span class="veto">曾巨威 林德福 王進士 李鴻鈞 賴士葆 蔡正元 黃昭順 鄭汝芬 江惠貞 蔡錦隆 陳碧涵 楊玉欣 吳育昇 楊瓊瓔 盧嘉辰 江啟臣 徐欣瑩 林國正 徐少萍 孫大千 林鴻池 翁重鈞 廖國棟 林滄敏 蘇清泉 李貴敏 費鴻泰 林明溱 謝國樑 陳超明 潘維剛 楊應雄 楊麗環 紀國棟 陳根德 陳鎮湘 詹凱臣 王廷升 盧秀燕 徐耀昌 孔文吉 王育敏 簡東明 陳淑慧 吳育仁 林郁方 張慶忠</span><span class="abstention">邱文彥</span></div> | |
</body> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
!!! 5 | |
html(lang="en") | |
head | |
meta(charset='utf-8') | |
meta(http-equiv="X-UA-Compatible", content="IE=edge,chrome=1") | |
meta(name='viewport', content='width=device-width') | |
title 立法委員投票結果 | |
link(rel="shortcut icon",href="favicon.ico") | |
script(type="text/javascript",src="http://crypto-js.googlecode.com/svn/tags/3.0.2/build/rollups/md5.js") | |
script(type="text/javascript",src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js") | |
script(type="text/javascript",src="http://d3js.org/d3.v3.min.js") | |
link(rel="stylesheet",type="text/css",href="index.css") | |
script(type="text/javascript",src="lyvote.js") | |
script(type="text/javascript",src="index.js") | |
body | |
#nuke.twlyvote.ad-8.session-2.sitting-13 | |
span.approval 許忠信 蔡煌瑯 李俊俋 葉宜津 鄭麗君 林岱樺 黃文玲 薛凌 蔡其昌 張曉風 許智傑 吳秉叡 陳唐山 林世嘉 黃偉哲 柯建銘 陳其邁 高志鵬 林淑芬 陳亭妃 何欣純 潘孟安 魏明谷 趙天麟 劉櫂豪 林佳龍 楊曜 姚文智 李應元 劉建國 李昆澤 陳歐珀 邱志偉 管碧玲 陳節如 蘇震清 蕭美琴 段宜康 陳明文 吳宜臻 丁守中 許添財 邱議瑩 尤美女 田秋堇 | |
span.veto 曾巨威 林德福 王進士 李鴻鈞 賴士葆 蔡正元 黃昭順 鄭汝芬 江惠貞 蔡錦隆 陳碧涵 楊玉欣 吳育昇 楊瓊瓔 盧嘉辰 江啟臣 徐欣瑩 林國正 徐少萍 孫大千 林鴻池 翁重鈞 廖國棟 林滄敏 蘇清泉 李貴敏 費鴻泰 林明溱 謝國樑 陳超明 潘維剛 楊應雄 楊麗環 紀國棟 陳根德 陳鎮湘 詹凱臣 王廷升 盧秀燕 徐耀昌 孔文吉 王育敏 簡東明 陳淑慧 吳育仁 林郁方 張慶忠 | |
span.abstention 邱文彥 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(function(){ | |
$(function(){ | |
return lyvote.render({ | |
/* optional argument */ | |
cx: 600, | |
cy: 500, | |
transform: "scale(0.8)", | |
seatMapping: lyvote.map.linear | |
/* required argument */, | |
namelist: "voter.json", | |
node: '#nuke' | |
}); | |
}); | |
}).call(this); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<- $ | |
lyvote.render do | |
/* optional argument */ | |
cx: 600 | |
cy: 500 # chart center coordinate | |
transform: "scale(0.8)" # chart transformation | |
#seat-count: [12 16 18 22 24 21] # seat count in each row, totally 6 rows. auto-gen if not provided | |
seat-mapping: lyvote.map.linear | |
/* required argument */ | |
namelist: "voter.json" # e.g., mly-8.json | |
node: \#nuke # tag selector in string | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(function(){ | |
var slice$ = [].slice, split$ = ''.split; | |
this.lyvote = { | |
svg: null, | |
config: { | |
cx: 500, | |
cy: 500, | |
transform: "", | |
node: 'body' | |
}, | |
colors: { | |
"KMT": '#55f', | |
"DPP": '#090', | |
"NSU": '#fbb', | |
"TSU": '#b26', | |
"PFP": '#f90', | |
"N/A": '#bbb', | |
'null': '#bbb' | |
}, | |
map: { | |
qsort: { | |
idx: 0, | |
map: {}, | |
order: null, | |
limit: 0, | |
init: function(r){ | |
var len, res$, i$, it, ref$, len$, t, i, results$ = []; | |
len = r.config.seatCount.reduce(curry$(function(x$, y$){ | |
return x$ + y$; | |
})); | |
this.limit = 0; | |
res$ = []; | |
for (i$ = 0; i$ < len; ++i$) { | |
it = i$; | |
res$.push(it); | |
} | |
this.order = res$; | |
res$ = []; | |
for (i$ = 0, len$ = (ref$ = this.order).length; i$ < len$; ++i$) { | |
it = ref$[i$]; | |
res$.push([it, r.seatPosition(it)[0]]); | |
} | |
this.order = res$; | |
for (i$ = 0; i$ < len; ++i$) { | |
it = i$; | |
ref$ = [this.order[it], it + parseInt(Math.random() * (len - it))], t = ref$[0], i = ref$[1]; | |
this.order[it] = this.order[i]; | |
results$.push(this.order[i] = t); | |
} | |
return results$; | |
}, | |
_sort: function(r, limit, level, L, R){ | |
var pi, t, p, i, j; | |
if (level > limit) { | |
return; | |
} | |
if (L >= R) { | |
return; | |
} | |
pi = L + parseInt(Math.random() * (R - L + 1)); | |
t = this.order[L]; | |
this.order[L] = this.order[pi]; | |
this.order[pi] = t; | |
p = this.order[L][1]; | |
i = L + 1; | |
j = R; | |
while (i < j) { | |
while (this.order[i][1] <= p && i < j) { | |
i++; | |
} | |
while (this.order[j][1] > p) { | |
j--; | |
} | |
if (i >= j) { | |
break; | |
} | |
t = this.order[i]; | |
this.order[i] = this.order[j]; | |
this.order[j] = t; | |
} | |
t = this.order[L]; | |
this.order[L] = this.order[j]; | |
this.order[j] = t; | |
this._sort(r, limit, level + 1, L, j - 1); | |
return this._sort(r, limit, level + 1, j + 1, R); | |
}, | |
sort: function(r){ | |
return this._sort(r, this.limit++, 0, 0, this.order.length - 1); | |
}, | |
indexOf: function(r, name){ | |
var ref$, ref1$; | |
return this.order[(ref1$ = (ref$ = this.map)[name]) != null | |
? ref1$ | |
: ref$[name] = this.idx++][0]; | |
} | |
}, | |
xorder: { | |
idx: 0, | |
map: {}, | |
order: null, | |
indexOf: function(r, name){ | |
var it, ref$, ref1$; | |
if (!this.order) { | |
this.order = (function(){ | |
var i$, to$, fn$ = curry$(function(x$, y$){ | |
return x$ + y$; | |
}), results$ = []; | |
for (i$ = 0, to$ = r.config.seatCount.reduce(fn$); i$ < to$; ++i$) { | |
it = i$; | |
results$.push([it, r.seatPosition(it)[0]]); | |
} | |
return results$; | |
}()).sort(function(a, b){ | |
return a[1] - b[1]; | |
}); | |
} | |
return this.order[(ref1$ = (ref$ = this.map)[name]) != null | |
? ref1$ | |
: ref$[name] = this.idx++][0]; | |
} | |
}, | |
strip: { | |
idx: 0, | |
map: {}, | |
order: null, | |
indexOf: function(r, name){ | |
var len, ref$, ref1$; | |
if (!this.order) { | |
len = r.config.seatCount.reduce(curry$(function(x$, y$){ | |
return x$ + y$; | |
})); | |
this.order = (function(){ | |
var i$, to$, results$ = []; | |
for (i$ = 0, to$ = len; i$ <= to$; i$ += 2) { | |
results$.push(i$); | |
} | |
return results$; | |
}()).concat((function(){ | |
var i$, to$, results$ = []; | |
for (i$ = 1, to$ = len; i$ <= to$; i$ += 2) { | |
results$.push(i$); | |
} | |
return results$; | |
}())); | |
} | |
return this.order[(ref1$ = (ref$ = this.map)[name]) != null | |
? ref1$ | |
: ref$[name] = this.idx++]; | |
} | |
}, | |
circular: { | |
idx: 0, | |
map: {}, | |
order: null, | |
indexOf: function(r, name){ | |
var it, ref$, ref1$; | |
if (!this.order) { | |
this.order = (function(){ | |
var i$, to$, fn$ = curry$(function(x$, y$){ | |
return x$ + y$; | |
}), results$ = []; | |
for (i$ = 0, to$ = r.config.seatCount.reduce(fn$); i$ < to$; ++i$) { | |
it = i$; | |
results$.push([ | |
it, fn1$( | |
r.seatPosition(it)) | |
]); | |
} | |
return results$; | |
function fn1$(it){ | |
return [it[0] - r.config.cx, it[1]].reduce(function(a, b){ | |
return a + Math.pow(b, 2); | |
}, 0); | |
} | |
}()).sort(function(a, b){ | |
return a[1] - b[1]; | |
}); | |
} | |
return this.order[(ref1$ = (ref$ = this.map)[name]) != null | |
? ref1$ | |
: ref$[name] = this.idx++][0]; | |
} | |
}, | |
linear: { | |
idx: 0, | |
map: {}, | |
order: null, | |
indexOf: function(r, name){ | |
var ref$, ref1$; | |
return (ref1$ = (ref$ = this.map)[name]) != null | |
? ref1$ | |
: ref$[name] = this.idx++; | |
} | |
}, | |
random: { | |
idx: 0, | |
map: {}, | |
order: null, | |
indexOf: function(r, name){ | |
var len, res$, i$, it, ref$, t, i, ref1$; | |
if (!this.order) { | |
len = r.config.seatCount.reduce(curry$(function(x$, y$){ | |
return x$ + y$; | |
})); | |
res$ = []; | |
for (i$ = 0; i$ < len; ++i$) { | |
it = i$; | |
res$.push(it); | |
} | |
this.order = res$; | |
for (i$ = 0; i$ < len; ++i$) { | |
it = i$; | |
ref$ = [this.order[it], it + parseInt(Math.random() * (len - it))], t = ref$[0], i = ref$[1]; | |
this.order[it] = this.order[i]; | |
this.order[i] = t; | |
} | |
} | |
return this.order[(ref1$ = (ref$ = this.map)[name]) != null | |
? ref1$ | |
: ref$[name] = this.idx++]; | |
} | |
} | |
}, | |
_idx: 0, | |
_map: {}, | |
seatMappingDefault: function(name){ | |
var ref$, ref1$; | |
return (ref1$ = (ref$ = this._map)[name]) != null | |
? ref1$ | |
: ref$[name] = this._idx++; | |
}, | |
seatMapping: function(name){ | |
if (this.config.seatMapping) { | |
return this.config.seatMapping.indexOf.call(this.config.seatMapping, this, name); | |
} else { | |
return this.map.random.indexOf(this, name); | |
} | |
}, | |
remap: function(mapObj){ | |
var _pt, this$ = this; | |
this.config.seatMapping = mapObj; | |
_pt = function(it){ | |
return this$.seatPosition(this$.seatMapping(it.name)); | |
}; | |
return this.seats.transition().duration(750).attr('transform', function(it){ | |
return "translate(" + _pt(it)[0] + "," + _pt(it)[1] + ")"; | |
}); | |
}, | |
seatPosition: function(idx){ | |
var sc, res$, i$, len$, i, ret, ref$, row, len, j, m, v, fn$ = curry$(function(x$, y$){ | |
return x$ + y$; | |
}); | |
sc = this.config.seatCount; | |
res$ = []; | |
for (i$ = 0, len$ = sc.length; i$ < len$; ++i$) { | |
i = i$; | |
res$.push(slice$.call(sc, 0, i + 1 || 9e9).reduce(fn$)); | |
} | |
sc = res$; | |
ret = sc.map(function(it){ | |
return it - idx; | |
}).filter((function(it){ | |
return it > 0; | |
})); | |
ref$ = [this.config.seatCount.length, ret.length], row = ref$[0], len = ref$[1]; | |
ref$ = [row - len, ret[0] - 1, sc[row - len] - 1 - (len < row && sc[row - len - 1]) || 0], i = ref$[0], j = ref$[1], m = ref$[2]; | |
v = [Math.cos(Math.PI * j / m), Math.sin(Math.PI * j / m)]; | |
return [this.config.cx + v[0] * (160 + i * 60), this.config.cy - v[1] * (160 + i * 60)]; | |
}, | |
seats: null, | |
hName: {}, | |
hParty: {}, | |
generate: function(error, mlys){ | |
var ref$, _sc, _sc_total, idx, i$, len$, mly, key$, i, names, j$, len1$, name, defs, imgs, panel, _pt, it, lockcell, this$ = this; | |
ref$ = [ | |
{}, { | |
0: 0 | |
} | |
], this.hName = ref$[0], this.hParty = ref$[1]; | |
if (!this.config.seatCount) { | |
_sc = [0, 1, 2, 3, 4, 5].map(function(it){ | |
return parseInt(2 * Math.PI * (it * 60 + 160)); | |
}); | |
_sc_total = _sc.reduce(curry$(function(x$, y$){ | |
return x$ + y$; | |
})); | |
this.config.seatCount = _sc.map(function(it){ | |
return Math.round(it * mlys.length / _sc_total); | |
}); | |
} | |
idx = 0; | |
for (i$ = 0, len$ = mlys.length; i$ < len$; ++i$) { | |
mly = mlys[i$]; | |
this.hName[mly.name] = { | |
name: mly.name, | |
vote: 0, | |
party: mly.party, | |
idx: idx++ | |
}; | |
(ref$ = this.hParty)[key$ = mly.party] == null && (ref$[key$] = this.hParty[0]++); | |
} | |
for (i$ = 0, len$ = (ref$ = this.config.vote).length; i$ < len$; ++i$) { | |
i = i$; | |
names = ref$[i$]; | |
for (j$ = 0, len1$ = names.length; j$ < len1$; ++j$) { | |
name = names[j$]; | |
this.hName[name].vote = i + 1; | |
} | |
} | |
this.svg = d3.select(this.config.node).append('svg').attr('width', '100%').attr('height', '100%'); | |
defs = this.svg.selectAll('defs').data(mlys).enter().append('pattern').attr('id', function(it){ | |
return 'defs_h' + this$.hName[it.name].idx; | |
}).attr('patternUnits', 'userSpaceOnUse').attr('x', 30).attr('y', 30).attr('width', 50).attr('height', 50); | |
imgs = defs.append('image').attr('xlink:href', function(it){ | |
return "http://avatars.io/50a65bb26e293122b0000073/" + CryptoJS.MD5('MLY/' + it.name).toString() + "?size=small"; | |
}).attr('x', 0).attr('y', 0).attr('width', 50).attr('height', 50).attr('transform', "scale(0.9)"); | |
panel = this.svg.append('g').attr('transform', function(){ | |
return this$.config.transform; | |
}); | |
_pt = function(it){ | |
return this$.seatPosition(this$.seatMapping(it.name)); | |
}; | |
this.seats = panel.selectAll('g.seat').data((function(){ | |
var results$ = []; | |
for (it in this.hName) { | |
results$.push(this.hName[it]); | |
} | |
return results$; | |
}.call(this)).sort(function(a, b){ | |
return this$.hParty[a.party] - this$.hParty[b.party]; | |
})).enter().append('g').attr('transform', function(it){ | |
return "translate(" + _pt(it)[0] + "," + _pt(it)[1] + ")"; | |
}); | |
lockcell = null; | |
this.seats.append('circle').attr('class', 'mly-seat').attr('r', 20).attr('fill', function(it){ | |
return this$.colors[it.party]; | |
}).style('opacity', function(it){ | |
if (it.vote === 0) { | |
return 0.3; | |
} else { | |
return 1; | |
} | |
}).on('click', function(){ | |
if (lockcell) { | |
d3.select(lockcell).attr('fill', function(it){ | |
return this$.colors[it.party]; | |
}).transition().duration(500).attr('transform', "scale(1)").attr('stroke', 'none').style('opacity', function(it){ | |
if (it.vote === 0) { | |
return 0.3; | |
} else { | |
return 1; | |
} | |
}); | |
} | |
if (lockcell === d3.event.target) { | |
return lockcell = null; | |
} | |
lockcell = d3.event.target; | |
return d3.select(d3.event.target).attr('fill', function(it){ | |
return "url(#defs_h" + it.idx + ")"; | |
}).transition().duration(500).attr('transform', "scale(2)").attr('stroke', function(it){ | |
return this$.colors[it.party]; | |
}).attr('stroke-width', '3px').style('opacity', 1); | |
}); | |
this.seats.append('path').attr('d', function(it){ | |
switch (it.vote) { | |
case 1: | |
return "M-12 0 L0 10 L11 -11"; | |
case 2: | |
return "M-10,-10 L10,10 L0 0 L-10 10 L10 -10"; | |
case 3: | |
return "M-10 0 L10 00"; | |
case 9: | |
return "M15 0 A15 15 0 1 1 -15 0 A15 15 0 1 1 15 0"; | |
default: | |
return "M0 0"; | |
} | |
}).attr('stroke', function(it){ | |
switch (it.vote) { | |
case 1: | |
return '#0b0'; | |
case 2: | |
return '#b00'; | |
case 3: | |
return '#999'; | |
default: | |
return '#b00'; | |
} | |
}).attr('stroke-width', '5px').attr('fill', 'none'); | |
this.seats.append('rect').attr('class', 'mly-name-box').attr('x', -25).attr('y', 9).attr('width', 50).attr('height', 17).attr('rx', 10).attr('ry', 10).attr('fill', '#fff').style('opacity', 0.4); | |
return this.seats.append('text').attr('class', 'mly-name').attr('y', 22).attr('text-anchor', 'middle').text(function(it){ | |
return it.name; | |
}); | |
}, | |
render: function(config){ | |
var x$, this$ = this; | |
if (!config.vote) { | |
x$ = $(config.node); | |
x$.find('span.approval').each(function(){ | |
return (config.vote || (config.vote = []))[0] = split$.call($(this).text(), ' '); | |
}); | |
x$.find('span.veto').each(function(){ | |
return (config.vote || (config.vote = []))[1] = split$.call($(this).text(), ' '); | |
}); | |
x$.find('span.abstention').each(function(){ | |
return (config.vote || (config.vote = []))[2] = split$.call($(this).text(), ' '); | |
}); | |
x$.find('span').hide(); | |
} | |
import$(this.config, config); | |
return d3.json(config.namelist, function(error, json){ | |
return this$.generate.call(this$, error, json); | |
}); | |
} | |
}; | |
function curry$(f, args){ | |
return f.length > 1 ? function(){ | |
var params = args ? args.concat() : []; | |
return params.push.apply(params, arguments) < f.length && arguments.length ? | |
curry$.call(this, f, params) : f.apply(this, params); | |
} : f; | |
} | |
function import$(obj, src){ | |
var own = {}.hasOwnProperty; | |
for (var key in src) if (own.call(src, key)) obj[key] = src[key]; | |
return obj; | |
} | |
}).call(this); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@lyvote = | |
svg: null | |
config: | |
cx: 500 | |
cy: 500 | |
#seat-count: [12 16 18 22 24 21] now seat-count is auto-calculated | |
transform: "" | |
node: \body | |
colors: | |
"KMT": \#55f | |
"DPP": \#090 | |
"NSU": \#fbb | |
"TSU": \#b26 | |
"PFP": \#f90 | |
"N/A": \#bbb | |
null: \#bbb | |
map: | |
qsort: | |
idx: 0 | |
map: {} | |
order: null | |
limit: 0 | |
init: (r) -> | |
len = r.config.seat-count.reduce (+) | |
@limit = 0 | |
@order = [it for it til len] | |
@order = [[it,(r.seat-position it)0] for it in @order] | |
for it til len | |
[t,i] = [@order[it],it + parseInt Math.random! * (len - it)] | |
@order[it] = @order[i] | |
@order[i] = t | |
_sort: (r, limit, level, L, R) -> | |
if level>limit then return | |
if L>=R then return | |
pi = L + parseInt Math.random! * (R - L + 1 ) | |
t = @order[L] | |
@order[L] = @order[pi] | |
@order[pi] = t | |
p = @order[L]1 | |
i = L+1 | |
j = R | |
while i < j | |
while @order[i]1<=p and i<j | |
i++ | |
while @order[j]1>p | |
j-- | |
if i>=j then break | |
t = @order[i] | |
@order[i] = @order[j] | |
@order[j] = t | |
t = @order[L] | |
@order[L] = @order[j] | |
@order[j] = t | |
@_sort(r, limit, level+1, L, j-1) | |
@_sort(r, limit, level+1, j+1, R) | |
sort: (r) -> | |
@_sort(r, @limit++, 0, 0, @order.length-1) | |
indexOf: (r, name) -> | |
@order[@map[name] ?= @idx++ ]0 | |
xorder: | |
idx: 0 | |
map: {} | |
order: null | |
indexOf: (r, name) -> | |
if !@order | |
@order = [[it,(r.seat-position it)0] for it til r.config.seat-count.reduce (+)].sort (a,b) -> a[1]-b[1] | |
return @order[@map[name] ?= @idx++ ]0 | |
strip: | |
idx: 0 | |
map: {} | |
order: null | |
indexOf: (r, name) -> | |
if !@order | |
len = r.config.seat-count.reduce (+) | |
@order = [0 to len by 2] +++ [1 to len by 2] | |
@order[@map[name] ?= @idx++ ] | |
circular: | |
idx: 0 | |
map: {} | |
order: null | |
indexOf: (r, name) -> | |
if !@order | |
@order = [[it, (r.seat-position it)|> -> [it[0]-r.config.cx,it[1]] .reduce ((a,b)->a+b**2),0] for it til r.config.seat-count.reduce (+)].sort (a,b) -> a[1]-b[1] | |
return @order[@map[name] ?= @idx++ ]0 | |
linear: | |
idx: 0 | |
map: {} | |
order: null | |
indexOf: (r, name) -> | |
return @map[name] ?= @idx++ | |
random: | |
idx: 0 | |
map: {} | |
order: null | |
indexOf: (r, name) -> | |
if !@order | |
len = r.config.seat-count.reduce (+) | |
@order = [it for it til len] | |
for it til len | |
[t,i] = [@order[it],it + parseInt Math.random! * (len - it)] | |
@order[it] = @order[i] | |
@order[i] = t | |
return @order[@map[name] ?= @idx++ ] | |
_idx: 0 | |
_map: {} | |
seat-mapping-default: (name) -> | |
@_map[name] ?= @_idx++ | |
seat-mapping: (name) -> | |
if @config.seat-mapping then @config.seat-mapping.indexOf .call @config.seat-mapping,@,name | |
else @map.random.indexOf @,name | |
remap: (map-obj) -> | |
@config.seat-mapping = map-obj | |
_pt = ~> @seat-position @seat-mapping it.name | |
@seats.transition! .duration 750 .attr \transform ~> "translate(#{(_pt it)0},#{(_pt it)1})" | |
seat-position: (idx) -> | |
sc = @config.seat-count | |
sc = [sc[to i].reduce (+) for ,i in sc] | |
ret = (sc.map (-> it - idx) .filter (> 0)) | |
[row, len] = [@config.seat-count.length, ret.length] | |
[i,j,m] = [row - len, ret[0]-1, sc[row - len] - 1 - (len<row && sc[row - len-1]) || 0 ] | |
v = [ Math.cos(Math.PI*j/m), Math.sin Math.PI*j/m ] | |
[ @config.cx + v[0]*(160+ i*60) , @config.cy - v[1]*(160 + i*60) ] | |
seats: null | |
h-name: {} | |
h-party: {} | |
generate: (error, mlys) -> | |
[@h-name,@h-party] = [{} {0:0}] | |
if !@config.seat-count | |
_sc = [0 til 6].map -> parseInt 2*Math.PI*(it*60+160) | |
_sc_total = _sc.reduce (+) | |
@config.seat-count = _sc.map -> Math.round it*mlys.length/_sc_total | |
idx = 0 | |
for mly in mlys | |
@h-name[mly.name] = | |
name: mly.name | |
vote: 0 | |
party: mly.party | |
idx: idx++ | |
@h-party[mly.party] ?= @h-party[0]++ | |
for names,i in @config.vote | |
for name in names | |
@h-name[name].vote = i+1 | |
@svg = d3.select @config.node .append \svg | |
.attr \width \100% | |
.attr \height \100% | |
defs = @svg.selectAll \defs .data mlys .enter! .append \pattern | |
.attr \id ~> \defs_h + @h-name[it.name].idx | |
.attr \patternUnits \userSpaceOnUse | |
.attr \x 30 | |
.attr \y 30 | |
.attr \width 50 | |
.attr \height 50 | |
imgs = defs.append \image | |
.attr \xlink:href -> "http://avatars.io/50a65bb26e293122b0000073/#{CryptoJS.MD5('MLY/'+it.name).toString()}?size=small" | |
.attr \x 0 | |
.attr \y 0 | |
.attr \width 50 | |
.attr \height 50 | |
.attr \transform "scale(0.9)" | |
panel = @svg.append \g | |
.attr \transform ~> @config.transform | |
_pt = ~> @seat-position @seat-mapping it.name | |
@seats = panel.selectAll \g.seat | |
.data [@h-name[it] for it of @h-name].sort( (a,b) ~> | |
@h-party[a.party] - @h-party[b.party]) .enter! .append \g | |
.attr \transform ~> "translate(#{(_pt it)0},#{(_pt it)1})" | |
lockcell = null | |
@seats.append \circle | |
.attr \class \mly-seat | |
.attr \r 20 | |
.attr \fill ~> @colors[it.party] | |
.style \opacity ~> if it.vote == 0 then 0.3 else 1 | |
.on \click ~> | |
if lockcell | |
d3.select lockcell .attr \fill ~> @colors[it.party] | |
.transition! .duration 500 | |
.attr \transform "scale(1)" | |
.attr \stroke \none | |
.style \opacity ~> if it.vote == 0 then 0.3 else 1 | |
if lockcell == d3.event.target | |
return lockcell := null | |
lockcell := d3.event.target | |
d3.select d3.event.target .attr \fill -> "url(\#defs_h#{it.idx})" | |
.transition! .duration 500 | |
.attr \transform "scale(2)" | |
.attr \stroke ~> @colors[it.party] | |
.attr \stroke-width \3px | |
.style \opacity 1 | |
@seats.append \path | |
.attr \d ~> switch it.vote | |
|1 => "M-12 0 L0 10 L11 -11" | |
|2 => "M-10,-10 L10,10 L0 0 L-10 10 L10 -10" | |
|3 => "M-10 0 L10 00" | |
|9 => "M15 0 A15 15 0 1 1 -15 0 A15 15 0 1 1 15 0" | |
|otherwise => "M0 0" | |
.attr \stroke ~> switch it.vote | |
|1 => \#0b0 | |
|2 => \#b00 | |
|3 => \#999 | |
|otherwise => \#b00 | |
.attr \stroke-width \5px | |
.attr \fill \none | |
@seats.append \rect | |
.attr \class \mly-name-box | |
.attr \x -25 | |
.attr \y 9 | |
.attr \width 50 | |
.attr \height 17 | |
.attr \rx 10 | |
.attr \ry 10 | |
.attr \fill \#fff | |
.style \opacity 0.4 | |
@seats.append \text | |
.attr \class \mly-name | |
.attr \y 22 | |
.attr \text-anchor \middle | |
.text (.name) | |
render: (config) -> | |
unless config.vote | |
$ config.node | |
..find \span.approval .each -> config.[]vote[0] = $ @ .text! / ' ' | |
..find \span.veto .each -> config.[]vote[1] = $ @ .text! / ' ' | |
..find \span.abstention .each -> config.[]vote[2] = $ @ .text! / ' ' | |
..find \span .hide! | |
@config <<< config | |
d3.json config.namelist, (error, json) ~> | |
@generate.call @, error, json | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
all: | |
jade --pretty index.jade | |
livescript -cp index.ls > index.js | |
livescript -cp lyvote.ls > lyvote.js |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[ { "name": "丁守中", | |
"party": "KMT", | |
"caucus": "KMT", | |
"constuiency": [ "TPE", 1 ] }, | |
{ "name": "孔文吉", | |
"party": "KMT", | |
"caucus": "KMT", | |
"constuiency": [ "aborigine", "highland" ] }, | |
{ "name": "尤美女", | |
"party": "DPP", | |
"caucus": "DPP", | |
"constuiency": [ "proportional" ] }, | |
{ "name": "王廷升", | |
"party": "KMT", | |
"caucus": "KMT", | |
"constuiency": [ "HUA", 0 ] }, | |
{ "name": "王育敏", | |
"party": "KMT", | |
"caucus": "KMT", | |
"constuiency": [ "proportional" ] }, | |
{ "name": "王金平", | |
"party": "KMT", | |
"caucus": "KMT", | |
"constuiency": [ "proportional" ] }, | |
{ "name": "王進士", | |
"party": "KMT", | |
"caucus": "KMT", | |
"constuiency": [ "PIF", 2 ] }, | |
{ "name": "王惠美", | |
"party": "KMT", | |
"caucus": "KMT", | |
"constuiency": [ "CHA", 1 ] }, | |
{ "name": "田秋堇", | |
"party": "DPP", | |
"caucus": "DPP", | |
"constuiency": [ "proportional" ] }, | |
{ "name": "江啟臣", | |
"party": "KMT", | |
"caucus": "KMT", | |
"constuiency": [ "TXG", 8 ] }, | |
{ "name": "江惠貞", | |
"party": "KMT", | |
"caucus": "KMT", | |
"constuiency": [ "TPQ", 7 ] }, | |
{ "name": "何欣純", | |
"party": "DPP", | |
"caucus": "DPP", | |
"constuiency": [ "TXG", 7 ] }, | |
{ "name": "吳宜臻", | |
"party": "DPP", | |
"caucus": "DPP", | |
"constuiency": [ "proportional" ] }, | |
{ "name": "吳育仁", | |
"party": "KMT", | |
"caucus": "KMT", | |
"constuiency": [ "proportional" ] }, | |
{ "name": "吳育昇", | |
"party": "KMT", | |
"caucus": "KMT", | |
"constuiency": [ "TPQ", 1 ] }, | |
{ "name": "吳秉叡", | |
"party": "DPP", | |
"caucus": "DPP", | |
"constuiency": [ "proportional" ] }, | |
{ "name": "呂玉玲", | |
"party": "KMT", | |
"caucus": "KMT", | |
"constuiency": [ "TAO", 5 ] }, | |
{ "name": "呂學樟", | |
"party": "KMT", | |
"caucus": "KMT", | |
"constuiency": [ "HSZ", 0 ] }, | |
{ "name": "李昆澤", | |
"party": "DPP", | |
"caucus": "DPP", | |
"constuiency": [ "KHH", 6 ] }, | |
{ "name": "李俊俋", | |
"party": "DPP", | |
"caucus": "DPP", | |
"constuiency": [ "CYI", 0 ] }, | |
{ "name": "李桐豪", | |
"party": "PFP", | |
"caucus": "PFP", | |
"constuiency": [ "proportional" ] }, | |
{ "name": "李貴敏", | |
"party": "KMT", | |
"caucus": "KMT", | |
"constuiency": [ "proportional" ] }, | |
{ "name": "李慶華", | |
"party": "KMT", | |
"caucus": "KMT", | |
"constuiency": [ "TPQ", 12 ] }, | |
{ "name": "李應元", | |
"party": "DPP", | |
"caucus": "DPP", | |
"constuiency": [ "proportional" ] }, | |
{ "name": "李鴻鈞", | |
"party": "KMT", | |
"caucus": "KMT", | |
"constuiency": [ "TPQ", 4 ] }, | |
{ "name": "邱文彥", | |
"party": "KMT", | |
"caucus": "KMT", | |
"constuiency": [ "proportional" ] }, | |
{ "name": "邱志偉", | |
"party": "DPP", | |
"caucus": "DPP", | |
"constuiency": [ "KHH", 2 ] }, | |
{ "name": "邱議瑩", | |
"party": "DPP", | |
"caucus": "DPP", | |
"constuiency": [ "KHH", 1 ] }, | |
{ "name": "林世嘉", | |
"party": "TSU", | |
"caucus": "TSU", | |
"constuiency": [ "proportional" ] }, | |
{ "name": "林正二", | |
"party": "PFP", | |
"caucus": "PFP", | |
"constuiency": [ "aborigine", "lowland" ] }, | |
{ "name": "林佳龍", | |
"party": "DPP", | |
"caucus": "DPP", | |
"constuiency": [ "TXG", 6 ] }, | |
{ "name": "林岱樺", | |
"party": "DPP", | |
"caucus": "DPP", | |
"constuiency": [ "KHH", 4 ] }, | |
{ "name": "林明溱", | |
"party": "KMT", | |
"caucus": "KMT", | |
"constuiency": [ "NAN", 2 ] }, | |
{ "name": "林郁方", | |
"party": "KMT", | |
"caucus": "KMT", | |
"constuiency": [ "TPE", 5 ] }, | |
{ "name": "林國正", | |
"party": "KMT", | |
"caucus": "KMT", | |
"constuiency": [ "KHH", 9 ] }, | |
{ "name": "林淑芬", | |
"party": "DPP", | |
"caucus": "DPP", | |
"constuiency": [ "TPQ", 2 ] }, | |
{ "name": "林滄敏", | |
"party": "KMT", | |
"caucus": "KMT", | |
"constuiency": [ "CHA", 2 ] }, | |
{ "name": "林德福", | |
"party": "KMT", | |
"caucus": "KMT", | |
"constuiency": [ "TPQ", 9 ] }, | |
{ "name": "林鴻池", | |
"party": "KMT", | |
"caucus": "KMT", | |
"constuiency": [ "TPQ", 6 ] }, | |
{ "name": "姚文智", | |
"party": "DPP", | |
"caucus": "DPP", | |
"constuiency": [ "TPE", 2 ] }, | |
{ "name": "柯建銘", | |
"party": "DPP", | |
"caucus": "DPP", | |
"constuiency": [ "proportional" ] }, | |
{ "name": "段宜康", | |
"party": "DPP", | |
"caucus": "DPP", | |
"constuiency": [ "proportional" ] }, | |
{ "name": "洪秀柱", | |
"party": "KMT", | |
"caucus": "KMT", | |
"constuiency": [ "proportional" ] }, | |
{ "name": "紀國棟", | |
"party": "KMT", | |
"caucus": "KMT", | |
"constuiency": [ "proportional" ] }, | |
{ "name": "孫大千", | |
"party": "KMT", | |
"caucus": "KMT", | |
"constuiency": [ "TAO", 6 ] }, | |
{ "name": "徐少萍", | |
"party": "KMT", | |
"caucus": "KMT", | |
"constuiency": [ "proportional" ] }, | |
{ "name": "徐欣瑩", | |
"party": "KMT", | |
"caucus": "KMT", | |
"constuiency": [ "HSQ", 0 ] }, | |
{ "name": "徐耀昌", | |
"party": "KMT", | |
"caucus": "KMT", | |
"constuiency": [ "MIA", 2 ] }, | |
{ "name": "翁重鈞", | |
"party": "KMT", | |
"caucus": "KMT", | |
"constuiency": [ "CYQ", 1 ] }, | |
{ "name": "陳其邁", | |
"party": "DPP", | |
"caucus": "DPP", | |
"constuiency": [ "proportional" ] }, | |
{ "name": "陳明文", | |
"party": "DPP", | |
"caucus": "DPP", | |
"constuiency": [ "CYQ", 2 ] }, | |
{ "name": "陳亭妃", | |
"party": "DPP", | |
"caucus": "DPP", | |
"constuiency": [ "TNN", 3 ] }, | |
{ "name": "陳唐山", | |
"party": "DPP", | |
"caucus": "DPP", | |
"constuiency": [ "TNN", 5 ] }, | |
{ "name": "陳根德", | |
"party": "KMT", | |
"caucus": "KMT", | |
"constuiency": [ "TAO", 1 ] }, | |
{ "name": "陳淑慧", | |
"party": "KMT", | |
"caucus": "KMT", | |
"constuiency": [ "proportional" ] }, | |
{ "name": "陳雪生", | |
"party": null, | |
"caucus": null, | |
"constuiency": [ "LJF", 0 ] }, | |
{ "name": "陳超明", | |
"party": "KMT", | |
"caucus": "KMT", | |
"constuiency": [ "MIA", 1 ] }, | |
{ "name": "陳節如", | |
"party": "DPP", | |
"caucus": "DPP", | |
"constuiency": [ "proportional" ] }, | |
{ "name": "陳碧涵", | |
"party": "KMT", | |
"caucus": "KMT", | |
"constuiency": [ "proportional" ] }, | |
{ "name": "陳歐珀", | |
"party": "DPP", | |
"caucus": "DPP", | |
"constuiency": [ "ILA", 0 ] }, | |
{ "name": "陳學聖", | |
"party": "KMT", | |
"caucus": "KMT", | |
"constuiency": [ "TAO", 3 ] }, | |
{ "name": "陳鎮湘", | |
"party": "KMT", | |
"caucus": "KMT", | |
"constuiency": [ "proportional" ] }, | |
{ "name": "馬文君", | |
"party": "KMT", | |
"caucus": "KMT", | |
"constuiency": [ "NAN", 1 ] }, | |
{ "name": "高志鵬", | |
"party": "DPP", | |
"caucus": "DPP", | |
"constuiency": [ "TPQ", 3 ] }, | |
{ "name": "高金素梅", | |
"party": "NSU", | |
"caucus": null, | |
"constuiency": [ "aborigine", "highland" ] }, | |
{ "name": "張嘉郡", | |
"party": "KMT", | |
"caucus": "KMT", | |
"constuiency": [ "YUN", 1 ] }, | |
{ "name": "張慶忠", | |
"party": "KMT", | |
"caucus": "KMT", | |
"constuiency": [ "TPQ", 8 ] }, | |
{ "name": "張曉風", | |
"party": "PFP", | |
"caucus": "PFP", | |
"constuiency": [ "proportional" ] }, | |
{ "name": "許忠信", | |
"party": "TSU", | |
"caucus": "TSU", | |
"constuiency": [ "proportional" ] }, | |
{ "name": "許添財", | |
"party": "DPP", | |
"caucus": "DPP", | |
"constuiency": [ "TNN", 4 ] }, | |
{ "name": "許智傑", | |
"party": "DPP", | |
"caucus": "DPP", | |
"constuiency": [ "KHH", 8 ] }, | |
{ "name": "曾巨威", | |
"party": "KMT", | |
"caucus": "KMT", | |
"constuiency": [ "proportional" ] }, | |
{ "name": "葉宜津", | |
"party": "DPP", | |
"caucus": "DPP", | |
"constuiency": [ "TNN", 1 ] }, | |
{ "name": "費鴻泰", | |
"party": "KMT", | |
"caucus": "KMT", | |
"constuiency": [ "TPE", 7 ] }, | |
{ "name": "黃文玲", | |
"party": "TSU", | |
"caucus": "TSU", | |
"constuiency": [ "proportional" ] }, | |
{ "name": "黃志雄", | |
"party": "KMT", | |
"caucus": "KMT", | |
"constuiency": [ "TPQ", 5 ] }, | |
{ "name": "黃昭順", | |
"party": "KMT", | |
"caucus": "KMT", | |
"constuiency": [ "KHH", 3 ] }, | |
{ "name": "黃偉哲", | |
"party": "DPP", | |
"caucus": "DPP", | |
"constuiency": [ "TNN", 2 ] }, | |
{ "name": "楊玉欣", | |
"party": "KMT", | |
"caucus": "KMT", | |
"constuiency": [ "proportional" ] }, | |
{ "name": "楊應雄", | |
"party": "KMT", | |
"caucus": "KMT", | |
"constuiency": [ "JME", 0 ] }, | |
{ "name": "楊曜", | |
"party": "DPP", | |
"caucus": "DPP", | |
"constuiency": [ "PEN", 0 ] }, | |
{ "name": "楊瓊瓔", | |
"party": "KMT", | |
"caucus": "KMT", | |
"constuiency": [ "TXG", 3 ] }, | |
{ "name": "楊麗環", | |
"party": "KMT", | |
"caucus": "KMT", | |
"constuiency": [ "TAO", 4 ] }, | |
{ "name": "詹凱臣", | |
"party": "KMT", | |
"caucus": "KMT", | |
"constuiency": [ "foreign" ] }, | |
{ "name": "廖正井", | |
"party": "KMT", | |
"caucus": "KMT", | |
"constuiency": [ "TAO", 2 ] }, | |
{ "name": "廖國棟", | |
"party": "KMT", | |
"caucus": "KMT", | |
"constuiency": [ "aborigine", "lowland" ] }, | |
{ "name": "管碧玲", | |
"party": "DPP", | |
"caucus": "DPP", | |
"constuiency": [ "KHH", 5 ] }, | |
{ "name": "蔡正元", | |
"party": "KMT", | |
"caucus": "KMT", | |
"constuiency": [ "TPE", 4 ] }, | |
{ "name": "蔡其昌", | |
"party": "DPP", | |
"caucus": "DPP", | |
"constuiency": [ "TXG", 1 ] }, | |
{ "name": "蔡煌瑯", | |
"party": "DPP", | |
"caucus": "DPP", | |
"constuiency": [ "proportional" ] }, | |
{ "name": "蔡錦隆", | |
"party": "KMT", | |
"caucus": "KMT", | |
"constuiency": [ "TXG", 4 ] }, | |
{ "name": "蔣乃辛", | |
"party": "KMT", | |
"caucus": "KMT", | |
"constuiency": [ "TPE", 6 ] }, | |
{ "name": "趙天麟", | |
"party": "DPP", | |
"caucus": "DPP", | |
"constuiency": [ "KHH", 7 ] }, | |
{ "name": "鄭天財", | |
"party": "KMT", | |
"caucus": "KMT", | |
"constuiency": [ "aborigine", "lowland" ] }, | |
{ "name": "鄭汝芬", | |
"party": "KMT", | |
"caucus": "KMT", | |
"constuiency": [ "CHA", 3 ] }, | |
{ "name": "鄭麗君", | |
"party": "DPP", | |
"caucus": "DPP", | |
"constuiency": [ "proportional" ] }, | |
{ "name": "劉建國", | |
"party": "DPP", | |
"caucus": "DPP", | |
"constuiency": [ "YUN", 2 ] }, | |
{ "name": "劉櫂豪", | |
"party": "DPP", | |
"caucus": "DPP", | |
"constuiency": [ "TTT", 0 ] }, | |
{ "name": "潘孟安", | |
"party": "DPP", | |
"caucus": "DPP", | |
"constuiency": [ "PIF", 3 ] }, | |
{ "name": "潘維剛", | |
"party": "KMT", | |
"caucus": "KMT", | |
"constuiency": [ "proportional" ] }, | |
{ "name": "盧秀燕", | |
"party": "KMT", | |
"caucus": "KMT", | |
"constuiency": [ "TXG", 5 ] }, | |
{ "name": "盧嘉辰", | |
"party": "KMT", | |
"caucus": "KMT", | |
"constuiency": [ "TPQ", 10 ] }, | |
{ "name": "蕭美琴", | |
"party": "DPP", | |
"caucus": "DPP", | |
"constuiency": [ "proportional" ] }, | |
{ "name": "薛凌", | |
"party": "DPP", | |
"caucus": "DPP", | |
"constuiency": [ "proportional" ] }, | |
{ "name": "賴士葆", | |
"party": "KMT", | |
"caucus": "KMT", | |
"constuiency": [ "TPE", 8 ] }, | |
{ "name": "謝國樑", | |
"party": "KMT", | |
"caucus": "KMT", | |
"constuiency": [ "KEE", 0 ] }, | |
{ "name": "魏明谷", | |
"party": "DPP", | |
"caucus": "DPP", | |
"constuiency": [ "CHA", 4 ] }, | |
{ "name": "簡東明", | |
"party": "KMT", | |
"caucus": "KMT", | |
"constuiency": [ "aborigine", "highland" ] }, | |
{ "name": "顏清標", | |
"party": "NSU", | |
"caucus": null, | |
"constuiency": [ "TXG", 2 ] }, | |
{ "name": "羅明才", | |
"party": "KMT", | |
"caucus": "KMT", | |
"constuiency": [ "TPQ", 11 ] }, | |
{ "name": "羅淑蕾", | |
"party": "KMT", | |
"caucus": "KMT", | |
"constuiency": [ "TPE", 3 ] }, | |
{ "name": "蘇清泉", | |
"party": "KMT", | |
"caucus": "KMT", | |
"constuiency": [ "proportional" ] }, | |
{ "name": "蘇震清", | |
"party": "DPP", | |
"caucus": "DPP", | |
"constuiency": [ "PIF", 1 ] } ] |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment