Initial commit, requires QWiki

master
kts of kettek (muzukashi) 2016-05-11 01:11:10 -07:00
commit 0346fa98bd
89 changed files with 3438 additions and 0 deletions

3
.gitignore vendored 100644
View File

@ -0,0 +1,3 @@
node_modules
QWiki
cache

9
NOTES 100644
View File

@ -0,0 +1,9 @@
onStart
- load 'wiki/qat/*' contents into memory, monitor for changes thereafter and update
- load last 'wiki/updates/*' contents into memory, monitor thereafter
@@QAT@@
- res.write(qats[Current day in year % count of qats loaded])
@@CONTENT@@:'/'
- res.write(renderUpdates(rules));

150
acts/default.js 100644
View File

@ -0,0 +1,150 @@
var fs = require('fs');
module.exports = function(qwiki) {
qwiki.rule('', '@@CONTENT@@', function(req, res, instance, next) {
if (req.area == '/' || req.area == '') {
qwiki.rules['updates']['@@CONTENT@@'](req, res, instance, next);
return;
} else {
for (var listing in qwiki.listings) {
if (req.area.substring(1, listing.length+1) == listing) {
req.listing = listing;
qwiki.rules['listing']['@@CONTENT@@'](req, res, instance, next);
return;
}
}
}
// instance.pos, instance.offset, instance.indices
var cache_path = 'cache/'+req.area+'.html';
res.write('<div class="content_row" id="bot">');
res.write('<div class="right">');
qwiki.readFile(res, cache_path, function(type, err) {
if (type == 'FNF') {
// cache does not exist - is there a wiki source?
var wiki_path = 'wiki/'+req.area+'.qwk';
fs.stat(wiki_path, function(err, stats) {
// TODO: stats.isFile()
if (err && err.code == 'ENOENT') {
// the wiki entry does not exist
res.write(req.area + ' does not exist yet');
res.write('</div></div>');
next();
} else if (err) {
// error while statting wiki entry
res.write(req.area + ': ' + err.code);
res.write('</div></div>');
next();
} else {
// wiki entry exists!
fs.readFile(wiki_path, function(err, data) {
if (err) {
res.write(req.area + ': ' + err.code);
res.write('</div></div>');
next();
} else {
qwiki.convertAndSave(req.area, (req.area in qwiki.wiki_index.pages ? qwiki.wiki_index.pages[req.area].format : qwiki.getDefault('format')), data, function() {
qwiki.readFile(res, wiki_path, function(type, err) {
if (type == 'FNF') {
res.write('error while creating cache');
res.write('</div></div>');
next();
} else if (err) {
res.write(req.area + ': ' + err.code);
res.write('</div></div>');
next();
} else {
res.write('</div></div>');
next();
}
});
});
}
});
}
});
} else if (err) {
res.write(req.area + ': ' + err.code);
res.write('</div></div>');
next();
} else {
res.write('</div></div>');
next();
}
});
});
qwiki.rule('', '@@TITLE@@', function(req, res, instance, next) {
res.write('qwiki ' + req.area);
next();
});
qwiki.rule('', '@@PAGE@@', function(req, res, instance, next) {
res.write(req.area);
next();
});
qwiki.rule('', '@@CRUMBS@@', function(req, res, instance, next) {
var parts = req.area.split('/');
var path = '';
parts[0] = '>';
for (var i = 0; i < parts.length; i++) {
path += (i == 0 ? '/' : parts[i]);
res.write('<li><a href="'+path+'">'+parts[i]+'</a></li>');
path += (i == 0 ? '' : '/');
}
next();
});
qwiki.rule('', '@@FOOTER@@', function(req, res, instance, next) {
res.write('<a href="http://kettek.net/qwiki">qwiki</a> Copyright 2015 <a href="http://kettek.net">kts of kettek</a>');
next();
});
qwiki.rule('', '@@QAT@@', function(req, res, instance, next) {
var d = new Date;
d.setHours(0, 0, 0, 0, 0);
res.write(qwiki.qats[d % (qwiki.qats.length-1)].render);
next();
});
qwiki.act('', function(req, res) {
var ext = qwiki.getExt(req.area);
var mimetype = qwiki.getMIMEtype(qwiki.getExt(req.area));
if (mimetype == '') mimetype = 'application/octet-stream';
if (ext !== '') { // write file on disk directly
var path = 'wiki/'+req.area;
fs.stat(path, function(err, stat) {
if (err == null) {
// TODO: etags should actually be based on binary data(CRC32, etc.), not last modified
// TODO: files should not be stat()`d each call, but should be cached and updated when the file updates (how? browser-based upload interface?)
var mtime = stat.mtime.getTime();
if (!(path in qwiki.etags) || qwiki.etags[path] != mtime) {
qwiki.etags[path] = mtime;
}
if ('if-none-match' in req.headers && req.headers['if-none-match'] == qwiki.etags[path]) {
res.writeHead(304, "Not Modified");
res.end();
} else {
res.writeHead(200, "OK", {
"Content-Type": mimetype,
"Content-Length": stat.size,
"ETag": mtime
});
var rs = fs.createReadStream(path);
rs.on('data', function(chunk) {
res.write(chunk);
});
rs.on('end', function() {
res.end();
});
}
} else if (err.code == 'ENOENT') {
res.writeHead(404);
res.end();
} else {
console.log(err);
res.write(err.message);
res.end();
}
});
} else { // no mimetype/ext, it must be a wiki entry
res.writeHead(200, "OK", {
"Content-Type": "text/html",
});
qwiki.parsePage('', '', req, res);
}
});
};

93
acts/edit.js 100644
View File

@ -0,0 +1,93 @@
var fs = require('fs');
module.exports = function(qwiki) {
qwiki.rule('edit', '@@CONTENT@@', function(req, res, instance, next) {
var area = (req.area == '' ? 'front' : req.area.substr(1));
var path = 'wiki/'+area+'.qwk';
res.write('<form action="" method="POST"><label for="page">Page</label> <input type="text" name="page" value="'+area+'"><br>');
res.write('<label for="format">Format</label> <select name="format">');
for (var format in qwiki.formats) {
var page_format = (typeof qwiki.wiki_index.pages[area] !== 'undefined' ? qwiki.wiki_index.pages[area].format : qwiki.getDefault('format'));
res.write('<option ' + (qwiki.formats[format].name == page_format ? 'selected ' : '') + 'value="'+qwiki.formats[format].name+'">'+qwiki.formats[format].fullname+'</option>');
}
res.write('</select><br>');
res.write('<label for="content">Content</label> <textarea width="100%" height="100%" name="content">');
qwiki.readFile(res, path, function(type, err) {
if (type == 'FNF') {
} else if (err) {
res.write(err);
}
res.write('</textarea><input type="submit" name="submit" value="cancel"><input type="submit" name="submit" value="save"></form>');
next();
});
});
qwiki.act('edit', function(req, res) {
var area = (req.area == '' ? 'front' : req.area.substr(1));
// handle POST
if ('submit' in req.fields && req.fields['submit'] == 'save') {
var old_area = area;
if ('page' in req.fields) {
area = req.fields['page'];
}
if (typeof qwiki.wiki_index.pages[area] == 'undefined') {
qwiki.wiki_index.pages[area] = {
format: qwiki.getDefault('format')
};
}
// get our format
if ('format' in req.fields) {
qwiki.wiki_index.pages[area].format = req.fields['format'];
}
//
console.log(old_area + ' vs ' + area);
if (old_area != area) {
fs.rename('wiki/'+old_area+'.qwk', 'wiki/'+area+'.qwk', function() {
qwiki.deleteCache(old_area, function() {
if ('content' in req.fields) {
qwiki.savePage(area, req.fields['content'], function(err) {
if (err) {
res.write(err.code);
res.end();
} else {
qwiki.createCache(area, req.fields['content'], function(err) {
if (err) {
res.write(err.code);
res.end();
} else {
res.writeHead(302, {'Location': '/'+area+'/edit'});
res.end();
}
});
}
});
}
});
});
} else {
if ('content' in req.fields) {
qwiki.savePage(area, req.fields['content'], function(err) {
if (err) {
res.write(err.code);
res.end();
} else {
qwiki.createCache(area, req.fields['content'], function(err) {
if (err) {
res.write(err.code);
res.end();
} else {
res.writeHead(302, {'Location': '/'+area+'/edit'});
res.end();
}
});
}
});
}
}
return;
}
res.writeHead(200, "OK", {
"Content-Type": "text/html",
});
qwiki.parsePage('edit', '', req, res);
});
};

71
acts/index.js 100644
View File

@ -0,0 +1,71 @@
// TODO: Index should likely show the index for the current location if it also contains a directory
var fs = require('fs');
module.exports = function(qwiki) {
qwiki.rule('index', '@@CONTENT@@', function(req, res, instance, next) {
var path = 'wiki/'+req.area;
qwiki.readDirectory(path, function(err, files) {
if (err) {
console.log('err: ' + err);
if (err.errno == -2) { // ENOENT
res.write('Cannot index "' + req.area + '" as it does not exist'); // FIXME: do actual errors
}
res.write('Error: ' + err);
next();
return;
}
files.sort(function(a, b) {
if (a.is_dir == true && b.is_dir == false) return -1;
else if (a.is_dir == false && b.is_dir == true) return 1;
else if (a.is_dir == false && b.is_dir == false) {
var a_ext = qwiki.getExt(a.name);
var b_ext = qwiki.getExt(b.name);
if (a_ext == 'qwk' && b_ext != 'qwk') return -1;
if (a_ext != 'qwk' && b_ext == 'qwk') return 1;
else return 0;
} else {
return 0;
}
});
/*files.sort(function(a, b) {
var a_ext = qwiki.getExt(a.name);
var b_ext = qwiki.getExt(b.name);
if (a_ext == 'qwk' && b_ext != 'qwk') return -1;
if (a_ext != 'qwk' && b_ext == 'qwk') return 1;
else return 0;
});*/
res.write('<h2>Index of '+req.area+'</h2>');
res.write('<ul id="act_index">')
if (req.area != '') {
res.write('<li><a class="file_dir" href="'+req.area+'/../index">..</a></li>');
}
for (var file in files) {
var name = '';
res.write('<li>');
if (qwiki.getExt(files[file].name) == 'qwk') {
name = files[file].name.slice(0, -4);
res.write('<a class="file_qwk" href="'+req.area+'/'+name+'">'+name+'</a>');
} else {
name = files[file].name;
if (files[file].is_dir) {
res.write('<a class="file_dir" href="'+req.area+'/'+name+'/index">'+name+'/</a>');
} else {
res.write('<a class="file_other" href="'+req.area+'/'+name+'">'+name+'</a>');
}
}
res.write('</li>');
}
res.write('</ul>');
next();
});
});
qwiki.rule('index', '@@CONTROLS@@', function(req, res, instance, next) {
res.write('<li><a href="'+(req.area == '' ? '/' : req.area)+'"><img src="/view.png">View</a></li><li><a href="'+req.area+'/upload"><img src="/upload.png">Upload</a></li>');
next();
});
qwiki.act('index', function(req, res) {
res.writeHead(200, "OK", {
"Content-Type": "text/html",
});
qwiki.parsePage('index', '', req, res);
});
};

98
acts/listing.js 100644
View File

@ -0,0 +1,98 @@
var fs = require('fs');
module.exports = function(qwiki) {
qwiki.rule('listing', '@@CONTENT@@', function(req, res, instance, next) {
var article = req.area.substring(req.listing.length+2);
if (article == '') {
res.write('<div class="content_row" id="bot">');
res.write('<div class="right">');
res.write('<h1>'+(req.listing.charAt(0).toUpperCase()+req.listing.slice(1))+'</h1>');
res.write('</div>');
res.write('</div>');
for (var i in qwiki.listings[req.listing]) {
res.write('<div class="content_row" id="bot">');
res.write('<div class="left">');
res.write('<h2>'+qwiki.listings[req.listing][i].date+'</h2>');
res.write('<h3>'+qwiki.listings[req.listing][i].time+'</h3>');
res.write('</div>');
res.write('<div class="right">');
res.write('<a href="'+req.listing+'/'+i+'">'+qwiki.listings[req.listing][i].title+'</a>');
res.write('</div>');
res.write('</div>');
}
next();
} else {
var entry = qwiki.listings[req.listing][article];
//article = article;
var cache_path = 'cache/'+req.listing+'/'+article+'.html';
var title = article;
var date = '00-00-00';
var time = '00:00:00';
if (typeof entry !== 'undefined') {
title = (typeof entry.title !== 'undefined' ? entry.title : article);
date = (typeof entry.date !== 'undefined' ? entry.date : '0');
time = (typeof entry.time !== 'undefined' ? entry.time : '0');
}
res.write('<div class="content_row" id="bot">');
res.write('<div class="left">');
res.write('<h2>'+date+'</h2>');
res.write('<h3>'+time+'</h3>');
res.write('</div>');
res.write('<div class="right">');
res.write('<h1>'+title+'</h1>');
qwiki.readFile(res, cache_path, function(type, err) {
if (type == 'FNF') {
// cache does not exist - is there a wiki source?
var wiki_path = 'wiki/'+req.listing+'/'+article+'.qwk';
fs.stat(wiki_path, function(err, stats) {
// TODO: stats.isFile()
if (err && err.code == 'ENOENT') {
// the wiki entry does not exist
res.write(article + ' does not exist yet');
res.write('</div></div>');
next();
} else if (err) {
// error while statting wiki entry
res.write(article + ': ' + err.code);
res.write('</div></div>');
next();
} else {
// wiki entry exists!
fs.readFile(wiki_path, function(err, data) {
if (err) {
res.write(article + ': ' + err.code);
res.write('</div></div>');
next();
} else {
qwiki.convertAndSave(req.listing+'/'+article, (article in qwiki.wiki_index.pages ? qwiki.wiki_index.pages[article].format : qwiki.getDefault('format')), data, function() {
qwiki.readFile(res, wiki_path, function(type, err) {
if (type == 'FNF') {
res.write('error while creating cache');
res.write('</div></div>');
next();
} else if (err) {
res.write(article + ': ' + err.code);
res.write('</div></div>');
next();
} else {
res.write('</div></div>');
next();
}
});
});
}
});
}
});
} else if (err) {
res.write(article + ': ' + err.code);
res.write('</div></div>');
next();
} else {
res.write('</div></div>');
next();
}
});
}
});
};

62
acts/old/delete.js 100644
View File

@ -0,0 +1,62 @@
// TODO: deletions should check to see if they were the last file in a directory, and if so, to delete the parent folder and redirect to the parent view
// TODO: additionally, deletions should work on generic files and even directories!
var fs = require('fs');
var path = require('path');
module.exports = function(qwiki) {
// **** DELETE
qwiki.rule('delete', '@@CONTENT@@', function(req, res, instance, next) {
res.write('<form action="" method="POST"> Deleting this page will also delete all page revisions! Are you sure you wish to do this?<div class="prompt"><input type="submit" name="submit" value="Yes"><input type="submit" name="submit" value="No"></div></form>');
next()
});
qwiki.act('delete', function(req, res) {
var area = (req.url == '' ? 'front' : req.url.substr(1));
// handle POST
if ('submit' in req.fields) {
if (req.fields['submit'] == 'Yes') {
fs.stat('wiki/'+area+'.qwk', function(err, stat) {
if (err == null) {
qwiki.deletePage(area, function() {
qwiki.deleteCache(area, function() {
console.log('redirecting to '+req.url);
res.writeHead(302, {'Location': req.url});
res.end();
});
});
} else if (err.code == 'ENOENT') {
// does not exist as a wiki document, it's a directory or a file
fs.stat('wiki/'+area, function(err, stat) {
if (err == null) {
if (stat.isDirectory()) {
console.log('request to delete directory');
} else {
fs.unlink('wiki/'+area, function(err) {
console.log('deleted file: ' + area);
});
}
} else if (err.code == 'ENOENT') {
console.log('file "' + area + '" does not exist');
} else {
console.log(err);
}
});
res.writeHead(302, {'Location': '../index'});
res.end();
} else {
console.log(err);
res.writeHead(302, {'Location': '../index'});
res.end();
}
});
return;
} else {
res.writeHead(302, {'Location': req.url+'/edit'});
res.end();
}
} else {
res.writeHead(200, "OK", {
"Content-Type": "text/html",
});
}
qwiki.parsePage('delete', 'edit', req, res);
});
}

97
acts/old/edit.js 100644
View File

@ -0,0 +1,97 @@
var fs = require('fs');
module.exports = function(qwiki) {
qwiki.rule('edit', '@@CONTENT@@', function(req, res, instance, next) {
var area = (req.url == '' ? 'front' : req.url.substr(1));
var path = 'wiki/'+area+'.qwk';
res.write('<form action="" method="POST"><div class="edit"><div><label for="page"><span>This is the page name that corresponds to the wiki URL, e.g., my_page => kettek.net/qwiki/my_page</span>Page</label> <input type="text" name="page" value="'+area+'"></div>');
res.write('<div><label for="format"><span>This is the data format of content source, such as HTML or raw.</span>Format</label> <select name="format">');
for (var format in qwiki.formats) {
var page_format = (typeof qwiki.wiki_index.pages[area] !== 'undefined' ? qwiki.wiki_index.pages[area].format : qwiki.getDefault('format'));
res.write('<option ' + (qwiki.formats[format].name == page_format ? 'selected ' : '') + 'value="'+qwiki.formats[format].name+'">'+qwiki.formats[format].fullname+'</option>');
}
res.write('</select></div>');
res.write('</div><div id="edit_content"><label for="content">Content<span>This is the content of the wiki page</span></label> <textarea name="content">');
qwiki.readFile(res, path, function(type, err) {
if (type == 'FNF') {
} else if (err) {
res.write(err);
}
res.write('</textarea></div><div class="prompt"><input type="submit" name="submit" value="cancel"><input type="submit" name="submit" value="save"></div></form>');
next();
});
});
qwiki.rule('edit', '@@CONTROLS@@', function(req, res, instance, next) {
res.write('<li><a href="'+(req.url == '' ? '/' : req.url)+'"><img src="/view.png">View</a></li><li><a href="'+req.url+'/revisions"><img src="/revisions.png">Revisions</a></li><li><a href="'+req.url+'/delete"><img src="/delete.png">Delete</a></li>');
next();
});
qwiki.act('edit', function(req, res) {
var area = (req.url == '' ? 'front' : req.url.substr(1));
// handle POST
if ('submit' in req.fields && req.fields['submit'] == 'save') {
var old_area = area;
if ('page' in req.fields) {
area = req.fields['page'];
}
if (typeof qwiki.wiki_index.pages[area] == 'undefined') {
qwiki.wiki_index.pages[area] = {
format: qwiki.getDefault('format')
};
}
// get our format
if ('format' in req.fields) {
qwiki.wiki_index.pages[area].format = req.fields['format'];
}
//
console.log(old_area + ' vs ' + area);
if (old_area != area) {
fs.rename('wiki/'+old_area+'.qwk', 'wiki/'+area+'.qwk', function() {
qwiki.deleteCache(old_area, function() {
if ('content' in req.fields) {
qwiki.savePage(area, req.fields['content'], function(err) {
if (err) {
res.write(err.code);
res.end();
} else {
qwiki.createCache(area, req.fields['content'], function(err) {
if (err) {
res.write(err.code);
res.end();
} else {
res.writeHead(302, {'Location': '/'+area+'/edit'});
res.end();
}
});
}
});
}
});
});
} else {
if ('content' in req.fields) {
qwiki.savePage(area, req.fields['content'], function(err) {
if (err) {
res.write(err.code);
res.end();
} else {
qwiki.createCache(area, req.fields['content'], function(err) {
if (err) {
res.write(err.code);
res.end();
} else {
res.writeHead(302, {'Location': '/'+area+'/edit'});
res.end();
}
});
}
});
}
}
return;
}
res.writeHead(200, "OK", {
"Content-Type": "text/html",
});
qwiki.parsePage('edit', '', req, res);
});
};

28
acts/old/new.js 100644
View File

@ -0,0 +1,28 @@
module.exports = function(qwiki) {
qwiki.rule('new', '@@CONTENT@@', function(req, res, instance, next) {
var area = req.url;
if (area == '') {
area = 'new_page';
} else {
area = req.url.substr(1) + '/new_page';
}
var path = 'wiki/'+req.url+'.qwk';
res.write('<form action="" method="POST"><div class="edit"><div><label for="page"><span>This is the page name that corresponds to the wiki URL, e.g., my_page => kettek.net/qwiki/my_page</span>Page</label> <input type="text" name="page" value="'+area+'"></div>');
res.write('</div><div class="prompt"><input type="submit" name="submit" value="edit"></div></form>');
next();
});
qwiki.act('new', function(req, res) {
// handle POST
if ('submit' in req.fields && req.fields['submit'] == 'edit') {
if ('page' in req.fields) {
res.writeHead(302, {'Location': '/'+req.fields['page']+'/edit'});
res.end();
return;
}
}
res.writeHead(200, "OK", {
"Content-Type": "text/html",
});
qwiki.parsePage('new', '', req, res);
});
};

View File

@ -0,0 +1,12 @@
module.exports = function(qwiki) {
// **** REVISIONS
qwiki.rule('revisions', '@@CONTENT@@', function(req, res, instance, next) {
var path = 'wiki/'+req.url+'.qwk';
res.write('revisions for ' + req.url.substr(1));
next()
});
qwiki.act('revisions', function(req, res) {
console.log("revisions action");
qwiki.parsePage('revisions', 'edit', req, res);
});
};

17
acts/old/search.js 100644
View File

@ -0,0 +1,17 @@
module.exports = function(qwiki) {
// **** SEARCH
qwiki.rule('search', '@@CONTENT@@', function(req, res, instance, next) {
if ('submit' in req.fields) {
if ('search' in req.fields) {
res.write('Results for: ' + req.fields['search']);
}
}
next();
});
qwiki.act('search', function(req, res) {
res.writeHead(200, "OK", {
"Content-Type": "text/html",
});
qwiki.parsePage('search', '', req, res);
});
};

74
acts/old/upload.js 100644
View File

@ -0,0 +1,74 @@
var path = require('path');
var fs = require('fs');
module.exports = function(qwiki) {
qwiki.act('upload', function(req, res) {
res.writeHead(200, "OK", {
"Content-Type": "text/html",
});
qwiki.parsePage('upload', '', req, res);
});
qwiki.rule('upload', '@@CONTENT@@', function(req, res, instance, next) {
res.write('<h2>Upload</h2>');
var wiki_path = process.cwd() + '/wiki/';
if (typeof req.files.file !== 'undefined') {
var loc_path = (typeof req.fields.location !== 'undefined' ? req.fields.location+'/' : req.url+'/');
var total = 0;
if (req.files.file instanceof Array) {
for (var i = 0, len = req.files.file.length; i < len; i++) {
var file = req.files.file[i];
var full_path = path.normalize(wiki_path + loc_path + encodeURIComponent(file.name));
if (full_path.indexOf(wiki_path) == -1) {
// TODO: actually show the error to user
res.write('DENIED: Attempted location is out of wiki context.');
end(req, res);
next();
return;
}
moveFile(file.path, full_path, function(err) {
res.write('Uploaded: ' + path.basename(full_path) + '<br>');
total++;
if (total >= len) {
end(req, res);
next();
return;
}
});
}
} else {
var file = req.files.file;
var full_path = path.normalize(wiki_path + loc_path + encodeURIComponent(file.name));
if (full_path.indexOf(wiki_path) == -1) {
res.write('DENIED: Attempted location is out of wiki context.');
end();
next();
return;
}
moveFile(file.path, full_path, function(err) {
res.write('Uploaded: ' + path.basename(full_path) + '<br>');
end(req, res);
next();
});
}
return;
}
end(req, res);
next();
});
function end(req, res) {
res.write('<form enctype="multipart/form-data" action="" method="POST"><div class="edit">');
res.write('<div><label for="file"><span>These are the file(s) to upload</span>File(s)</label> <input type="file" name="file" multiple></div>');
res.write('<div><label for="location"><span>This is the target location to save the file(s) to</span>Location</label> <input type="text" name="location" value="'+req.url+'"></div>');
res.write('</div>');
res.write('<div class="prompt"><input type="submit" name="submit" value="Upload"></div>');
res.write('</form>');
};
function moveFile(from, to, cb) {
qwiki.r_mkdir(path.dirname(to), 0777, function() {
fs.rename(from, to, function(err) {
cb(err);
});
});
};
};

16
acts/updates.js 100644
View File

@ -0,0 +1,16 @@
module.exports = function(qwiki) {
qwiki.rule('updates', '@@CONTENT@@', function(req, res, instance, next) {
for (var i = qwiki.updates.length-1; i >= 0; i--) {
res.write('<div class="content_row" id="bot">');
res.write('<div class="left">');
res.write('<h2>'+qwiki.updates[i].date+'</h2>');
res.write('<h3>'+qwiki.updates[i].time+'</h3>');
res.write('</div>');
res.write('<div class="right">');
res.write(qwiki.updates[i].render);
res.write('</div>');
res.write('</div>');
}
next();
});
};

15
acts/view.js 100644
View File

@ -0,0 +1,15 @@
module.exports = function(qwiki) {
// **** VIEW
qwiki.act('view', function(req, res) {
if (req.area == '') req.area = 'front';
var path = 'wiki/'+req.area+'.qwk';
qwiki.readFile(res, path, function(type, err) {
if (type == 'FNF') {
} else if (err) {
res.write(err);
}
res.end();
});
});
};

72
index.html 100644
View File

@ -0,0 +1,72 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
<title>kettek @@PAGE@@</title>
<link href='http://fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic' rel='stylesheet' type='text/css'>
<link href='https://fonts.googleapis.com/css?family=Montserrat:700' rel='stylesheet' type='text/css'>
<link href='https://fonts.googleapis.com/css?family=Inconsolata' rel='stylesheet' type='text/css'>
<link rel="stylesheet" type="text/css" href="//cloud.github.com/downloads/lafeber/world-flags-sprite/flags16.css" />
<script type="text/javascript" src="/js/Walker.js"></script>
<script type="text/javascript" src="/js/img2popup.js"></script>
<script type="text/javascript" src="/js/history.js"></script>
<script type="text/javascript">
window.onload = function() {
ktk.startWalker('box', 100, 25, 8);
img2popup.Go();
hist.Go();
};
</script>
<link rel="icon" type="image/png" href="/favicon.png">
<link href="/style.css" rel="stylesheet" type="text/css">
</head>
<body>
<div id="content">
<form id="lang" class="f16" method="POST" action="">
<input type="submit" class="flag jp" name="lang" value="jp">
<input type="submit" class="flag us" name="lang" value="eng">
</form>
<div class="row" id="top">
<div class="left">
<a href="/"><h1 id="title">ket<span>tek</span></h1></a>
<div id="box">
<box style="width:100%;left:0;bottom:0;"></box>
<box style="width:1%;left:0;bottom:3px;height:60%"></box>
<box style="width:5%;left:5%;bottom:30%;height:2px"></box>
<box style="width:5%;left:10%;bottom:3px;height:30%"></box>
<box style="width:10%;left:50%;bottom:3px;height:10%"></box>
<box style="width:5%;left:65%;bottom:3px;height:40%"></box>
<box style="width:10%;left:85%;bottom:3px;height:60%"></box>
</div>
</div>
<div class="right">
<div style="position: absolute; top: 0; right: 0px; height:118px; width: 350px; overflow: hidden; padding-right: 16px;z-index:1000;padding-left: 16px; background-color: rgba(10, 10, 10, 0.4); box-shadow: inset 0 0 2px #111;">
<a class="twitter-timeline" width="350px" height="200px" href="https://twitter.com/kts_kettek" data-chrome="transparent noheader nofooter noborders noscrollbar" data-widget-id="693600100510093312">Tweets by @kts_kettek</a><script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0],p=/^http:/.test(d.location)?'http':'https';if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src=p+"://platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>
</div>
<div id="qatbox">
@@QAT@@
</div>
<div id="menu_container">
<div class="menu">
<a href="/software">software</a>
<a href="/games">games</a>
<a href="/articles">articles</a>
<a href="/columbarium">columbarium</a>
</div>
</div>
</div>
</div>
<div id="crumbs">
@@CRUMBS@@
</div>
<div id="main_content">
@@CONTENT@@
</div>
</div>
<div id="footer">
Copyright 2016 <a href="/about">Ketchetwahmeegwun T. Southall</a><br>
Powered by <a href="/software/qwiki">QWiki</a>
</div>
</body>
</html>

149
index.js 100644
View File

@ -0,0 +1,149 @@
var QWiki = require('./QWiki/index.js');
var chokidar = require('chokidar');
var fs = require('fs');
var path = require('path');
var port = 8080;
process.argv.forEach(function (val, index, array) {
var parts = val.split('=');
var key = '';
var value = '';
if (parts[0].substr(0, 2) == '--') {
key = parts[0].substr(2);
value = parts[1];
}
if (key == 'port') {
if (value == '') {
console.log(key + ' needs a value');
} else {
port = Number(value);
}
}
});
var qwiki = new QWiki();
qwiki.addMIMEtype('png', 'image/png');
qwiki.addMIMEtype('jpg', 'image/jpg');
qwiki.addMIMEtype('svg', 'image/svg+xml');
qwiki.addMIMEtype('css', 'text/css');
var m_markdownit = require('markdown-it')({
typographer: true
});
m_markdownit.use(require('markdown-it-anchor'));
m_markdownit.use(require('markdown-it-table-of-contents'), {includeLevel: "2-8"});
m_markdownit.use(require('markdown-it-deflist'));
m_markdownit.use(require('markdown-it-header-sections'));
m_markdownit.use(require('markdown-it-sup'));
qwiki.addFormat('md', 'Markdown', function(source) {
// source is a Buffer, but render seems to need a String
return m_markdownit.render(source.toString());
});
qwiki.setDefault('format', 'md');
function updateQat(index) {
if (index < 0 || index >= qwiki.qats.length);
fs.readFile(qwiki.qats[index].path, function(err, data) {
if (err) throw err;
qwiki.qats[index].source = data.toString();
qwiki.qats[index].render = m_markdownit.render(qwiki.qats[index].source);
});
};
function updateUpdate(index) {
if (index < 0 || index >= qwiki.updates.length);
fs.readFile(qwiki.updates[index].path, function(err, data) {
if (err) throw err;
var filename = path.basename(qwiki.updates[index].path);
filename = filename.substr(0, filename.lastIndexOf('.'));
var parts = filename.split('_', 2);
qwiki.updates[index].date = (parts.length > 0 ? parts[0] : '');
qwiki.updates[index].time = (parts.length > 1 ? parts[1].replace(/-/g, ':') : '');
qwiki.updates[index].source = data.toString();
qwiki.updates[index].render = m_markdownit.render(qwiki.updates[index].source);
});
};
function updateArticles(path) {
fs.readFile(path, function(err, data) {
if (err) throw err;
qwiki.articles = JSON.parse(data);
});
};
function updateSoftware(path) {
fs.readFile(path, function(err, data) {
if (err) throw err;
qwiki.softwares = JSON.parse(data);
});
};
function updateListing(name, path) {
fs.readFile(path, function(err, data) {
if (err) throw err;
qwiki.listings[name] = JSON.parse(data);
});
};
qwiki.listen(port, function() {
console.log('Watching wiki/qat');
qwiki.qats = [];
chokidar.watch('wiki/qat/', {}).on('all', function(event, path) {
if (event == 'add') {
var qat = { path: path, source: '', render: '' };
qwiki.qats.push(qat);
updateQat(qwiki.qats.length-1);
} else if (event == 'unlink') {
for (var i = 0, len = qwiki.qats.length; i < len; i++) {
if (qwiki.qats[i].path == path) {
qwiki.qats.splice(i, 1);
break;
}
}
} else if (event == 'change') {
var qat;
for (var i = 0, len = qwiki.qats.length; i < len; i++) {
if (qwiki.qats[i].path == path) {
qat = qwiki.qats[i];
updateQat(i);
break;
}
}
}
});
console.log('Watching wiki/updates');
qwiki.updates = [];
chokidar.watch('wiki/updates/', {}).on('all', function(event, path) {
if (event == 'add') {
var update = { path: path, source: '', render: '' };
qwiki.updates.push(update);
updateUpdate(qwiki.updates.length-1);
} else if (event == 'unlink') {
for (var i = 0, len = qwiki.updates.length; i < len; i++) {
if (qwiki.updates[i].path == path) {
qwiki.updates.splice(i, 1);
break;
}
}
} else if (event == 'change') {
var update;
for (var i = 0, len = qwiki.updates.length; i < len; i++) {
if (qwiki.updates[i].path == path) {
update = qwiki.updates[i];
updateUpdate(i);
break;
}
}
}
});
console.log('Watching wiki/articles.json');
qwiki.listings = {};
chokidar.watch('wiki/articles.json', {}).on('all', function(event, path) {
if (event == 'add' || event == 'change') {
updateListing('articles', path);
}
});
});

21
package.json 100644
View File

@ -0,0 +1,21 @@
{
"name": "polywiki",
"version": "0.0.1",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "kts of kettek <kettek1@kettek.net> (https://kettek.net/)",
"license": "GPLv3",
"dependencies": {
"chokidar": "^1.4.2",
"formidable": "^1.0.17",
"markdown-it": "^5.0.2",
"markdown-it-anchor": "^2.3.2",
"markdown-it-deflist": "^2.0.0",
"markdown-it-header-sections": "^0.2.0",
"markdown-it-sup": "^1.0.0",
"markdown-it-table-of-contents": "^0.1.2"
}
}

89
wiki/about.qwk 100644
View File

@ -0,0 +1,89 @@
# Ketchetwahmeegwun T. Southall
Constant progging waveform. Mechanical keyboard reprobate.
[![KTS Picture](/kts.png)](/kts.png)
* **E-mail**: kettek1@kettek.net
* **XMPP**: kts@wechat.exoss.net
* **Twitter**: [@kts_kettek](https://twitter.com/kts_kettek)
* **Languages/Systems**:
* 15+ years experience with C
* 10+ years experience with PHP/JavaScript/HTML
* 8+ years experience with C++
* 1+ year experience with Node.js, Express.js, and many others
* Familiarity with Java, Python, Perl, BASH scripting
* 10+ years familiarity with Solaris and Linux
* 6+ years familiarity with Mac OS X and Winderps
* **Sysadmin**:
* 8+ years managing Apache/PHP and SSH services
* 4+ years managing SQL databases
* 3+ years managing XMPP and mumble services
* 2+ years managing named DNS
## [PGP pubkey](/pubkey.gpg)
-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: GnuPG v2.0.22 (GNU/Linux)
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
sxB82jaIVmZB1wZrTG1w704c4xyaNJQ=
=JHLx
-----END PGP PUBLIC KEY BLOCK-----

View File

@ -0,0 +1,9 @@
{
"use-premake-and-start-winning": {"data": "2016-03-15", "time": "03:35:05", "title": "Use Premake (5) and Start Winning"},
"xcode-42-and-c-11": {"date": "2016-02-16", "time": "02:58:45", "title": "XCode 4.2 and C++11"},
"minimalistic-linux-browsers": {"date": "Ongoing", "time": "Eternal", "title": "Linux/X11 Minimalistic Browser Reviews"},
"powermac-g5-to-atx-pinouts": {"date": "2015", "time": "???", "title": "PowerMac G5 Front/Fan/Speaker to ATX/PC pinouts"},
"desktop-feng-shui": {"date": "2015-03-21", "time": "", "title": "Desktop Feng Shui"},
"mangband-hacking": {"date": "2015-02-02", "time": "02:08:10:322", "title": "MAngband Hacking"},
"release-your-source": {"date": "2014-11-28", "time": "", "title": "Release your (Engine's) Source!"}
}

Binary file not shown.

View File

@ -0,0 +1,36 @@
[[toc]]
## Introduction
This document expresses my thoughts on feng shui in the context of the software developer's environment. It emphasizes improving workflow and concentration through the minimization and removal of visual distractions.
## Balance and Harmony
Every desktop and its surroundings possesses particular senses of balance and harmony that may influence the feelings of the user.
For software developers, and in particular programmers, desktop feng shui is of particular importance, as visual distractions and imbalances can be detrimental to one's capability to work.
Although each developer's sense and needs of harmony will differ - and some may not even care or be affected much by such things - in general a sense of good order is of importance. Order is at the foundation of good program design and commenting quality, and as such, this should be emphasized by the environment as well.
Although not required, tiling window managers are excellent methods of enforcing balance and efficiency within the desktop. Even further, the organization of tiling itself, when combined with display sizes and aspect ratios, can enhance harmony and order greatly.
For non-tiling window managers, it is best to keep your desktop in good order, with minimal clutter and strong organization. Failing to do so introduces visual clutter that can easily distract the mind from concentration.
## Colors and Visual Theming
Colors, especially of IDEs and terminals, can play important roles in enhancing concentration and decreasing distractions. In general, muted colors can provide a peaceful sense to the environment, although sometimes can be detrimental when strong notifications are wanted.
The guiding principles for colors should general be to draw focus to the areas one cares about the most. For programming, this generally means that comment areas and folded sections of code should not draw as much attention and should hold to colors that do not call as much attention to themselves. Types, variables, and values should generally call more attention and should be of brighter and more complex coloring. General text should be of a neutral tone at a sufficient brightness so as to not be drowned out by the emphasized texts.
In general, color schemes fall into light and dark schemes, usually of complementary or partially complementary inverted schemes. Although varying from individual to individual, darker schemes can promote a strong sense of focus, especially if bordered by much brighter color schemes. In this way, a dark scheme in the primary programming editor window, if surrounded by brighter schemes containing more information or debugging information, acts as the center point, drawing focus to itself whilst also keeping contained and isolated from the others - i.e., a bastion of focus.
Additionally, the background also plays an important role. Whether it is the precise shade of the color scheme or a graphical background image seen through transparency, the background can promote a sense to the experience and promote particular thoughts in greater earnest. In this sense, it is usually wisest to choose backgrounds that motivate you or promote senses of peace. These backgrounds, if graphical, should likely change to match what you are developing, so as to promote subconscious thought and provide positive reinforcement.
## Beyond the Virtual Desktop
Such principles do not need to be isolated to just the virtual desktop, but can also be expanded to include multiple monitors, the physical desktop, and most everything that can fall within the visual field.
In multi-monitor setups, the distance between monitors, orientations, and size discrepancies can play crucial roles in what feelings are emphasized in the user. Physical distances between monitors can play a similar role to the previously mentioned dark-amidst-light focus scheming. Orientation can promote certain patterns of usage, such as portrait for reading manual pages, or landscape for programming - these things differ, of course, by font size and how many rows and columns one can fit comfortably within the height and width.
With size discrepancies and orientation differences, the virtual desktops' placement should be adjusted so the movement of the mouse from one screen to the other does not contain too much difference - i.e., if moving to the right from Screen 1 to Screen 2, the vertical distance changed between the two should be minimal, and if preferred, centered.
## Beyond the Physical Desktop
Going further than this, what is beyond the physical monitors matter as well. Having an open view, such as a window, can be positive by enhancing moments of meditation and clarity, especially if a peaceful view is to be seen. However, if the view does not promote a sense of peace and is too distracting, the physical location should be adjusted. In a sense, what is behind the physical monitors plays the same role as desktop backgrounds and what sense you wish to have while developing.
## A Holistic Feng Shui
In conclusion, one should develop a strong sense for the entirity of their environment, both virtual and physical, and adjust both to promote the sensibilities they most require. If you wish to focus more on one particular aspect, then mute other portions by chosing softer color schemes, smaller fonts, or increasing the distance between them. Acquiring the proper feng shui of your desktop will require your own experimentation and analysis, but it should be approached if you wish to optimize your own productivity.

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

View File

@ -0,0 +1,69 @@
Got one server with multiple HTTP services?
Want a scheme like:
myhost.net/
-> 127.0.0.1:8080
myhost.net/app1
-> 127.0.0.1:8081
myhost.net/app2
-> 127.0.0.1:8082
OKAY!
Assuming haproxy.cfg's global and defaults sections to be stock:
frontend http-in
bind *:80
# our hosts
acl match_default path_beg /
acl match_app1 path_beg /app1
acl match_app2 path_beg /app2
## map our hosts to the appropriate backends
use_backend host_app1 if match_app1
use_backend host_app2 if match_app2
use_backend host_default if match_default
backend host_default
server node0 127.0.0.1:8080
backend host_app1
server node0 127.0.0.1:8081
reqrep ^([^\ ]*\ /)app1[/]?(.*) \1\2
backend host_app2
server node0 127.0.0.1:8082
reqrep ^([^\ ]*\ /)app2[/]?(.*) \1\2
There ya go!
How about a scheme like:
request for *
-> 10.0.0.1:8081
request for app1.net
-> 10.0.0.2:80
request for app2.net
-> 10.0.0.3:80
Try this!
frontend http-in
bind *:80
# our hosts
acl match_app1 hdr(host) -i app1.net
acl match_app2 hdr(host) -i app2.net
## map our hosts to the appropriate backends
use_backend host_default
use_backend host_app1 if match_app1
use_backend host_app2 if match_app2
backend host_default
server node0 10.0.0.1:8081
backend host_app1
server node0 10.0.0.2:80
backend host_app2
server node0 10.0.0.3:80

View File

@ -0,0 +1,69 @@
[[toc]]
This document describes some technical notes/aspects of MAngband/Angband that I learned while writing an SDL2 interface (so I could play MAngband "unencumbered" on various platforms).
## z-terms
MAngband, being a derivative of Angband, uses the concept of "virtual terminals" or "z-term"s. A z-term is a matrix of rows*columns of cells that correspond to a basic terminal device. Each cell in a z-term may have an "attribute", such as a color, as well as a "character". Characters may be drawn at arbitrary locations within the matrix and the z-term does various intelligent checks to ensure that the minimal amount of updates are triggered to signify an update to whatever the front-end may be.
Getting into the topic of front-ends, z-terms provide a set of a function pointers that act as hooks and are expected to handle certain types of data/information. These hooks are intended to be used to create, draw, and destroy a "z-term" and its interface. These hooks are:
* **void (*init_hook)(term *t);**
* Function that should create the "z-term" interface
* **void (*nuke_hook)(term *t);**
* Function that should destroy the "z-term" interface
* **errr (*user_hook)(int n);**
* User-defined hook, not sure
* **errr (*xtra_hook)(int n, int v);**
* Extremely important function that handles "xtra" events, such as polling for events, playing a sound, delaying, etc.
* **errr (*curs_hook)(int x, int y);**
* Function for drawing the cursor at the given location
* **errr (*wipe_hook)(int x, int y, int n);**
* Function for wiping "n" characters from the given location
* **errr (*pict_hook)(int x, byte a, char c);**
* Function for drawing a special "pict" character -- a graphic image. Byte attribute "a" and char "c" correspond to the row and column of the desired sprite. This function is called when attr "a" and char "c" have their high bits set, thus signifying an image. Proper "row" and "column" coordinates must be acquired by toggling the high bit, e.g., "attr &= ~(1 << 7);" and "ch &= ~(1 << 7);".
* **errr (*text_hook)(int x, int y, int n, byte a, cptr s);**
* Function for drawing a string with attributes from the given location
In the case of MAngband, there are console(cap,ibm,gcu), SDL, X11, Xaw, and Windows "z-term" implementations. Each one of these implementations handles the interfacing of at least 1 "z-term" to the user interface of the implementation.
The base-line requirements for a "z-term" interface is to:
* 1. For each z-term, create a visual window
* 2. Add in a hook to write characters and clear cells
* 3. Handle events and sent to the appropriate z-term
* 4. Handle closing/freeing the window
,,,,,,,,,,,,,,,,,,,,,,,,
MAngband z-term usage
````````````````````````
MAngband can use a total of 8 z-terms, the first of which is the only required one. These terms and their function descriptions are:
* 0 / Main "screen" window
* 1 / ???
* 2 / ???
* 3 / ???
* 4 / Chat
* 5 / ???
* 6 / ???
* 7 / ???
## Basic MAngband logic
The main "connected" loop for MAngband is:
* **keymap_init();**
* **show_motd();**
* **Net_start()**
* **Input_loop();**
* 1. Sleep, then read socket
* 2. Send commands
* 3. Read commands via **process_command()**, then **request_command()**
* 4. flush input via **Term_fresh()**
* 5. **window_stuff()** ???
* 6. Keep alive
* **Net_cleanup();**
* **quit(NULL);**
## MAngband commands and keymaps
One of the more difficult aspects of interfacing with the "z-term" is understanding the proper way to pass keyboard input.

View File

@ -0,0 +1,115 @@
This document covers my personal experiences and opinions of various minimalistic browsers. Sections of this document are likely to update and will be marked as such.
The current list of browsers and their last review times are:
* Midori 0.5.9 - //2014-01-10//
* NetSurf 3.0 - //2014-01-10//
* xombrero 1.6.3 - //2014-01-10//
* dwb 2013.03.30 - //2014-01-10//
As of 2014-01-10, I recommend **dwb** followed by xombrero.
----
My opinion(s) are influenced by the following:
* Slackware, i3wm, and vim
* minimalism for aesthetics __and__ resource usage
* A liking of tabs
* Good keyboard control
## Midori 0.5.9
[![shot_midori.png](/articles/minimalistic-linux-browsers/shot_midori.png)](/articles/minimalistic-linux-browsers/shot_midori.png)
website
: [midori-browser.org](http://midori-browser.org)
requires
: GTK, webkitgtk, libunique, vala
Tab management is on the top, but a plugin allows for vertical tab management. Tab width is rather large, which is not nice.
Overall, very chunky, but pretty fast.
## NetSurf 3.0
[![shot_netsurf.png](/articles/minimalistic-linux-browsers/shot_netsurf.png)](/articles/minimalistic-linux-browsers/shot_netsurf.png)
website
: [netsurf-browser.org](http://netsurf-browser.org)
requires
: GTK
As advertised, NetSurf is a very fast graphical web browser. This speed is accomplished by using a custom layout and rendering engine. While this does indeed provide a fast browsing experience, it can also bring about strong visual differences when compared to other browsers.
Although JavaScript can be enabled from the preferences, I could not get JavaScript to actually work on any of the sites I frequently travel. From the main website, initial JavaScript support was stated as being worked on, but it seems to not be fully implemented. As such, the browsing experience will be limited on any sites using JavaScript enhancements.
Plugins do not seem to work, at least in my experience. Just as with JavaScript, there is an enable Plugins checkbox in the preferences, but it didn't seem to change anything.
Tab management is fairly simple, but is nice enough to allow you to position the tab listing on the top, bottom, left, or right positions of the browser. Given that I prefer side tab listings, this is a very nice feature. Sadly, no tab tree branching/parenting is supported.
Do Not Track options are there, so that is nice.
My final opinion is that is it a nice, extremely fast browser that, sadly, does not provide a modern browsing experience.
## Xombrero 1.6.3
[![shot_xombrero.png](/articles/minimalistic-linux-browsers/shot_xombrero.png)](/articles/minimalistic-linux-browsers/shot_xombrero.png)
website
: [opensource.conformal.com/wiki/xombrero](https://opensource.conformal.com/wiki/xombrero)
requires
: GTK, libbsd, webkitgtk3
Xombrero is a minimalistic browser that prioritizes personal security, saves screenspace, and maintains support for both mouse and keyboard browsing.
Per default, xombrero functions by maintaining a website/domain whitelist for cookies, javascript, and plugins. This mode can be toggled.
Keyboard browsing is accomplished via keystrokes and commands. Commands are handled by opening the prompt with ":" and typing the wanted command.
JavaScript enhanced websites tended to be very problematic, as xombrero did not pass keystrokes to underlying JavaScript.
Sessions can be saved and recalled, however sessions are lost if the browser is closed unexpectedly. There may be a way to guard from this by using session autosaving, however I did not explore this.
Tabs can be visually shown at the top, although this can be disabled. Otherwise, tabs are managed via listing commands in the command prompt.
I experienced crashing on occasion after closing complex websites such as Twitter or YouTube.
Overall, I found it to be quite nice, and the optional mouse-friendly user interface is useful. If security tied to the browser is your thing, xombrero is definitely nice.
## dwb 2013.03.30
[![shot_dwb.png](/articles/minimalistic-linux-browsers/shot_dwb.png)](/articles/minimalistic-linux-browsers/shot_dwb.png)
website
: [portix.bitbucket.org/dwb/](http://portix.bitbucket.org/dwb/)
requires
: GTK, webkitgtk, json-c
dwb actually succeeds at being a truly keyboard-centric browser. Styled after vi/vim, dwb manages to achieve proper keyboard shortcuts by using an **insert** mode that allows keyboard input to pass to the browser unimpeded. Most other browsers I've used tend to choke on page-specific keyboard input and shortcut key conflicts, so kudos here. It must be noted that it took me a few days to get accustomed to switching to insert mode after tab-focus (clicking on text boxes autoswitches, btw), so expect accidental shortcut activation.
Following links using dwb is a breeze, as it uses an extremely nice **hints** system. Via separate keystrokes, one can create "follow" popups for "hints", links, and images, and even choose to open in the same tab, a new tab, or a new window. One __excellent__ feature is that standard link following triggers JavaScript onClick events, so JavaScript enhanced websites work amazingly.
Using the above hinting, links can by copied to the clipboard **or** the current primary selection. This is very nice, as I often use both.
Configuration is managed in-browser which is very nice.
Sessions can be saved and are automatically recovered if the browser is closed unexpectedly.
Click to enable flash that works with keyboard hinting!
A lot more stuff - very feature rich while being very slim.
Fav'd, quite heavily because I like vim.
Major problem. After running for 50 hours, consisting of heavy usage (youtube, twitter, etc.), it was using around 2 gigs of memory with only one blank tab open. There appears to be some meory leaks. CPU usage was nice and low, though.
## vimprobable2
In short, I wish it was more like dwb.
Mode does not auto-switch to insert when tabbing to a text field - it seems to require a mouseclick.
tabs are opened as separate windows which I don't like.
Follow hinting/link is far less sleek - it's like xombrero's "number every link into the hundreds" method. Mouseclicks are emitted, so nice there.
Flash is played per default.
## Conclusion
**dwb** because it actually works as a minimalistic and modern keyboard-centric browser.
Second to that is **xombrero** because it works well enough.

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

View File

@ -0,0 +1,181 @@
[[toc]]
## G5 Front Pinouts
So as to alleviate foolishness, the G5 front panel pinouts, as sourced from the 2005 Power Mac G5 Service Source manual, are:
<--- Locking plastic notch is on this side
1 2
+---+---+
25V - | o | o | - V-GND
+---+---+
FW TPA - | o | o | - FW TPA+
+---+---+
CHS GND FW - | o | o | - CHS GND USB
+---+---+
FW TPB - | o | o | - FW TPB+
+---+---+
USB PWR - | o | o | - USB GND
+---+---+
USB- - | o | o | - USB+
+---+---+
LED - | o | o | - PWR BTN
+---+---+
AUDIO SENSE - | o | o | - AUDIO COM
+---+---+
AUDIO RIGHT - | o | o | - AUDIO LEFT
+---+---+
## USB Pinouts
1 2
+---+---+
VCC - | o | o | - USB +5V
+---+---+
USB0- - | o | o | - USB1 -
+---+---+
USB0+ - | o | o | - USB1 +
+---+---+
GND - | o | o | - GND
+---+---+
| | o | - USB Shield GND
+---+---+
G5 6(CHASSIC GND USB) to 10(Shield)
G5 9(USB PWR) to 1 (VCC)
G5 10(USB GND) to 7 (GND)
G5 11(USB-) to 3 (USB0 -)
G5 12(USB+) to 5 (USB0 +)
For some inexplicable reason, other people's front panel diagrams were pretty screwed up - USB0- to USB- and USB1- to USB+ and similar. Additionally, the most "officious" (most commonly found) G5 front panel pinout had pins 11 and 12, aka USB- and USB+, reversed! According to the official Power Mac G5 Service manual, which covers the Power Mac G5, Power Mac G5 (June 2004), and Power Mac G5 (Early 2005), pin 11 is USB- and pin 12 is USB+.
## Audio Pinouts
1 2
+---+---+
MIC_L - | o | o | - GND
+---+---+
MIC_R - | o | o | - PRESENCE
+---+---+
LINE_R - | o | o | - SNS1_RETURN
+---+---+
SNS_SEND - | o | |
+---+---+
LINE_L - | o | o | - SNS2_RETURN
+---+---+
G5 17(AUDIO RIGHT) to 5 (LINE_R)
G5 16(AUDIO LEFT) to 9 (LINE_L)
G5 15(AUDIO SENSE) to 10 (SNS2_RETURN) -- one schematic tied 10 to 7
G5 16(AUDIO COM) to 2 (GND) -- one schematic also tied in 4
Note that, according to some vague forum sources, you could also tie SNS_SEND to SNS2_RETURN to allow for selection of the device from the operating system:
G5 17(AUDIO RIGHT) to 5 (LINE_R)
G5 16(AUDIO LEFT) to 9 (LINE_L)
G5 16(AUDIO COM) to 2 (GND)
G5 16(AUDIO COM) to 4 (PRESENCE)
10 (SNS2_RETURN) to 7 (SNS_SEND)
## G5 Fan Pinouts
Definitions:
* PWM is Pulse Width Modulation
* SNS is Sense/Fan RPM
* GND is common ground
* 12V is constant +12V (obviously)
* TMP is temperature sensor
All PowerMac G5 fans use the same basic pinout of PWM, SNS, GND, 12V, from pin 1 to pin 4, respectively.
The regular hard-drive bay fan and the PCI fan use the following pinouts:
PWM SNS GND 12V
| | | |
pin 1 +---+---+---+---+ pin 4
| o | o | o | o |
+---+---+---+---+
The "blower" hard-drive bay fan uses a 5-pin connector, however the 5th pin is not connected, so you can safely ignore it:
PWM SNS GND 12V
| | | |
pin 1 +---+---+---+---+---+ pin 5
| o | o | o | o | |
+---+---+---+---+---+
The front CPU fans use the following pinouts:
PWM1 S1 GND 12V PWM2 S2 TMP- TMP+
| | | | | | | |
pin 1 +---+---+---+---+---+---+---+---+ pin 8
| o | o | o | o | o | o | o | o |
+---+---+---+---+---+---+---+---+
The back CPU fans use the following pinouts:
PWM1 S1 GND 12V PWM2 S2
| | | | | |
pin 1 +---+---+---+---+---+---+ pin 6
| o | o | o | o | o | o |
+---+---+---+---+---+---+
## PC Fan Header Pinouts
4-pin ATX motherboard headers, such as those used for the CPU fan are:
GND 12V SNS PWM
| | | |
pin 1 +---+---+---+---+
| o | o | o | o |
+---+---+---+---+
The more common 3-pin motherboard header is the same as the 4-pin, but missing the fourth PWM pin:
GND 12V SNS
| | |
pin 1 +---+---+---+
| o | o | o |
+---+---+---+
## G5 to PC Fan Pinouts
The basic notion is to use the PC motherboard's 4-pin fan header to drive the G5 fans. If you do not have a 4-pin female connector, then a floppy-style molex connector will also fit the motherboard's 4-pin header. The basic pinout for using the motherboard's 4-pin header, in text, is:
G5 1(PWM1) to HDR 4(PWM)
G5 2(SENSE1) to HDR 3(SENSE)
G5 3(GROUND) to HDR 1(GROUND)
G5 4(12V) to HDR 2(12V)
G5 5(PWM2) to HDR 4(PWM)
G5 6(SENSE2) to NOTHING
On my Gigabyte 970A-UD3P motherboard, which uses an ITE 118620E, pin 4 was listed as "Reserved" and output around 4.97 volts constant - this imples +5V VCC, not PWM. However, when I connected all 4 pins to the motherboard, pin 4's output dropped to around 3.5V - this is insufficient to drive "max" PWM for the G5 fans.
However, in the case that your fourth pin does not provide PWM or a constant +5V, or if you're using a 3-pin motherboard header, then you must borrow +5V from the PSU's molex connector. The basic schematic is:
G5 1(PWM1) to PSU +5V
G5 2(SENSE1) to HDR 3(SENSE)
G5 3(GROUND) to HDR 1(GROUND)
G5 4(12V) to HDR 2(12V)
G5 5(PWM2) to PSU +5v
G5 6(SENSE2) to NOTHING
Alternatively, one could make a circuit to convert the variable mobo header +12V to a PWM signal - G5 pin 4 would then have to be powered by a separate +12V molex pin.
If you don't wish to power the fan(s) through the motherboard header, you can instead use a PSU molex connector only:
G5 1(PWM1) to PSU +5V
G5 2(SENSE1) to NOTHING
G5 3(GROUND) to PSU GROUND
G5 4(12V) to PSU +12V
G5 5(PWM2) to PSU +5v
G5 6(SENSE2) to NOTHING
One thing to keep in mind when powering multiple fans from a motherboard header is that the motherboard is only rated to provide a certain amount of amperage through that header - if it exceeds this amount, you can risk damaging the motherboard or the chip responsible for powering the fans. In general, it seems that each fan header provides 1 amp max, however this varies between manufacturers and models, so ensure that you do not exceed this amount.
I am unsure of the actual amperage draw of the G5 fans - standard "PC" fans use around 0.15a, and as far as I can tell, running the G5's fans from the motherboard's header doesn't cause any issues, not even with dual G5 CPU fans running from the same header. I also ran the system through a watt measurement tool and could not find any actual increase in wattage - in fact, the meter measured lower values on average with the G5 fans connected (121-122 without fans, 118-120 with fans). The decrease is most likely due to the CPU fan not being forced to spin as much to keep cool.
## G5 Speaker to PC Pinouts
The speaker pinouts are fairly obvious and the only thing you need to keep track of is the polarity. On the G5's front fan/speaker combo, the 2-pin cable is for the speaker, and the wire with the white stripe down the side represents positive. Most PC motherboards use a 4-pin header plug that only has two wires attached - the pinout is:
G5 white(+) to HDR 1(+)
G5 black- to HDR 4(-)
This could vary for you, so ensure that positive maps to positive and negative to negative.

View File

@ -0,0 +1,54 @@
[[toc]]
## Preface
This writing pertains to the concept of releasing full video game engine source code. It analyzes proclaimed reasons for maintaining proprietary ownership, potential issues, and ultimately claims that placing video game engines as free software or open source holds little personal risk and accomplishes much for global knowledge, development, and communities.
## Introduction
As a game developer and a free software advocate, an inevitable question comes up of whether or not to release one's video game engine under a free software or open source license. The immediate question that comes to mind when commercial video game production is held at the forefront is that such a release could endanger the commercial success or profit of the game due to competing products being released using the same code base. However, while this appears as an initial concern, there are, as far as I understand, no rational reasons for adhering to this belief.
To highlight the chances of risk, let us first analyze what could happen through a delayed source release pattern. Let us assume that Game A is a non-free video game that is being developed by a Studio. Game A uses Engine Z which does not include the art, sound, and other similar, non-engine related assets. In this way, Game A can be broken down into the Engine and the Assets.
After the initial release of the game, which is met with moderate success, the Studio decides to release the source code for Engine Z under a free software license. The Assets for the game are not included with the source code, as the users must generate their own content for Engine Z to allow for a new game to function. Various potentials crop up from this release, which are expounded upon and addressed in terms of probability below.
## Risk 1: Competition
1. A competing product is made that potentially impacts post-release profit.
Although this could occur, the potential of it varies greatly depending on how specific the engine is towards particular game mechanics and logic. The more generalized the engine is, the greater potential there is for a new product to be made from said engine. If the engine is specialized, only similar games can be made.
However, how much probability is there in a new product being made from another engine? Given that there are, as far as my research goes, no successful commercial games that were created from an free software or open source released engine created for a commercial game, it seems fairly improbable. Licensed engines, such as id's various idtech engines, do not count for the reason that at the time their licensing the source code was not released as open source or free software. The absence of this occurance does not guarantee that it could not happen, of course. All the same, there is no compelling argument for this occurring.
In the event of such a (thus far improbable) commercial game from a free software released engine, what would actually occur?
1. Any modifications to the engine's code must be released under the same terms as the free software license, thus keeping knowledge available and increasing user and developer freedom.
2. Depending on the release time and the type of new game using the free software engine, profit for the original developer may or may not be impacted. Given that developing a game, especially a coherent game with a full body of assets, takes much time and effort, it seems unlikely that any substantial profit impact could even occur.
In summation, given that no examples exist of a commercial game being made from a previously released commercial game's engine actually succeeding or even existing in the first place, it seems unlikely that it is even a concern. If a competing game was actually released, it would require a full body of new assets that take a great amount of time and effort to create, thus severely reducing chance for commercial competition. Furthermore, any engine modifications for the new game would have to be released under the same license as the original engine, thus maintaining freedom of and access to knowledge as per free software.
## Risk 2: Game Exploitation
2. Game exploits are created.
This concern is far more legitimate than the first, for the reason that providing an absolute transparency and access to the engine's inner workings mean that reverse engineering does not need to be done. However, the amount of concern for this is dependent on both the type and the design of the game in question. For most games, exploits are inevitable. If the game is a single-player game or most any non-competitive game, the exploits are irrelevent as they only serve to change the game experience for the player. This does not impact profit.
However, in the case of multiplayer games, and especially competitive games, exploits impact more than an individual user and are thus a concern. As is known within the gaming world, exploits - or hacks - are inevitable and something you have to deal with. In general, most anti-hacking systems (such as binary checksumming or similar) can be bypassed. The most trustworthy form of defense is, as is common in the gaming world, having democratic votekicking systems or knowledgable administrators to ban or kick exploitative players.
Given the premise that exploits are ultimately unavoidable, there are methods to counter based on game and network design. For example, if the game uses a centralized server model, wherein a single server ultimately controls the data and logic of all game entities, exploits such as speed hacking can be detected by ensuring the player does not exceed particular movement speeds via particular methods in some given upper limit of ticks. Furthermore, information such as player location, health, and otherwise does not have to be transferred to a given player unless the player is in line-of-sight or within some distance of the other player. Given this, even if the player modifies their client to see health or location, the server does not send enough information unless the situation requires that player knowing that information.
In a non-centralized server model, such as a client-to-client command relay design as used in RTS games such as Starcraft for Age of Empires, exploitation can be limited in that any significant changes to a client's engine would result in a desyncronization of that client. This results in one player experiencing an entirely different outcome separate from the other players, thus nullifying the reason for exploit. However, as was and is the problem with said design, players can use the commands relayed to acquire information on the competing players' units (maphacks, etc.). The counter is to do some form of checksumming that does not only check the binary checksum, which can be easily counterfeited, but rather checksums some amount of live game data between all clients, notifying all clients when a discrepancy is found. One method would be to use the current command history to check if an exploiting player is seeing more of the game world or accessing more than they should be from their relative position. This could be done from any of the clients connected or from a third-party service that simulates command activity.
In summation, exploitation is inevitable and releasing source code may increase the frequency. However, any increase of exploitation due to source release is entirely speculative and could actually result in a decrease due to exploitation or security patches being found and created in the first place. Furthermore, the design of an engine will likely be the most authorative method of dealing with exploits, regardless of source code availability or not. Finally, anti-exploit measures, in the form of detection systems, are possible, however the most reliable form is that of community-based policing via admins or votekicking.
## Risk 3: Easy Piracy
3. Easy Piracy of the Game
Of the two concerns provided thus far, piracy is the most legitimate concern, as most any protection scheme can be by-passed with greater ease due to source availability. Some methods can be created that reduce the chance of this, such as a centralized server that authenticates users based on a product key or account information, however such methods could also be by-passed. However, I hold that this is little different than the current and historical situation of game piracy. As it stands, DRM-style systems are not effective at preventing piracy and generally do best at hindering legitimate users from playing the game they paid for.
Combating piracy is a losing game in which the only vaguely effective method is to restrict the freedoms of legitimate purchasers to such an extreme level that would inevitably lead to a decrease in overall profit due to cumbersome and annoying user restriction.
In summation, even in the non-free world, fighting piracy with DRM is a losing battle that rarely stops illegitimite users and primarily hurts legitimate users. The best combat is to create a fun game with a strong community connection that values and empowers players. If players, regardless of piracy or not, are empowered and valued, they will feel a greater compulsion to support the original developers.
## Conclusion
Given this analysis, it is clear that arguments against source code release of a game's engine ultimately hold little to no water. Competiting products made from the source code are highly unlikely due to the long development window required to create entirely new assets. Exploitation is ultimately the same regardless of source code release or not. Preventing piracy is as it is - a losing battle that fails at any real prevention and usually hurts legitimate players most in the process.
There may be some cases wherein source code release could impact long-term profit not from the original game itself, as other developers could use the source code rather than a licensed engine to develop a new game. However, they would have to release modified works under the same license. It is worth noting that the original developer could do a closed license version to another company that is non-free so long as it does not use any new code contributed under the open source license.
In conclusion, source code release, whether immediate or delayed, causes little to no substantial problems for profit, exploitation, or piracy. Left unaddressed is the potential for public relations and community support and development that could result from source code release.

View File

@ -0,0 +1,137 @@
[[toc]]
## The Setup
Here we are assuming that you have the following systems and you want a competent and easy-to-use cross-platform and native-centric compiling solution:
* Mac OS 10.6.8
* XCode 4.2
* Windows 7
* Visual Studio 2013
* Linux
* GNU Make w/ GCC 4
## The Problem
In my experience, many cross-platform build solutions feel very clunky (CMake) or use a specific IDE to provide cross-platform support (Code::Blocks, GNU Make w/ GCC on Windows with many shivs).
In the case of the former, I prefer highly portable and very small programs that are easy to deploy to any environment -- CMake does not fulfill this. In the case of the latter, I prefer to use the tools intended for a given platform, as it is a headache not only for oneself to set up all the specific requirements, but it is cumbersome to those who wish to simply build your project.
Towards this end, we are searching for a solution that focuses on using **native tools**, is **portable**, and **easy to use**.
The answer that I've found is *Premake* -- version 5 to be exact.
## The Solution: Premake
### What is Premake
Premake is...
### Why Premake
* Single lua script
* Portable binary with built-in lua
### Example premake5.lua
Let's say you have an SDL2 project that uses OpenGL and you want the following
directory structure:
* Project/
* src/
* build/
*src* is where the project source code lies, and *build* is where you want the
project files to end up. After compilation, you want the binary to be placed
in the project root.
To create a script compatible with generating project files for Linux, Windows,
and Mac OS X, you would use a script similar to the following:
solution "Project"
configurations { "Debug", "Release" }
location ("build/" .. _ACTION)
project "Project"
kind "WindowedApp"
language "C++"
targetdir "./"
location ("build" .. _ACTION)
files { "src/**.hpp", "src/**.cpp" }
configuration { "linux" }
buildoptions { "-I/usr/include/SDL2/" }
links { "SDL2", "GLEW", "GL", "pthread" }
configuration "windows"
links { "glew32", "opengl32", "SDL2", "SDL2main", "ws2_32" }
configuration "macosx"
syslibdirs { "/Library/Frameworks/" }
libdirs { "/Library/Frameworks/" }
links { "SDL2.framework", "OpenGL.framework" }
includedirs { "/Library/Frameworks/SDL2.framework/Headers/" }
sysincludedirs { "/Library/Frameworks/SDL2.framework/Headers/" }
### The Linux Build
On Linux, you have multiple options, but here we assume GNU make is our target project file:
premake5 gmake
Afterwards, you can simply enter the *build/gmake* directory and run `make`:
cd build/gmake && make && cd ../..
Now you can execute your program:
./Project
### The Windows Build
On Windows you also have multiple possible IDE project files, but here we assume
Visual Studio 2013:
premake5 vs2013
Now you can open your project file generated in *build/vs2013/* and build/run it.
### From The Command-line: `vsbuild`
![Running vsbuild in Cygwin](cygwin_vsbuild.png)
However, if you're like me, you might prefer being able to use the terminal to
build and run your project as well.
My solution was to create two scripts to be executed: a shell script that
executes a batch file.
The wrapper shell script is simple enough:
#!/bin/bash
cmd /c C:/Users/kts/.local/bin/vsbuild.bat "$@"
The batch is also fairly simple, but you may have to adjust it if you're not using
Visual Studio 2013:
call "C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\vcvarsall.bat" x86
msbuild %*
Now instead of opening the project file with VS, you can simply navigate to the
*build/vs2013* directory and run `vsbuild`:
cd build/vs2013 && vsbuild && cd ../..
You can then execute your program:
./Project.exe
Note: There are some issues with how stdout is handled from within mintty/cygwin
-- output was only flushed when the program finished.
* Compile: `vsbuild`
* Clean: `vsbuild /t:clean`
### The Mac Build
Mac OS X also has multiple options, but here we are using XCode4 due to an older
laptop:
premake5 xcode4
You can then open your project file with XCode and do the normal build/run.
Or use the command-line:
cd build/xcode4 && xcodebuild && cd ../..
You can then run your program:
./Project
Note: There are some obvious problems with not creating an application bundle, so
you likely want to clear the *targetdir* project directive.
* Compile: `xcodebuild`
* Clean: `xcodebuild clean`

View File

@ -0,0 +1,77 @@
[[toc]]
## Preface
This brief guide comes as a result of requiring C++11 support under a Dell Latitude D620 with only Mac OS 10.6.8 peasantry.
Special thanks to those who initially wrote information regarding these processes:
* [How to use a recent GCC with Xcode 5? answer](http://stackoverflow.com/a/19442587) -- **frogcjn**
* [Integrating GCC 4.4 to Xcode (MacOS/Snow Leopard) ](http://skurganov.blogspot.com/) -- **Sergey Kurganov**
## Stage 1. Install GCC 4.8 from Homebrew
For this process, we'll be using Homebrew -- alternatives like macports or manual compilation can be adapted to work as well.
brew update
brew install homebrew/versions/gcc48 --with-all-languages
## Stage 2. Link in new GCC 4.8
For this stage, I opted to keep a similar feel as per the standard GCC versions in /usr/bin, such as /usr/bin/gcc-4.0:
ln -sf /usr/local/Cellar/gcc48/4.8.5/bin/g++-4.8 /usr/bin/g++-4.8
ln -sf /usr/local/Cellar/gcc48/4.8.5/bin/c++-4.8 /usr/bin/c++-4.8
ln -sf /usr/local/Cellar/gcc48/4.8.5/bin/gcc-4.8 /usr/bin/gcc-4.8
ln -sf /usr/local/Cellar/gcc48/4.8.5/bin/ccp-4.8 /usr/bin/cpp-4.8
Thereafter we can link the system gcc/g++/etc. binaries to the new 4.8 versions:
ln -sf /usr/bin/g++-4.8 /usr/bin/g++
ln -sf /usr/bin/c++-4.8 /usr/bin/c++
ln -sf /usr/bin/gcc-4.8 /usr/bin/gcc
vi /usr/bin/cpp
line 51: CPP="gcc-4.8 -E"
[![gcc4.8.5.png](gcc4.8.5.png)](gcc4.8.5.png)
## Stage 3. Install/Create XCode GCC 4.8 plugin
At this point we need a GCC 4.8 compiler plugin for XCode.
Your first option is to download this [zip file](/files/GCC%204.8.xcplugin.zip) and extract it to:
/Developer/Library/Xcode/PrivatePlugIns/Xcode3Core.ideplugin/Contents/SharedSupport/Developer/Library/Xcode/Plug-ins
Your second option is to use the following steps (terminal-centric):
cd /Developer/Library/Xcode/PrivatePlugIns/Xcode3Core.ideplugin/Contents/SharedSupport/Developer/Library/Xcode/Plug-ins
cp -rfpv GCC\ 4.2.xcplugin GCC\ 4.8.xcplugin
cd GCC\ 4.8.xcplugin/Contents/
plutil -convert xml1 Info.plist
vi Info.plist
line 10: <string>com.apple.xcode.compilers.gcc.4_8</string>
line 14: <string>GCC 4.8 Compiler Xcode Plug-in</string>
plutil -convert binary1 Info.plist
cd Resources
mv GCC\ 4.2.xcspec GCC\ 4.8.xcspec
vi GCC\ 4.8.xcspec
line 10: Identifier = "com.apple.compilers.gcc.4_8";
line 13: Name = "GCC 4.8";
line 14: Description = "GNU C/C++ Compiler 4.8";
line 16: Version = "4.8";
line 38: ExecPath = "/usr/bin/gcc-4.8"
line 41: ShowInCompilerSelectionPopup = YES;
line 42: IsNoLongerSupported = NO;
line 252: DefaultValue = NO;
line 876: DefaultValue = NO;
line 1016: DefaultValue = NO;
cd English.lproj
mv GCC\ 4.2.strings GCC\ 4.8.strings
vi GCC\ 4.8.strings
line 11: "Name" = "GCC 4.8";
line 12: "Description" = "GNU C/C++ Compiler 4.8";
line 13: "Version" = "4.8";
Reload XCode and select **GCC 4.8** under *Build Settings -> Build Options -> Compiler for C/C++/Objective-C*.
**Congratulations**, you can now compile with GCC 4.8!
Even more fun, you now have C++11 at your disposal by setting **--std=c++11** under *Build Settings -> GCC 4.8 - Language -> Other C++ Flags*
**Even More Congratulations**, you can now compile with lamdas!

BIN
wiki/bullet.png 100644

Binary file not shown.

After

Width:  |  Height:  |  Size: 131 B

View File

@ -0,0 +1,19 @@
# Columbarium
[[toc]]
Herein lies various projects that are:
* incomplete
* abandoned
* showing the potential for resurrection
----
## Games
### 7DRL2015
Beginnings of a roguelike engine + game.
## Software
### proclib
### kettext
### noirchat
### netwine

Binary file not shown.

View File

@ -0,0 +1,4 @@
# Harmony of the Planes
## Setting
You are citizens of the Grand Temple of the Inner Planes, the heart of all that ties all planes of existence together.

BIN
wiki/favicon.png 100644

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

2
wiki/front.qwk 100644
View File

@ -0,0 +1,2 @@
# Shazam, yo.
This is mad cray

58
wiki/games.qwk 100644
View File

@ -0,0 +1,58 @@
# Games
[[toc]]
Because games are not software?
Most games here are as a result of development competitions and similar. Unlike the rest of humanity, these are ultimately coded from scratch, excluding the use of SDL/SDL2/OpenGL and such similar base libraries.
----
## DCRAWL
* **Site**: [DCRAWL](/games/DCRAWL)
* **Year**: 2015
* **Event**: #TextJam2015
* **Language**: C
* **Libraries**: ncurses/PDCurses
Faux-3D console dungeon crawling game -- or rather, stumble around a maze until you find the invisible exit. Made in far less than 24 hours for **#TextJam2015**.
[![DCRAWL screenshot](/games/DCRAWL.png)](/games/DCRAWL.png)
## Petite Juliet
* **Site**: [Petite Juliet](/games/Petite_Juliet)
* **Year**: 2014
* **Event**: Ludum Dare 31 Compo
* **Language**: C++
* **Libraries**: SDL2, SDL2_image, SDL2_mixer, OpenGL
Single-screen arcade brawling game featuring stylized pixel art. Made primarily the last 24 hours for the **Ludum Dare 31 Compo**.
[![Petite Juliet screenshot](/games/PetiteJuliet.png)](/games/PetiteJuliet.png)
## CirQuit
* **Site**: [CirQuit](/games/CirQuit)
* **Year**: 2014
* **Event**: #NESJAM2014
* **Language**: JavaScript
* **Libraries**: [CBDL](/columbarium/CBDL)
Puzzle game adhering to some NES limitations. Made during a month-long vacation for **NESJAM 2014**.
[![CirQuit screenshot](/games/CirQuit.png)](/games/CirQuit.png)
## Newsboy
* **Site**: [Newsboy](/games/Newsboy)
* **Year**: 2014
* **Event**: #GameMaker2014
* **Language**: C
* **Libraries**: SDL2, SDL2_image, SDL2_ttf, SDL2_mixer, OpenGL
Engine/Game written in C using SDL2_* in approximately a month's time of off and on tinkering. **14k lines of code**!
[![Newsboy screenshot](/games/Newsboy.png)](/games/Newsboy.png)
## VAD
* **Site**: [VAD](/games/VAD)
* **Year**: 2014
* **Event**: #TextJam2014
* **Language**: C
* **Libraries**: ncurses/PDCurses
Text-based adventure parser/engine in the vein of **Adventure**. Made in under 48 hours for **#TextJam2014**
[![VAD screenshot](/games/VAD.png)](/games/VAD.png)

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 808 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 157 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

BIN
wiki/games/VAD.png 100644

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Binary file not shown.

699
wiki/js/Walker.js 100644
View File

@ -0,0 +1,699 @@
var ktk = ktk || {};
/*
===============================================================================
ktk.Walker
===============================================================================
*/
/*
0 0 0 0
/|\ /|\ /|\ /|
_ \ /| |\
*/
ktk.startWalker = function(div, x, y, size) {
new ktk.Walker(div, x, y, size);
}
ktk.walker_data = {
spawn_cycle:
[
[
["---"],
[" "],
[" "]
],
[
["&nbsp;0 "],
["---"],
[" "]
],
[
["&nbsp;0 "],
["/|\\"],
["---"]
],
[
["&nbsp;0 "],
["/|\\"],
["_|_"]
]
],
stand_cycle:
[
[
["&nbsp;0 "],
["/|\\"],
["_|_"]
],
[
["&nbsp;0 "],
["/|\\"],
["_|/"]
]
],
bored_cycle:
[
[
["&nbsp;0 "],
["/|\\"],
["_|_"]
],
[
["&nbsp;&nbsp;0"],
["/|\\"],
["_|_"]
],
[
["&nbsp;0 "],
["-|\\"],
["_|_"]
],
[
["0 "],
["-|-"],
["_|_"]
],
[
["&nbsp;0 "],
["~|-"],
["_|_"]
],
[
["&nbsp;&nbsp;0"],
["~|~"],
["_|_"]
],
[
["&nbsp;0"],
["-|~"],
["_|_"]
]
],
walk_right_cycle:
[
[
["&nbsp;0 "],
["/|\\"],
["&nbsp;\\ "]
],
[
["&nbsp;0 "],
["&nbsp;|"],
["&nbsp;| "]
],
[
["&nbsp;0 "],
[",|\\"],
["/ \\"]
]
],
walk_left_cycle:
[
[
["&nbsp;0 "],
["/|\\"],
["/ \\"]
],
[
["&nbsp;0 "],
["&nbsp;|"],
["&nbsp;| "]
],
[
["&nbsp;0 "],
["/|&gt;"],
["/&nbsp;\\"]
]
],
/*
0 0
<' <`
/` ,|
*/
push_right_cycle:
[
[
["&nbsp;0 "],
["&nbsp;&lt;'"],
["&nbsp;/`"]
],
[
["&nbsp;0 "],
["&nbsp<`"],
["&nbsp;,|"]
]
],
/*
0 0
`> '>
'\ |`
*/
push_left_cycle:
[
[
["&nbsp;0 "],
["`&gt;"],
["'\\"]
],
[
["&nbsp;0 "],
["'&gt;"],
["&nbsp;|`"]
]
],
/*
\0/ \0/ \0/
| | |
/ | \
*/
falling_cycle:
[
[
["\\0/"],
["&nbsp;| "],
["/ "]
],
[
["\\0/"],
["&nbsp;| "],
["&nbsp;| "]
],
[
["\\0/"],
["&nbsp;| "],
["&nbsp;&nbsp;\\"]
]
],
/*
0/ 0, 0'
|, |' |'
/ \ \`
*/
climb_right_cycle:
[
[
["&nbsp;0 "],
["&nbsp;|,"],
["&nbsp;/ "]
],
[
["&nbsp;0,"],
["&nbsp;|'"],
["&nbsp;&nbsp;\\"]
],
[
["&nbsp;0'"],
["&nbsp;|'"],
["&nbsp;\\`"]
]
],
/*
\0 ,0 '0
`| .| '|
\ / /
*/
climb_left_cycle:
[
[
["\\0 "],
["`| "],
["&nbsp;/ "]
],
[
[",0 "],
[".| "],
["/ "]
],
[
["'0 "],
["'| "],
["/ "]
]
]
};
ktk.newSurrounding = function(element, ignore_xy) {
var ignore_xy = (typeof ignore_xy === 'undefined' ? false : true);
var width = parseInt(element.offsetWidth) || parseInt(element.style.width) || parseInt(element.style.minWidth);
var height = parseInt(element.offsetHeight) || parseInt(element.style.height) || parseInt(element.style.minHeight);
var x = (ignore_xy == false ? parseInt(element.offsetLeft) : 0 );
var y = (ignore_xy == false ? parseInt(element.offsetTop) : 0 );
var id = element.id || element.className || 'foo';
return new ktk.Surrounding(element, id, x, y, width, height);
};
ktk.Surrounding = function(element, id, x, y, width, height) {
this.id = id;
this.x = x;
this.y = y;
this.width = width;
this.height = height;
this.element = element;
};
ktk.Walker = function(parent_div, start_x, start_y, start_size) {
_walker_ = this;
if (parent_div == 'body') {
this.world_name = 'body';
this.world_element = document.body;
} else {
this.world_name = parent_div;
this.world_element = document.getElementById(this.world_name);
}
this.world = ktk.newSurrounding(this.world_element, parent_div);
console.log(this.world);
this.surroundings = [];
this.set = "spawn_cycle";
this.last_set = "spawn_cycle";
this.frame = 0;
this.last_frame = 0;
this.order = 0;
this.last_order = 0;
this.is_playing = false;
this.is_acting = true;
this.is_falling = false;
this.next_action = '';
this.last_action = '';
this.action = 'spawn';
this.action_elapsed = 0;
this.action_duration = 100;
this.MOVE_SUCCESS = 0;
this.MOVE_FAILURE = 1;
this.size = start_size;
this.width = this.size*2;
this.height = this.size*3.6;
this.arm_strength = 1;
this.leg_strength = 4;
this.element = document.createElement('div');
this.element.style.fontSize = this.size+"px";
this.element.style.width = this.width+"px";
this.element.style.height = this.height+"px";
this.element.style.display = "block";
this.element.style.position = "absolute";
this.element.id = "ktk.Walker";
this.element.className = "ktkWalker";
this.x = start_x;
this.y = start_y;
this.x_velocity = 0;
this.y_velocity = 0;
this.world_element.appendChild(this.element);
this.Tick = function() {
this.current_time = new Date().getTime();
this.delta_time = (this.current_time - this.previous_time);
this.elapsed_time += this.delta_time;
this.doGravity();
this.Think();
this.Blit();
this.previous_time = this.current_time;
setTimeout(function() { _walker_.Tick(); }, 100);
};
this.Think = function() {
if (!this.is_acting) {
var rand = Math.round(Math.random());
if (rand == 0) {
this.thinkWalk();
} else {
//this.thinkWalk();
this.thinkBored();
}
// if (this.bored_level > 4) {
// this.thinkBored();
// }
} else {
this.doAction();
//this.playSet(this.set, 0);
}
};
this.Blit = function() {
this.element.style.left = this.x+"px";
this.element.style.top = this.y+"px";
};
this.thinkNext = function() {
if (this.next_action == "climb") {
this.action = "climb";
this.action_duration = 2000;
this.is_acting = true;
}
this.next_action = '';
};
this.thinkWalk = function() {
var rand = Math.round(Math.random());
var duration = Math.round(Math.random() * (8000 - 2000) + 2000);
if (rand == 0) {
this.action = "walk_left";
this.action_duration = duration;
this.is_acting = true;
} else {
this.action = "walk_right";
this.action_duration = duration;
this.is_acting = true;
}
};
this.doAction = function() {
this.action_elapsed += 250;
if (!this.is_falling) {
if (this.action == "walk_left") {
this.playSet("walk_left_cycle");
this.Move(-(this.leg_strength), 0);
} else if (this.action == "walk_right") {
this.playSet("walk_right_cycle");
this.Move(this.leg_strength, 0);
} else if (this.action == "bored") {
this.playSet("bored_cycle");
} else if (this.action == "climb_right") {
this.playSet("climb_right_cycle");
this.Move(0, -(this.arm_strength+(this.leg_strength/2)));
} else if (this.action == "climb_left") {
this.playSet("climb_left_cycle");
this.Move(0, -(this.arm_strength+(this.leg_strength/2)));
} else if (this.action == "spawn") {
this.playSet("spawn_cycle");
} else if (this.action == "push_right") {
this.playSet("push_right_cycle");
this.Push((this.arm_strength/2)+(this.leg_strength/2), 0);
} else if (this.action =="push_left") {
this.playSet("push_left_cycle");
this.Push(-((this.arm_strength/2)+(this.leg_strength/2)), 0);
}
if (this.action_elapsed >= this.action_duration) {
this.is_acting = false;
this.last_action = this.action;
this.action = '';
this.action_elapsed = 0;
this.action_duration = 0;
if (this.next_action != '') {
this.action = this.next_action;
this.action_duration = this.next_action_duration;
this.next_action = '';
this.is_acting = true;
}
}
} else {
if (this.last_action == "climb_right") {
if (this.action == "walk_right") {
this.playSet("walk_right_cycle");
//this.Move((this.arm_stength+(this.leg_strength/2)), 0);
this.Move(2, 0);
}
} else if (this.last_action == "climb_left") {
if (this.action == "walk_left") {
this.playSet("walk_left_cycle");
//this.Move(-(this.arm_stength+(this.leg_strength/2)), 0);
this.Move(-2, 0);
}
}
if (this.action == "climb_right") {
this.playSet("climb_right_cycle");
//console.log(-(this.arm_strength+(this.leg_strength)));
//this.Move(0, -(this.arm_stength+(this.leg_strength/2)));
this.Move(0, -4);
} else if (this.action == "climb_left") {
this.playSet("climb_left_cycle");
//this.Move(0, -(this.arm_stength+(this.leg_strength/2)));
this.Move(0, -4);
} else if (this.action == "falling") {
this.playSet("falling_cycle");
} else if (this.action == "spawn") {
this.playSet("spawn_cycle");
}
if (this.action_elapsed >= this.action_duration) {
this.is_acting = false;
this.last_action = this.action;
this.action = '';
this.action_elapsed = 0;
this.action_duration = 0;
this.is_climbing = false;
if (this.next_action != '') {
this.action = this.next_action;
this.action_duration = this.next_action_duration;
this.next_action = '';
this.is_acting = true;
}
}
}
};
this.Move = function(x, y) {
var x_collision = false;
var y_collision = false;
var move_return = this.MOVE_FAILURE;
var collision_check = {collision: false};
if ( (this.x+x > this.world.x && this.x+x+this.width < this.world.x+this.world.width) && (this.y+y > this.world.y && this.y+y+this.height < this.world.y+this.world.height) ) {
for (var i=0;i < this.surroundings.length;i++) {
if (this.surroundings[i].id != this.world_name) {
var collision_check = this.checkCollision(this.x+x, this.y+y, this.surroundings[i]);
if (collision_check.collision == true) {
break;
}
}
}
if (!collision_check.collision) {
this.x += x;
this.y += y;
move_return = this.MOVE_SUCCESS;
} else {
if (collision_check.y < 0 && collision_check.y > -this.height/2) {
this.Move(x, y+(collision_check.y));
} else if (collision_check.y < 0 && collision_check.y > -(this.leg_strength+this.arm_strength)*this.height*2) {
var push_weight = 0;
// Climb!
push_weight += (this.width/(this.surroundings[i].width*16)) + (this.height/(this.surroundings[i].height*16));
var rand = Math.random();
if (rand > push_weight) { // climb
this.action_duration = (Math.abs(collision_check.y)/ (this.leg_strength/2 + this.arm_strength) )*200;
if (collision_check.x > -6) {
this.action = "climb_right";
this.next_action = "walk_right"
this.next_action_duration = 1000;
} else {
this.action = "climb_left";
this.next_action = "walk_left"
this.next_action_duration = 1000;
}
this.is_climbing = true;
} else { // push
this.action_duration = 1500;
if (collision_check.x > -6) {
this.action = "push_right";
} else {
this.action = "push_left";
}
}
} else {
this.action_duration = 0;
}
}
} else {
this.action_duration = 0;
}
return move_return;
};
this.Push = function(x, y) {
var x_collision = false;
var y_collision = false;
var move_return = this.MOVE_FAILURE;
if ( (this.x+x > this.world.x && this.x+x+this.width < this.world.x+this.world.width) && (this.y+y > this.world.y && this.y+y+this.height < this.world.y+this.world.height) ) {
for (var i=0;i < this.surroundings.length;i++) {
if (this.surroundings[i].id != this.world_name) {
var collision_check = this.checkCollision(this.x+x, this.y+y, this.surroundings[i]);
if (collision_check.collision == true) {
break;
}
}
}
if (collision_check.collision) {
if (collision_check.x > -6) {
this.pushSurrounding(i, x, 0);
this.Move(x-1, 0);
} else {
this.pushSurrounding(i, x, 0);
this.Move(x-1, 0);
}
}
} else {
this.action_duration = 0;
}
return move_return;
};
this.pushSurrounding = function(id, x, y) {
this.surroundings[id].x += x;
this.surroundings[id].y += y;
this.surroundings[id].element.style.left = this.surroundings[id].x+"px";
//this.surroundings[id].element.style.left = parseInt(this.surroundings[id].element.style.left)+x+"px";
this.surroundings[id].element.style.top = this.surroundings[id].y+"px";
//this.surroundings[id].element.style.top = parseInt(this.surroundings[id].element.style.top)+y+"px";
};
this.doGravity = function() {
//this.push_y += 2;
if (this.Move(0, 3) == this.MOVE_SUCCESS) {
this.is_falling = true;
if (!this.is_climbing) {
// this.action = "falling";
// this.action_duration += 250;
}
} else {
this.is_falling = false;
if (this.action == "falling") {
this.action = '';
this.action_duration = '';
}
}
};
this.checkCollision = function(new_x, new_y, target) {
var collision_x = 0;
var collision_y = 0;
var collision = false;
var is_collision_x = false;
var is_collision_y = false;
if ((new_x+this.width) > target.x && new_x < target.x+target.width) {
is_collision_x = true;
}
collision_x = target.x - (new_x+this.width);
/*if ((new_x+this.width) <= target.x) {
collision_x = target.x - (new_x-this.width);
//} else if (new_x >= target.x+target.width) {
} else {
collision_x = (target.x+target.width) - new_x;
}*/
if (new_y+this.height > target.y && new_y < target.y+target.height) {
is_collision_y = true;
}
collision_y = target.y - (new_y+this.height);
/*if (new_y+this.height <= target.y) {
collision_y = target.y - (new_y+this.height);
//} else if (new_y >= target.y+target.height) {
} else {
collision_y = (target.y+target.height) - new_y;
}*/
//console.log(collision_x+"_"+collision_y);
if (is_collision_x && is_collision_y) {
collision = true;
}
return {collision: collision, collision_x: collision_x, collision_y: collision_y, x: collision_x, y: collision_y};
};
this.thinkBored = function() {
var duration = Math.round(Math.random() * (1000 - 4000) + 4000);
this.action = "bored";
this.action_duration = duration;
this.is_acting = true;
/*
if (this.last_set == "walk_left_cycle") {
if (this.last_frame == ktk.walker_data[this.last_set].length-1) {
this.playSet("walk_left_cycle", 1);
} else {
this.playSet("walk_left_cycle", 0);
}
} else {
this.playSet("walk_left_cycle");
}*/
};
this.buildSurroundings = function(target_div) {
target_div = (typeof target_div !== 'undefined' ? this.world_element : document.body);
this.elements_list = target_div.getElementsByTagName('*');
for (var i=0; i < this.elements_list.length; i++) {
if (this.elements_list[i].id !== this.world_name && this.elements_list[i].id !== this.element.id) {
var new_surrounding = ktk.newSurrounding(this.elements_list[i]);
if (new_surrounding != 1) {
this.surroundings.push(new_surrounding);
}
}
}
console.log(this.surroundings);
};
this.playSet = function(set, order) {
set = (typeof set !== 'undefined' ? set : this.set);
order = (typeof order !== 'undefined' ? order : this.order);
if (this.last_set == set) {
if (this.last_frame == ktk.walker_data[this.last_set].length-1) {
order = 1;
} else {
order = 0;
}
}
if (this.set != set) {
this.set = set;
this.frame = 0;
this.order = order;
this.is_playing = true;
} else {
if (order == 0) {
if (this.frame < ktk.walker_data[this.set].length-1) {
this.frame++;
this.setFrame(this.set, this.frame);
} else {
this.last_set = this.set;
this.last_frame = this.frame;
this.is_playing = false;
}
} else if (order == 1) {
if (this.frame > 0) {
this.frame--;
this.setFrame(this.set, this.frame);
} else {
this.last_set = this.set;
this.last_frame = this.frame;
this.is_playing = false;
}
}
}
};
this.setFrame = function(set, number) {
if(ktk.walker_data[set]) {
if (ktk.walker_data[set][number]) {
this.set = set;
this.frame = number;
this.element.innerHTML = ktk.walker_data[set][number][0] +
'<br>' + ktk.walker_data[set][number][1] +
'<br>' + ktk.walker_data[set][number][2];
}
}
};
this.buildSurroundings(this.world_name);
this.setFrame("stand_cycle", 0);
this.Tick();
}

77
wiki/js/history.js 100644
View File

@ -0,0 +1,77 @@
/* This script implements HTML5 History states for clients that support it. It parses all links for those beginning in "?"(local), replaces with History-browsing functionality, and onclick updates the "content" div (and reparses accordingly). */
var hist = {
content: null,
crumbs: null,
title: 'kettek',
Go: function() {
if (window.history.replaceState === undefined) return;
this.content = document.getElementById("main_content");
//document.title = this.title + ' ' + this.getFirstHeaderText(this.content);
this.crumbs = document.getElementById('crumbs');
window.history.replaceState({content: this.content.innerHTML, url: window.location.href, title: document.title}, document.title, window.location.href);
this.doParse();
window.onpopstate = this.popState;
},
doParse: function(ele) {
hist.buildCrumbs();
var l = (typeof ele === 'undefined' ? document.getElementsByTagName('A') : ele.getElementsByTagName('A'));
for (var i = 0; i < l.length; i++) {
if (!l[i].href) continue;
if (l[i].host !== window.location.host) continue;
var last = l[i].href.lastIndexOf('/');
var area = l[i].href.substr(last+1);
if (area.indexOf('.') > -1) continue; // ignore files with extensions
if (l[i].hash) {
if (window.location.host+window.location.pathname == l[i].host+l[i].pathname) continue;
}
l[i].onclick = function() {
hist.loadContent(this.getAttribute("href"));
return false;
};
}
img2popup.doParse(hist.content);
},
loadContent: function(target) {
var r = new XMLHttpRequest();
r.open("GET", target+'?QRULE=@@CONTENT@@', true);
r.onreadystatechange = (function(r, target) { return function() {
switch (r.readyState) {
case 4:
document.title = hist.title+' '+target;
window.history.pushState({content: r.responseText, url: target, title: hist.title+' '+target}, target, target);
hist.content.innerHTML = r.responseText;
hist.doParse(hist.content);
break;
}
}})(r, target);
r.send();
},
popState: function(e) {
if (e.state == null) return;
document.title = e.state.title;
hist.content.innerHTML = e.state.content;
hist.doParse(hist.content);
},
buildCrumbs: function() {
hist.crumbs.innerHTML = '';
var parts = window.location.pathname.split('/');
var path = '';
parts[0] = '>';
for (var i = 0; i < parts.length; i++) {
if (parts[i] == '') continue;
path += (i == 0 ? '/' : parts[i]);
var li = document.createElement('li');
var a = document.createElement('a');
a.href = path;
a.innerHTML = parts[i];
li.appendChild(a);
hist.crumbs.appendChild(li);
path += (i == 0 ? '' : '/');
}
},
getFirstHeaderText: function(el) {
var els = el.getElementsByTagName('H1');
if (els.length >= 1) return els[0].innerHTML;
return '';
}
};

View File

@ -0,0 +1,180 @@
/* This script acquires all image tags encased in anchor tags that link to an image file then adds onclick events to popup + zoom the image rather than visiting the given link. */
var img2popup = {
popup: null,
focused: false,
width: 0,
height: 0,
twidth: 0,
theight: 0,
left: 0,
top: 0,
start_time: 0,
zoom_time: 250,
delta: 0,
Go: function(ele) {
if (this.popup == null) this.doSetup();
this.doParse();
},
doParse: function(ele) {
var context = (typeof ele === 'undefined' ? document.getElementsByTagName("img") : ele.getElementsByTagName("img"));
for (var i = 0; i < context.length; i++) {
var img = context[i];
var p = context[i].parentNode;
if (p.nodeName == "A") {
if (p.href.match(/\.(png|jpg|jpeg|gif)$/)) {
p.onclick = (function(p, img) { return function(e) {
if (!e) var e = window.event;
e.cancelBubble = true; if (e.stopPropagation) e.stopPropagation();
img2popup.popup.src = p.href;
img2popup.popup.style.width = img.clientWidth+'px';
img2popup.popup.style.height = img.clientHeight+'px';
var style = window.getComputedStyle(img, null);
var bbox = img.getBoundingClientRect();
img2popup.left = bbox.left + (((bbox.right-bbox.left)-parseInt(style.getPropertyValue('width')))/2);
img2popup.top = bbox.top + (((bbox.bottom-bbox.top)-parseInt(style.getPropertyValue('height')))/2);
return false;
}})(p, img);
}
}
}
},
doSetup: function() {
// create our black bg
this.bg = document.createElement("div");
this.bg.style.visibility = "hidden";
this.bg.style.position = "fixed";
this.bg.style.left = 0;
this.bg.style.top = 0;
this.bg.style.width = "100%";
this.bg.style.height = "100%";
this.bg.style.backgroundColor = "#111";
this.bg.style.opacity = 0;
this.bg.style.zIndex = "1999";
document.body.appendChild(this.bg);
// create our actual popup element
this.popup = document.createElement("img");
this.popup.style.visibility = "hidden";
this.popup.style.position = "fixed";
this.popup.id = "popup";
this.popup.style.zIndex = "2000";
this.popup.onload = function() {
this.style.width = this.style.height = '';
img2popup.width = this.width; img2popup.height = this.height;
img2popup.start_time = new Date;
img2popup.doResize();
this.style.visibility = "visible";
img2popup.bg.style.visibility = "visible";
img2popup.focused = true;
};
document.body.appendChild(this.popup);
document.addEventListener('click', function(e) {
if (!e) var e = window.event;
e.cancelBubble = true; if (e.stopPropagation) e.stopPropagation();
if (e.button != 2 && img2popup.focused) img2popup.doHide();
return false;
});
document.addEventListener('keydown', function(e) {
if (e.which == 27 && img2popup.focused) img2popup.doHide();
});
window.onresize = img2popup.doResize;
},
doHide: function() {
if (this.timer == null) {
img2popup.start_time = new Date;
this.timer = setInterval(function() { img2popup.doReverp(); }, 10);
}
},
doResize: function() {
var w = img2popup.width;
var h = img2popup.height;
var sw = (window.innerWidth || document.documentElement.clientWidth);
var sh = (window.innerHeight || document.documentElement.clientHeight);
var r = Math.min((sw-32) / w, (sh-32) / h);
if (r < 1.0) {
w *= r;
h *= r;
}
img2popup.twidth = w;
img2popup.theight = h;
if (this.timer == null) this.timer = setInterval(function() { img2popup.doInterp(); }, 10);
},
doInterp: function() {
var delta = new Date - img2popup.start_time;
var R = delta / img2popup.zoom_time; // ratio of delta to zoom time
var Rr = (1.0 - R); // reverse delta ratio
var w = img2popup.twidth; // target resize width
var h = img2popup.theight; // target resize height
// center of client window
var sw = (window.innerWidth || document.documentElement.clientWidth);
var sh = (window.innerHeight || document.documentElement.clientHeight);
// calculate reverse target dimensions
w *= R;
h *= R;
// get left and top offsets to image origin with reverse ratio
var ix = img2popup.left * Rr;
var iy = img2popup.top * Rr;
// get center offsets with ratio
var ox = ((sw/2) - (w/2)) * R;
var oy = ((sh/2) - (h/2)) * R;
// apply our styling
this.popup.style.left = (ox+ix)+'px';
this.popup.style.top = (oy+iy)+'px';
this.popup.style.width = w+"px";
this.popup.style.height = h+"px";
this.popup.style.opacity = 1.0 * R;
this.bg.style.opacity = 0.9 * R;
// and, of course, stop the loop if zoom_time has elapsed
if (delta >= img2popup.zoom_time) {
clearInterval(this.timer);
this.timer = null;
w = img2popup.twidth;
h = img2popup.theight;
this.popup.style.left = (sw/2)-(w/2)+'px';
this.popup.style.top = (sh/2)-(h/2)+'px';
this.popup.style.width = w+"px";
this.popup.style.height = h+"px";
this.popup.style.opacity = 1.0;
this.bg.style.opacity = 0.9;
}
},
doReverp: function() {
var delta = new Date - img2popup.start_time;
var R = delta / img2popup.zoom_time; // ratio of delta to zoom time
var Rr = (1.0 - R); // reverse delta ratio
var w = img2popup.twidth; // target resize width
var h = img2popup.theight; // target resize height
// center of client window
var sw = (window.innerWidth || document.documentElement.clientWidth);
var sh = (window.innerHeight || document.documentElement.clientHeight);
// calculate reverse target dimensions
w *= Rr;
h *= Rr;
// get left and top offsets to image origin with ratio
var ix = img2popup.left * R;
var iy = img2popup.top * R;
// get center offsets with reverse ratio
var ox = ((sw/2) - (w/2)) * Rr;
var oy = ((sh/2) - (h/2)) * Rr;
// apply our styling
this.popup.style.left = (ox+ix)+'px';
this.popup.style.top = (oy+iy)+'px';
this.popup.style.width = w+"px";
this.popup.style.height = h+"px";
this.popup.style.opacity = 1.0 * Rr;
this.bg.style.opacity = 0.9 * Rr;
// and, of course, stop the loop if zoom_time has elapsed
if (delta >= img2popup.zoom_time) {
clearInterval(this.timer);
this.timer = null;
this.popup.style.opacity = 0.0;
this.popup.style.visibility = "hidden";
this.popup.src = "";
this.bg.style.opacity = 0.0;
this.bg.style.visibility = "hidden";
this.focused = false;
}
}
};

BIN
wiki/kts.png 100644

Binary file not shown.

After

Width:  |  Height:  |  Size: 89 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.7 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 MiB

BIN
wiki/pix/Lolita.png 100644

Binary file not shown.

After

Width:  |  Height:  |  Size: 585 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 392 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 320 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 386 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

65
wiki/pubkey.gpg 100644
View File

@ -0,0 +1,65 @@
-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: GnuPG v2.0.22 (GNU/Linux)
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
sxB82jaIVmZB1wZrTG1w704c4xyaNJQ=
=JHLx
-----END PGP PUBLIC KEY BLOCK-----

BIN
wiki/qat.png 100644

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

View File

@ -0,0 +1 @@
Expedite progress -- think in the future, become estranged from the now.

View File

@ -0,0 +1 @@
The **Order of Precedence** is to _improve oneself_, _learn_, and _have fun_. One should first seek to improve oneself. Improving oneself often comes through learning. Learning comes best with it is fun. However, if learning is not fun, one must still learn. If improving oneself does not acquire new knowledge, one must still improve. In this way, one must always seek these things, but be willing to do away with the least of them.

View File

@ -0,0 +1 @@
Societies and their idiosyncracies see themselves as the pinnacle of all worlds -- the only possible -- or probable -- formation of society.

View File

@ -0,0 +1 @@
To society's human, the first principles of their society are seen as immutable properties of general human organization and being. Every possible world is seen through a strict lense of societal-formulative biases -- core fundamentals taken for granted as the required basis for humanity.

View File

@ -0,0 +1 @@
Move beyond modern limitations, doubt fundamentals and entertain worlds void of preformulated idiosyncrasies. Imagine and strive towards the altogether different.

View File

@ -0,0 +1 @@
Approach others first as a friend, then as a teacher -- in all ways possible, speak to promote learning and experimentation.

View File

@ -0,0 +1 @@
Avoid immaterial and trite expenditures of time and energy. Any moment not spent improving oneself decreases the maximum potential for flourishing.

View File

@ -0,0 +1 @@
Seek to extend yourself beyond your abilities, ignore perceived limitations, and, above all, be entirely unreasonable in your desire and drive to create.

View File

@ -0,0 +1 @@
Do not waste time debating the worth of one tool over another. Even a coarse brush can create fine art in the hands of one who truly seeks to create.

BIN
wiki/qwat.png 100644

Binary file not shown.

After

Width:  |  Height:  |  Size: 427 B

BIN
wiki/slkscr.ttf 100644

Binary file not shown.

View File

@ -0,0 +1,4 @@
{
"adobar": {"date": "2016-02-16", "time": "02:58:45", "title": "Adobar"},
"qwiki": {"date": "Ongoing", "time": "Eternal", "title": "QWiki"}
}

52
wiki/software.qwk 100644
View File

@ -0,0 +1,52 @@
# Software
[[toc]]
Most of the still usable and/or relevant things I've created -- see [Columbarium](/columbarium) for software of a forgotten era.
----
## Substantial Things
### [Adobar](/software/adobar) -- HTML5/CSS3 Animation Program
* **Whyy**: Because everything else sucks.
* **System**: Linux, Windows, OS X, anything supported by XUL.
Actually create HTML5/CSS3 animations with this XUL program!
### [QWiki](/software/qwiki) -- Node.js file-based wiki to make life easy.
* **Whyy**: Because simplicity.
* **System**: Anything supported by Node.js
A Node.js HTTP server that provides a customizable wiki using files as the database. Easily expandable to use different text renderers, such as Markdown.
[![QWiki.png](/software/QWiki.png)](/software/QWiki.png)
## Minor Things
### [polymail](/software/polymail) -- Send spam with ease!
* **Whyy**: Creating and sending newsletters via console was annoying.
* **System**: Anything supported by Node.js
A Node.js program that manages sending emails to multiple recipients, using Markdown as the default newsletter's renderer.
### [ARK](/software/ark) -- become a Cool Kid(tm) with a **brand new** directory indexer!
* **Whyy**: AJAX.
* **System**: Apache/PHP
A fancy HTML5 & JavaScript PHP directory index intended to replace Apache's default.
### [proclib](/software/proclib) -- struggle with a parser in the pursuit of randomization.
* **Whyy**: Experimentation in guided randomized map generation via a custom parser
* **System**: Linux, Windows, OS X, whatever you can get C to compile on
Doggedly attempt to understand proclib's syntax, I dare you (it's actually pretty straight forward).
### [EBIC](/software/EBIC) -- batch convert all the images!
* **Whyy**: At the time, a distinct lack of any similar simple utility.
* **System**: Mac OS 10.3+
AppleScript frontend to `sips` for converting/resizing images en masse.
### [EPPPD](/software/EPPPD) -- pppd all the TTY devices!
* **Whyy**: Playing with AppleScript.
* **System**: Mac OS 10.3+
AppleScript frontend to pppd.
## Scripts
### [JavaScript](/software/js)
A collection of scripts pertaining to JavaScript, generally for the browser or Node.js.
### [Shell scripts](/software/shell)
Various shell scripts for shell scripting things.

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

View File

@ -0,0 +1 @@
# Shell Scripts

409
wiki/style.css 100644
View File

@ -0,0 +1,409 @@
@font-face {
font-family: silkscreen;
src: url(slkscr.ttf);
}
html,body {
margin: 0; padding: 0;
width: 100%; height: 100%;
font-size: normal;
font-family: "Inconsolata", serif;
color: #DDD;
background-color: #111;
}
h1,h2,h3,h4,h5 {
margin: 0;
font-family: "Montserrat", sans-serif;
text-shadow: 0px 0px 2px #000;
}
h1 { font-size: 150%; }
h2 { font-size: 125%; }
h3 { font-size: 115%; }
h4 { font-size: 105%; }
h5 { font-size: 100%; }
a {
color: #d1901a;
}
#content {
width: 1000px;
margin: auto;
-webkit-border-radius: 8px;
-moz-border-radius: 8px;
border-radius: 8px;
box-shadow: 0px 0px 3px #111;
margin-bottom: 1em;
position: relative;
overflow: hidden;
box-sizing: border-box;
min-height: 75%;
}
/* top and bot styling */
#top .left {
font-size: 100%;
}
#top .left:after {
border: 0;
position: absolute;
z-index: 100;
}
#top {
background-image: url('pix/Lolita1_2.png');
background-repeat: no-repeat;
background-position: center;
-webkit-border-radius: 8px;
-moz-border-radius: 8px;
border-radius: 8px 8px 0 0;
box-shadow: 0px 0px 3px #111;
min-height: 180px;
}
#top:before {
content: '';
position: absolute;
z-index: 100;
left: 0;
top: 0;
width: 100%;
height: 100%;
background-color: rgba(10, 10, 10, 0.4);
background-image: -webkit-repeating-linear-gradient(135deg, rgba(0,0,0,.1), rgba(0,0,0,.1) 1px, transparent 2px, transparent 2px, rgba(0,0,0,.1) 3px);
background-image: -moz-repeating-linear-gradient(135deg, rgba(0,0,0,.1), rgba(0,0,0,.1) 1px, transparent 2px, transparent 2px, rgba(0,0,0,.1) 3px);
background-image: -o-repeating-linear-gradient(135deg, rgba(0,0,0,.1), rgba(0,0,0,.1) 1px, transparent 2px, transparent 2px, rgba(0,0,0,.1) 3px);
background-image: repeating-linear-gradient(135deg, rgba(0,0,0,.1), rgba(0,0,0,.1) 1px, transparent 2px, transparent 2px, rgba(0,0,0,.1) 3px);
-webkit-background-size: 8px 8px;
-moz-background-size: 8px 8px;
background-size: 8px 8px;
}
/* default row and column settings */
.row {
position: relative;
margin: auto;
margin-top: 2em;
display: -webkit-box;
display: -moz-box;
display: -ms-flexbox;
display: -webkit-flex;
display: flex;
-webkit-flex-flow: row wrap;
justify-content: flex-start;
align-items: stretch;
width: 100%;
z-index: 1000;
}
.content_row {
position: relative;
margin: auto;
display: -webkit-box;
display: -moz-box;
display: -ms-flexbox;
display: -webkit-flex;
display: flex;
-webkit-flex-flow: row wrap;
justify-content: flex-start;
align-items: stretch;
width: 100%;
padding: 2em 2em 0 2em;
box-sizing: border-box;
background-color: #222;
background-image: -webkit-repeating-linear-gradient(135deg, rgba(0,0,0,.3), rgba(0,0,0,.3) 1px, transparent 2px, transparent 2px, rgba(0,0,0,.3) 3px);
background-image: -moz-repeating-linear-gradient(135deg, rgba(0,0,0,.3), rgba(0,0,0,.3) 1px, transparent 2px, transparent 2px, rgba(0,0,0,.3) 3px);
background-image: -o-repeating-linear-gradient(135deg, rgba(0,0,0,.3), rgba(0,0,0,.3) 1px, transparent 2px, transparent 2px, rgba(0,0,0,.3) 3px);
background-image: repeating-linear-gradient(135deg, rgba(0,0,0,.3), rgba(0,0,0,.3) 1px, transparent 2px, transparent 2px, rgba(0,0,0,.3) 3px);
-webkit-background-size: 8px 8px;
-moz-background-size: 8px 8px;
background-size: 8px 8px;
}
.content_row img {
width: 50%;
text-align: center;
display: block;
margin: 1em auto;
box-shadow: 0px 0px 3px #111;
border-radius: 8px;
padding: 1em;
background-color: #111;
}
.left {
color: #999;
color: #D6A;
position: relative;
min-height: 1em;
flex: 1;
padding: 0px 48px 16px 16px;
text-align: right;
font-size: xx-small;
z-index: 1000;
}
.left:after {
content: "";
position: absolute;
width: 1em;
height: 20%;
top: 0px;
right: 0%;
border-right: 1px dotted #666;
border-right: 1px dotted #D6A;
border-right: 2px dotted #d1901a;
}
.right {
min-height: 1em;
flex: 7;
padding: 0px 2em 0em 2em;
z-index: 1000;
}
/* row animation */
@keyframes open {
0% { right: 100%; opacity: 0; }
50% { right: -8%; opacity: 1; }
60% { right: 4%; }
70% { right: -2%; }
80% { right: 0%; }
100% { right: 0%; }
}
.content_row {
animation: open 1s;
}
/* play box*/
#box {
position: relative;
display: block;
right: 0;
top: 0;
margin-left: 8px;
margin-top: 24px;
margin-bottom: 6px;
width: 570px;
height: 94px;
background-color: #111;
box-shadow: 0px 0px 8px #111;
opacity: 0.8;
}
box {
position: absolute;
display: block;
border: 1px solid #D6A;
width: 1px; height: 2px;
}
.ktkWalker {
font-weight: 800;
font-family: monospace;
text-align: center;
}
/* menu */
#menu_container {
position: absolute;
left: 0;
bottom: 0;
width: 586px;
margin-left: 16px;
margin-right: 20px;
z-index: 1000;
}
.menu {
margin: 0;
padding: 0;
display: flex;
flex-flow: row wrap;
justify-content: center;
align-items: left;
}
.menu a {
flex-grow: 1;
text-align: center;
/*box-shadow: inset 0px 0px 3px #d1901a;*/
font-family: "Montserrat", sans-serif;
color: #d1901a;
background-color: rgba(34, 34, 34, 0.8);
border-radius: 8px 8px 0 0;
text-decoration: none;
display: block;
padding: 0.5em;
transition: all .10s;
text-shadow: 0px 0px 2px #000;
box-shadow: inset 0px 0px 4px #181818;
margin-right: 0.5em;
margin-left: 0.5em;
}
.menu a:hover {
background-color: rgba(10, 10, 10, 0.5);
-webkit-transition: background-color .10s linear;
-moz-transition: background-color .10s linear;
-o-transition: background-color .10s linear;
-ms-transition: background-color .10s linear;
transition: background-color .10s linear;
}
p {
text-align: justify;
}
/* breadcrumbs */
#crumbs {
position: absolute;
left: 3em;
z-index: 1000;
}
#crumbs li {
list-style-type: none;
float: left;
padding: 0; margin: 0;
}
#crumbs a {
text-decoration: none;
margin-right: 1em;
padding: 0 0.5em 0.5em 0.5em;
transition: all .10s;
background-color: rgba(10, 10, 10, 0.1);
text-shadow: 0px 0px 2px #333;
box-shadow: inset 0px 0px 6px #111;
}
#crumbs a:hover {
background-color: rgba(10, 10, 10, 0.5);
-webkit-transition: background-color .10s linear;
-moz-transition: background-color .10s linear;
-o-transition: background-color .10s linear;
-ms-transition: background-color .10s linear;
transition: background-color .10s linear;
}
/* qat */
#qatbox {
width: 382px;
background-image:url('favicon.png');
background-repeat: no-repeat;
background-position: 362px;
z-index: 1001;
position: absolute;
bottom: 0;
right: 0;
}
#qatbox p {
font-family: 'silkscreen', console, system;
font-smooth: never;
-webkit-font-smoothing : none;
text-align: justify;
vertical-align: middle;
font-size: 8px;
border: 1px solid #ccc;
padding: 2px;
background-color: #111;
position: relative;
margin-right: 32px;
max-height: 48px;
}
#qatbox p:after {
content: '';
position: absolute;
right: -8px;
bottom: 2px;
width: 0;
height: 0;
border-top: 10px solid transparent;
border-bottom: 10px solid transparent;
border-left: 8px solid #111;
}
#qatbox p:before {
content: '';
position: absolute;
right: -9px;
bottom: 2px;
width: 0;
height: 0;
border-top: 10px solid transparent;
border-bottom: 10px solid transparent;
border-left: 8px solid #ccc;
}
/* title */
#title {
position: absolute;
z-index: 1001;
left: 45px;
top: 0;
margin-top: -16px;
z-index: 100;
color: #AAA;
color: #1A6EB1;
font-size: 300%;
font-family: "Montserrat", sans-serif;
text-shadow: 0px 0px 2px #000;
}
#title span {
color: #D6A;
}
/* footer */
#footer {
color: #666;
font-size: small;
text-align: center;
padding-bottom: 1em;
}
/* lang */
#lang {
position: absolute;
right: 4px;
top: 8px;
z-index: 1000;
}
#lang input {
border: 0;
font-size: 0;
cursor: pointer;
}
/* content stuff */
p {
padding-left: 2em;
}
ul {
padding-left: 2em;
list-style-image: url('/bullet.png');
}
hr {
width: 95%;
border: 0;
border-top: 1px solid #ccc;
box-shadow: 0 0 3px #111;
}
table {
width: 75%;
background-color: rgba(200, 200, 200, 0.2);
box-shadow: 0 0 3px #111;
}
th {
font-family: "Montserrat", sans-serif;
text-shadow: 0px 0px 2px #000;
box-shadow: 0 0 3px #111;
padding: 0.25em;
}
td {
font-family: "Inconsolata", serif;
text-shadow: 0px 0px 2px #111;
background-color: rgba(200, 200, 200, 0.2);
box-shadow: 0 0 3px #111;
padding: 0.5em;
}
code {
font-family: "Inconsolata", serif;
font-smooth: never;
-webkit-font-smoothing : none;
font-smoothing : none;
vertical-align: middle;
font-size: 14px;
background-color: #101010;
color: #3A8EF1;
text-shadow: 0px 0px 2px #3a8eF1;
}
pre {
width: 90%;
margin-left: 2em;
padding: 1em;
white-space: pre-wrap;
white-space: -moz-pre-wrap !important;
white-space: -pre-wrap;
white-space: -o-pre-wrap;
word-wrap: break-word;
background-color: #101010;
-webkit-border-radius: 8px;
-moz-border-radius: 8px;
border-radius: 8px;
box-shadow: 0px 0px 3px #111;
position: relative;
}

1
wiki/test 100644
View File

@ -0,0 +1 @@
HAYY

View File

@ -0,0 +1,7 @@
# Petite Juliet Released!
After slogging through Ludum Dare 31, [Petite Juliet](/games/PetiteJuliet) has been created! Developed from scratch using C++, SDL2, OpenGL, and GLSL, it's kind of a cool little game.
[![Mon Petite!](/games/PetiteJuliet.png)](/games/PetiteJuliet.png)
27 out of 48 hours were blasted away in the creation of this game.
I plan to expand it in the future, implementing some of the features that were (sadly) missed due to rushing about. See the TODO here.

View File

@ -0,0 +1,3 @@
# ARK 1.0
[ARK/Alternative Registry Keeper](/software/ARK) has been released!
[![ARK scroonshet](/software/ARK.png)](/software/ARK.png)

View File

@ -0,0 +1,6 @@
# MAngband 1.1.2 SDL2 interface
I spent some time this last week hacking together an SDL2 interface for MAngband. I will be uploading the binaries for Windows 7, OS X, and Linux, along with the modified MAngband 1.1.2 source, once it is complete.
[![MAngband SDL2 screenshot](/games/MAngband.png)](/games/MAngband.png)
You can read some of my notes on hacking MAngband here - this should also provide enough information to make your own interface if you felt so inclined.

View File

@ -0,0 +1,6 @@
# QWiki 0.1
QWiki version 0.1 is now available, yo.
[![QWiki 0.1](/software/QWiki.png)](/software/QWiki.png)
You can do all sorts of snazzy snazz with it.

View File

@ -0,0 +1,5 @@
# XCode 4.2, GCC 4.8, and C++11
[![GCC 4.8.5](/articles/gcc4.8.5.png)](/articles/gcc4.8.5.png)
Short article on how to get C++11 support on XCode 4.2/Mac OS 10.6.8, aggregated from the disparate information on the net.
[Read it Here](/articles/xcode-42-and-c-11)

8
wiki/workout.qwk 100644
View File

@ -0,0 +1,8 @@
# Meta 3 -- Shoulders & Traps
| Exercise | Set 1 | Set 2 | Set 3 | Set 4 | Set 5 |
|---- | ---- | ---- | ---- | ---- | ---- |
|**Overhead Presses** | | | | | |
|**Upright Rows** | | | | | |
|**Lateral/Forward Raises**| | | | | |
|**Shrugs** | | | | | |