Some changes and new stuff

This commit is contained in:
Russell 2015-08-24 10:04:57 -05:00
parent 33ea98b002
commit 0b5a4fcfb8
19 changed files with 900 additions and 9 deletions

View File

@ -1,20 +1,20 @@
krowbar&^%224&^%1434372702
krowbar&^%225&^%1438182841
karlen&^%271&^%1426779321
endorphant&^%584&^%1434930668
endorphant&^%630&^%1438131263
jumblesale&^%24&^%1426171214
marcus&^%540&^%1434989294
papa&^%102&^%1434788735
marcus&^%616&^%1440424356
papa&^%179&^%1438878499
epicmorphism&^%5&^%1421937744
audy&^%76&^%1431897326
kc&^%18&^%1422326056
vilmibm&^%9&^%1423247508
cmr&^%452&^%1434995429
cmr&^%864&^%1440424361
imt&^%519&^%1424087616
cndorphant&^%788&^%1424094192
rain&^%17&^%1422310975
sl2c&^%91&^%1424847521
selfsame&^%1&^%1422230012
bear&^%207&^%1434744601
bear&^%208&^%1438015446
coaxial&^%8&^%1422325983
joe&^%8&^%1422325983
hardmath123&^%4&^%1422325983
@ -23,4 +23,8 @@ cel&^%11&^%1430162676
quote_bots&^%3&^%1424737471
bave&^%1&^%1427591141
scellef&^%13&^%1428707074
cndorphbot&^%6&^%1433564301
cndorphbot&^%8&^%1438044694
reppard&^%11&^%1437512059
jesse&^%6&^%1437569027
khoi&^%3&^%1438044039
sanqui&^%4&^%1438184911

View File

@ -90,3 +90,21 @@
1434162536&^%vilmibm&^%when was the last time you saw a whale or butterfly | donations for tilde.town: https://www.patreon.com/nathanielksmith
1434457394&^%krowbar&^%What languages (other than English) can you speak? | donations for tilde.town: https://www.patreon.com/nathanielksmith
1434995963&^%krowbar&^%What mannerisms have you picked up from friends or family? | donations for tilde.town: https://www.patreon.com/nathanielksmith
1435160342&^%krowbar&^%What is your favorite cafinated or pick-me-up drink? | donations for tilde.town: https://www.patreon.com/nathanielksmith
1435209856&^%vilmibm&^%kiss the earth; wipe the soil from your lips and smear it on your laptop screen | donate https://www.patreon.com/nathanielksmith
1435676406&^%krowbar&^%How do you celebrate your country or show patriotism? | donate https://www.patreon.com/nathanielksmith
1436142566&^%vilmibm&^%fuck geopolitical borders | donate https://www.patreon.com/nathanielksmith
1436214837&^%vilmibm&^%apply to be a tilde.town sysadmin! email nathanielksmith@gmail.com | donate https://www.patreon.com/nathanielksmith
1437586202&^%vilmibm&^%let's talk about html and feels | donate https://www.activeworlds.com/web/index.php
1437586215&^%vilmibm&^%let's talk about html and feels | donate https://www.patreon.com/nathanielksmith
1437665519&^%krowbar&^%Have you ever served on a jury? How did it go? | donate https://www.patreon.com/nathanielksmith
1437973628&^%hardmath123&^%Electronic progressive bass dubhouse Chicago step | donate https://www.patreon.com/nathanielksmith
1438115317&^%hardmath123&^%The pink just got a whole lot pinker. | donate https://www.patreon.com/nathanielksmith
1438368557&^%hardmath123&^%vilmibm has root on our server and in our hearts| donate https://www.patreon.com/nathanielksmith
1438368561&^%hardmath123&^%vilmibm has root on our server and in our hearts | donate https://www.patreon.com/nathanielksmith
1438732910&^%hardmath123&^%"We're not thinking machines, we're feeling machines that happen to think." - Peter Watts, _Blindsight_ | donate https://www.patreon.com/nathanielksmith
1439339666&^%joe&^%~joe has a new job, let's party hard
1439442465&^%hardmath123&^%'rejoice', said he, 'for the king has returned'
1439443352&^%vilmibm&^%let's talk bout html and feels | congrats ~joe
1440076665&^%krowbar&^%Let's Play Factorio together! Community event *this* Saturday 1pm-3pm GMT. Ask ~krowbar or ~jumblesale for details
1440363401&^%krowbar&^%Welcome to tilde.town! A place where creativity abounds!

View File

@ -1 +1,4 @@
krowbar&^%0&^%1
krowbar&^%0&^%6
vilmibm&^%0&^%6
hardmath123&^%0&^%6
joe&^%0&^%1

199
Code/python/bannedWords Normal file
View File

@ -0,0 +1,199 @@
aboard
about
above
across
after
against
along
amid
among
anti
around
as
at
before
behind
below
beneath
beside
besides
between
beyond
but
by
concerning
considering
despite
down
during
except
excepting
excluding
following
for
from
in
inside
into
like
minus
near
of
off
on
onto
opposite
outside
over
past
per
plus
regarding
round
save
since
than
through
to
toward
towards
under
underneath
unlike
until
up
upon
versus
via
with
within
without
all
another
any
anybody
anyone
anything
both
each
either
everybody
everyone
everything
few
he
her
hers
herself
him
himself
his
it
its
itself
many
me mine
more
most
much
my
myself
neither
no one
nobody
none
one
other
others
our
ours
ourselves
several
she
some
somebody
someone
something
that
their
theirs
them
themselves
these
they
this
those
us
we
what
whatever
which
whichever
who
whoever
whom
whomever
whose
you
your
yours
yourself
yourselves
an
am
as
to
up
us
in
be
can
how
get
got
has
did
every
also
too
try
is
was
do
if
oh
so
ill
are
been
or
dont
just
had
set
put
have
im
ive
not
then
goes
youre
use
id
the
a
and
i
me
when
where
how
would
whats
because
thats
there
doing
even
does

View File

@ -0,0 +1,29 @@
#!/usr/bin/python
import fileinput
import json
import time
import calendar
import shutil
logfile = "/home/jumblesale/Code/irc/log"
outfile = "/home/krowbar/logs/userData.json"
userData = {} #hash keyed by "user" that contains an array of timestamps
#we only care about recent chats, let's say for the past two weeks
timeCutoff = calendar.timegm(time.gmtime()) - (2 * 7 * 24 * 60 * 60)
with open(logfile, "r") as log:
for line in log:
try:
time, user, message = line.split("\t", 3)
time = int(time)
except ValueError:
continue #There are some bad lines in the log file that we'll ignore if we can't parse
if time > timeCutoff:
#if the user already exists in the list
if user in userData:
userData[user].append(time) #append the new time
else: #if they are new
userData[user] = [time] #create a new list
with open(outfile + ".tmp", "w") as tmpFile:
tmpFile.write(json.dumps(userData))
shutil.move(outfile + ".tmp", outfile)

38
Code/python/chatcloud.py Normal file
View File

@ -0,0 +1,38 @@
#!/usr/bin/python
import fileinput
import json
import time
import calendar
import re
import shutil
logfile = "/home/jumblesale/Code/irc/log"
outfile = "/home/krowbar/logs/chatcloud.json"
bannedWordsFile = "/home/krowbar/Code/python/bannedWords"
wordData = {} # keyed by "word" that contains a count
#we only care about recent chats, let's say for the past two weeks
timeCutoff = calendar.timegm(time.gmtime()) - (2 * 7 * 24 * 60 * 60)
minOccurance = 10
bannedWords = open(bannedWordsFile).read().splitlines()
with open(logfile, "r") as log:
for line in log:
try:
time, user, message = line.split("\t", 3)
time = int(time)
except ValueError:
continue #There are some bad lines in the log file that we'll ignore if we can't parse
if time > timeCutoff:
for word in re.sub('[\'\";:,.?!*&^\-()\[\]]', '', message).lower().split():
if word in bannedWords:
continue
#if the word already exists in the list
if word in wordData:
wordData[word] += 1
else: #if they are new
wordData[word] = 1
#print "Added word: " + word
wordData = {i:wordData[i] for i in wordData if wordData[i] >= minOccurance }
with open(outfile + ".tmp", "w") as tmpFile:
tmpFile.write(json.dumps(wordData))
shutil.move(outfile + ".tmp", outfile)

View File

@ -0,0 +1,21 @@
<!DOCTYPE html>
<html>
<head>
<title>Who chats and when?</title>
</head>
<script type="text/javascript" src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.6/d3.min.js" charset="utf-8"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.10.1/lodash.min.js"></script>
<script type="text/javascript">
userData = {};
jQuery.getJSON("/~krowbar/data/userData.json", function(json) {
userData = json;
});
</script>
<body>
Here's some stuff! Check the console for userData
<br/>
Maybe I should use Google charts again instead of D3. Remember to use .setUTCSeconds()
</body>
</html>

View File

@ -0,0 +1,26 @@
How do do stuff
Data structure
users["name"]
.talked = array of irc times
.mentioned = array of irc times
DATA DAEMON
* Parse log for nicks that said something
- Populate data structure
* For each line, log the person who talked
- Check if any other person was mentioned
- Only log if it is at least 1 minute past their last chat/reference (maybe
to reduce data size)
* Write to log file
- Same file or dated one?
- Only certain time frames??
* Run daily/hourly?
PRESENTATION
* Select a user name from the drop down
- See a timeline with colored strands of when they spoke and were mentioned
* Something that looks like the Github commit history
* Use D3 for coolness

View File

@ -0,0 +1,387 @@
// Word cloud layout by Jason Davies, http://www.jasondavies.com/word-cloud/
// Algorithm due to Jonathan Feinberg, http://static.mrfeinberg.com/bv_ch03.pdf
(function() {
if (typeof define === "function" && define.amd) define(["d3"], cloud);
else cloud(this.d3);
function cloud(d3) {
d3.layout.cloud = function cloud() {
var size = [256, 256],
text = cloudText,
font = cloudFont,
fontSize = cloudFontSize,
fontStyle = cloudFontNormal,
fontWeight = cloudFontNormal,
rotate = cloudRotate,
padding = cloudPadding,
spiral = archimedeanSpiral,
words = [],
timeInterval = Infinity,
event = d3.dispatch("word", "end"),
timer = null,
random = Math.random,
cloud = {};
cloud.start = function() {
var board = zeroArray((size[0] >> 5) * size[1]),
bounds = null,
n = words.length,
i = -1,
tags = [],
data = words.map(function(d, i) {
d.text = text.call(this, d, i);
d.font = font.call(this, d, i);
d.style = fontStyle.call(this, d, i);
d.weight = fontWeight.call(this, d, i);
d.rotate = rotate.call(this, d, i);
d.size = ~~fontSize.call(this, d, i);
d.padding = padding.call(this, d, i);
return d;
}).sort(function(a, b) { return b.size - a.size; });
if (timer) clearInterval(timer);
timer = setInterval(step, 0);
step();
return cloud;
function step() {
var start = Date.now();
while (Date.now() - start < timeInterval && ++i < n && timer) {
var d = data[i];
d.x = (size[0] * (random() + .5)) >> 1;
d.y = (size[1] * (random() + .5)) >> 1;
cloudSprite(d, data, i);
if (d.hasText && place(board, d, bounds)) {
tags.push(d);
event.word(d);
if (bounds) cloudBounds(bounds, d);
else bounds = [{x: d.x + d.x0, y: d.y + d.y0}, {x: d.x + d.x1, y: d.y + d.y1}];
// Temporary hack
d.x -= size[0] >> 1;
d.y -= size[1] >> 1;
}
}
if (i >= n) {
cloud.stop();
event.end(tags, bounds);
}
}
}
cloud.stop = function() {
if (timer) {
clearInterval(timer);
timer = null;
}
return cloud;
};
function place(board, tag, bounds) {
var perimeter = [{x: 0, y: 0}, {x: size[0], y: size[1]}],
startX = tag.x,
startY = tag.y,
maxDelta = Math.sqrt(size[0] * size[0] + size[1] * size[1]),
s = spiral(size),
dt = random() < .5 ? 1 : -1,
t = -dt,
dxdy,
dx,
dy;
while (dxdy = s(t += dt)) {
dx = ~~dxdy[0];
dy = ~~dxdy[1];
if (Math.min(Math.abs(dx), Math.abs(dy)) >= maxDelta) break;
tag.x = startX + dx;
tag.y = startY + dy;
if (tag.x + tag.x0 < 0 || tag.y + tag.y0 < 0 ||
tag.x + tag.x1 > size[0] || tag.y + tag.y1 > size[1]) continue;
// TODO only check for collisions within current bounds.
if (!bounds || !cloudCollide(tag, board, size[0])) {
if (!bounds || collideRects(tag, bounds)) {
var sprite = tag.sprite,
w = tag.width >> 5,
sw = size[0] >> 5,
lx = tag.x - (w << 4),
sx = lx & 0x7f,
msx = 32 - sx,
h = tag.y1 - tag.y0,
x = (tag.y + tag.y0) * sw + (lx >> 5),
last;
for (var j = 0; j < h; j++) {
last = 0;
for (var i = 0; i <= w; i++) {
board[x + i] |= (last << msx) | (i < w ? (last = sprite[j * w + i]) >>> sx : 0);
}
x += sw;
}
delete tag.sprite;
return true;
}
}
}
return false;
}
cloud.timeInterval = function(_) {
return arguments.length ? (timeInterval = _ == null ? Infinity : _, cloud) : timeInterval;
};
cloud.words = function(_) {
return arguments.length ? (words = _, cloud) : words;
};
cloud.size = function(_) {
return arguments.length ? (size = [+_[0], +_[1]], cloud) : size;
};
cloud.font = function(_) {
return arguments.length ? (font = d3.functor(_), cloud) : font;
};
cloud.fontStyle = function(_) {
return arguments.length ? (fontStyle = d3.functor(_), cloud) : fontStyle;
};
cloud.fontWeight = function(_) {
return arguments.length ? (fontWeight = d3.functor(_), cloud) : fontWeight;
};
cloud.rotate = function(_) {
return arguments.length ? (rotate = d3.functor(_), cloud) : rotate;
};
cloud.text = function(_) {
return arguments.length ? (text = d3.functor(_), cloud) : text;
};
cloud.spiral = function(_) {
return arguments.length ? (spiral = spirals[_] || _, cloud) : spiral;
};
cloud.fontSize = function(_) {
return arguments.length ? (fontSize = d3.functor(_), cloud) : fontSize;
};
cloud.padding = function(_) {
return arguments.length ? (padding = d3.functor(_), cloud) : padding;
};
cloud.random = function(_) {
return arguments.length ? (random = _, cloud) : random;
};
return d3.rebind(cloud, event, "on");
};
function cloudText(d) {
return d.text;
}
function cloudFont() {
return "serif";
}
function cloudFontNormal() {
return "normal";
}
function cloudFontSize(d) {
return Math.sqrt(d.value);
}
function cloudRotate() {
return (~~(Math.random() * 6) - 3) * 30;
}
function cloudPadding() {
return 1;
}
// Fetches a monochrome sprite bitmap for the specified text.
// Load in batches for speed.
function cloudSprite(d, data, di) {
if (d.sprite) return;
c.clearRect(0, 0, (cw << 5) / ratio, ch / ratio);
var x = 0,
y = 0,
maxh = 0,
n = data.length;
--di;
while (++di < n) {
d = data[di];
c.save();
c.font = d.style + " " + d.weight + " " + ~~((d.size + 1) / ratio) + "px " + d.font;
var w = c.measureText(d.text + "m").width * ratio,
h = d.size << 1;
if (d.rotate) {
var sr = Math.sin(d.rotate * cloudRadians),
cr = Math.cos(d.rotate * cloudRadians),
wcr = w * cr,
wsr = w * sr,
hcr = h * cr,
hsr = h * sr;
w = (Math.max(Math.abs(wcr + hsr), Math.abs(wcr - hsr)) + 0x1f) >> 5 << 5;
h = ~~Math.max(Math.abs(wsr + hcr), Math.abs(wsr - hcr));
} else {
w = (w + 0x1f) >> 5 << 5;
}
if (h > maxh) maxh = h;
if (x + w >= (cw << 5)) {
x = 0;
y += maxh;
maxh = 0;
}
if (y + h >= ch) break;
c.translate((x + (w >> 1)) / ratio, (y + (h >> 1)) / ratio);
if (d.rotate) c.rotate(d.rotate * cloudRadians);
c.fillText(d.text, 0, 0);
if (d.padding) c.lineWidth = 2 * d.padding, c.strokeText(d.text, 0, 0);
c.restore();
d.width = w;
d.height = h;
d.xoff = x;
d.yoff = y;
d.x1 = w >> 1;
d.y1 = h >> 1;
d.x0 = -d.x1;
d.y0 = -d.y1;
d.hasText = true;
x += w;
}
var pixels = c.getImageData(0, 0, (cw << 5) / ratio, ch / ratio).data,
sprite = [];
while (--di >= 0) {
d = data[di];
if (!d.hasText) continue;
var w = d.width,
w32 = w >> 5,
h = d.y1 - d.y0;
// Zero the buffer
for (var i = 0; i < h * w32; i++) sprite[i] = 0;
x = d.xoff;
if (x == null) return;
y = d.yoff;
var seen = 0,
seenRow = -1;
for (var j = 0; j < h; j++) {
for (var i = 0; i < w; i++) {
var k = w32 * j + (i >> 5),
m = pixels[((y + j) * (cw << 5) + (x + i)) << 2] ? 1 << (31 - (i % 32)) : 0;
sprite[k] |= m;
seen |= m;
}
if (seen) seenRow = j;
else {
d.y0++;
h--;
j--;
y++;
}
}
d.y1 = d.y0 + seenRow;
d.sprite = sprite.slice(0, (d.y1 - d.y0) * w32);
}
}
// Use mask-based collision detection.
function cloudCollide(tag, board, sw) {
sw >>= 5;
var sprite = tag.sprite,
w = tag.width >> 5,
lx = tag.x - (w << 4),
sx = lx & 0x7f,
msx = 32 - sx,
h = tag.y1 - tag.y0,
x = (tag.y + tag.y0) * sw + (lx >> 5),
last;
for (var j = 0; j < h; j++) {
last = 0;
for (var i = 0; i <= w; i++) {
if (((last << msx) | (i < w ? (last = sprite[j * w + i]) >>> sx : 0))
& board[x + i]) return true;
}
x += sw;
}
return false;
}
function cloudBounds(bounds, d) {
var b0 = bounds[0],
b1 = bounds[1];
if (d.x + d.x0 < b0.x) b0.x = d.x + d.x0;
if (d.y + d.y0 < b0.y) b0.y = d.y + d.y0;
if (d.x + d.x1 > b1.x) b1.x = d.x + d.x1;
if (d.y + d.y1 > b1.y) b1.y = d.y + d.y1;
}
function collideRects(a, b) {
return a.x + a.x1 > b[0].x && a.x + a.x0 < b[1].x && a.y + a.y1 > b[0].y && a.y + a.y0 < b[1].y;
}
function archimedeanSpiral(size) {
var e = size[0] / size[1];
return function(t) {
return [e * (t *= .1) * Math.cos(t), t * Math.sin(t)];
};
}
function rectangularSpiral(size) {
var dy = 4,
dx = dy * size[0] / size[1],
x = 0,
y = 0;
return function(t) {
var sign = t < 0 ? -1 : 1;
// See triangular numbers: T_n = n * (n + 1) / 2.
switch ((Math.sqrt(1 + 4 * sign * t) - sign) & 3) {
case 0: x += dx; break;
case 1: y += dy; break;
case 2: x -= dx; break;
default: y -= dy; break;
}
return [x, y];
};
}
// TODO reuse arrays?
function zeroArray(n) {
var a = [],
i = -1;
while (++i < n) a[i] = 0;
return a;
}
var cloudRadians = Math.PI / 180,
cw = 1 << 11 >> 5,
ch = 1 << 11,
canvas,
ratio = 1;
if (typeof document !== "undefined") {
canvas = document.createElement("canvas");
canvas.width = 1;
canvas.height = 1;
ratio = Math.sqrt(canvas.getContext("2d").getImageData(0, 0, 1, 1).data.length >> 2);
canvas.width = (cw << 5) / ratio;
canvas.height = ch / ratio;
} else {
// Attempt to use node-canvas.
canvas = new Canvas(cw << 5, ch);
}
var c = canvas.getContext("2d"),
spirals = {
archimedean: archimedeanSpiral,
rectangular: rectangularSpiral
};
c.fillStyle = c.strokeStyle = "red";
c.textAlign = "center";
}
})();

View File

@ -0,0 +1,52 @@
<!DOCTYPE html>
<meta charset="utf-8">
<body>
<script type="text/javascript" src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.6/d3.js"></script>
<script type="text/javascript" src="d3.layout.cloud.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.10.1/lodash.min.js"></script>
<script>(function() {
var fill = d3.scale.category20();
layout = d3.layout.cloud();
jQuery.getJSON("/~krowbar/data/chatcloud.json", function(json) {
jsonWords = [];
_.forEach(json, function(count, word) {
console.log("Added", word, count);
jsonWords.push({text: word, size: count});
});
layout
.size([1200, 800])
.words(jsonWords)
.padding(5)
.rotate(function() { return ~~(Math.random() * 2) * 90; })
.font("Impact")
.fontSize(function(d) { return d.size * 2 / 3; })
.on("end", draw);
layout.start();
});
draw = function(words) {
console.log("Started draw with", words);
d3.select("body").append("svg")
.attr("width", layout.size()[0])
.attr("height", layout.size()[1])
.append("g")
.attr("transform", "translate(" + layout.size()[0] / 2 + "," + layout.size()[1] / 2 + ")")
.selectAll("text")
.data(words)
.enter().append("text")
.style("font-size", function(d) { return d.size + "px"; })
.style("font-family", "Impact")
.style("fill", function(d, i) { return fill(i); })
.attr("text-anchor", "middle")
.attr("transform", function(d) {
return "translate(" + [d.x, d.y] + ")rotate(" + d.rotate + ")";
})
.text(function(d) { return d.text; });
}
})();</script>

View File

@ -0,0 +1 @@
/home/krowbar/logs/chatcloud.json

View File

@ -0,0 +1 @@
/home/krowbar/logs/du_log.json

View File

@ -0,0 +1 @@
/home/krowbar/logs/userData.json

View File

@ -0,0 +1,13 @@
<html>
<head>
<title>Tilde Donators</title>
</head>
<body>
</body>
<h1>Tilders Interested in making donations</h1>
<ul>
<li>~krowbar</li>
<li>~marcus</li>
<li>~endorphant</li>
<li>~elly</li>
</html>

79
public_html/du/index.html Normal file
View File

@ -0,0 +1,79 @@
<html>
<head>
<title>Tilder Disk Usage</title>
</head>
<script type="text/javascript" src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
<script type="text/javascript" src="https://www.google.com/jsapi"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.15/angular.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.8.0/lodash.min.js"></script>
<script type="text/javascript">
google.load("visualization", "1.1", {packages:["corechart", "line"]});
google.setOnLoadCallback(drawCharts);
function drawCharts() {
var data = new google.visualization.DataTable();
var piechart = new google.visualization.PieChart(document.getElementById('donutchart'));
var linedata = new google.visualization.DataTable();
var linechart = new google.visualization.LineChart(document.getElementById('linechart'));
var date = new Date(0);
data.addColumn('string', 'User');
data.addColumn('number', 'Disk Usage');
data.addColumn('number', 'File Count');
var pieoptions = {
title: 'Tilder Disk Usage',
subtitle: 'in kb',
pieHole: 0.4,
sliceVisibilityThreshold: 0.01
};
var lineoptions = {
title: 'Tilder Disk Usage',
subtitle: 'over time',
vAxis: {
0: {title: 'kb'},
logScale: true
}
};
jQuery.getJSON("/~krowbar/data/du_log.json", function(json) {
date.setUTCSeconds(json[json.length-1].date);
//Draw PieChart
data.addRows(
_.map(json[json.length-1].data, function(d) { return [d.user, d.du, d.files];})
);
piechart.draw(data, pieoptions);
//Draw LineChart
linedata.addColumn('date', 'Date');
var userData = {};
_.forEach(json, function(set, idx) {
_.forEach(set.data, function(point) {
if(point.du > 2000) { //the 'interesting' threshold is set at 20000kb
if(!userData[point.user]) {
userData[point.user] = [];
var size = json.length;
while(size--) userData[point.user][size] = 0;
linedata.addColumn('number', point.user);
}
userData[point.user][idx] = point.du;
}
})
})
_.forEach(json, function(set,idx) {
var d = new Date(0);
d.setUTCSeconds(set.date);
linedata.addRow([d].concat(_.map(userData, function(user) { return user[idx];})));
});
console.log(linedata);
linechart.draw(linedata, lineoptions);
});
}
</script>
<body>
<div id="donutchart" style="width: 700px; height: 400px;"></div>
<div id="linechart" style="width: 1200px; height: 1200px;"></div>
</body>

12
public_html/dw/index.html Normal file
View File

@ -0,0 +1,12 @@
<html>
<head>
<title>Dungeon World</title>
</head>
<body>
Resources:
<ul>
<li><a href="http://www.dungeon-world.com">Official Site</a></li>
<li><a href="http://www.dungeonworldsrd.com">Dungeon World SRD</a></li>
<li><a href="http://joebanner.co.uk">Adventures</a></li>
</ul>
</body>

View File

@ -0,0 +1,5 @@
Server: factorio.krowbar.xyz (68.48.241.214:34197)<br/>
Mods download: <a href="https://drive.google.com/file/d/0BwsaQxa1UIRROWtoT1Nvdi1TVWM/view?usp=sharing">https://drive.google.com/file/d/0BwsaQxa1UIRROWtoT1Nvdi1TVWM/view?usp=sharing</a><br/>
Mumble server: 69.65.43.91:2162

@ -0,0 +1 @@
Subproject commit 3f01fb0103b243ad02d6c6616cd18f1e98ae4792

View File

@ -18,8 +18,9 @@ var mission_grammars = Array(
{chance:10, grammar: 'actor +"\'s " + noun1'},
{chance:10, grammar: 'noun1 + " of the " + noun2'},
{chance:10, grammar: 'noun1 + " of " + noun2'},
{chance:10, grammar: 'noun1 + " of " + color + " " + noun2'},
{chance:10, grammar: 'adj1 + " " + noun1 + " and " + adj2 + " " + noun2'},
{chance:3, grammar: '"Attack of the " + actors + "s"'}
{chance:3, grammar: '"Attack of the " + actor + "s"'}
);
this.getNoun = function(badNouns) {
return _.chain(nouns)