20,741
edits
m (→The script: add more sections to the article menu) |
|||
Line 444: | Line 444: | ||
// @name:it Instant-Cquotes | // @name:it Instant-Cquotes | ||
// @license public domain | // @license public domain | ||
// @version 0. | // @version 0.38 | ||
// @date 2016-05-05 | // @date 2016-05-05 | ||
// @description Automatically converts selected FlightGear mailing list and forum quotes into post-processed MediaWiki markup (i.e. cquotes). | // @description Automatically converts selected FlightGear mailing list and forum quotes into post-processed MediaWiki markup (i.e. cquotes). | ||
Line 460: | Line 460: | ||
// @require https://code.jquery.com/ui/1.11.4/jquery-ui.js | // @require https://code.jquery.com/ui/1.11.4/jquery-ui.js | ||
// @require http://subprotocol.com/js/genetic-0.1.12.min.js | // @require http://subprotocol.com/js/genetic-0.1.12.min.js | ||
// @require http://synaptic.juancazala.com/scripts/homepage/synaptic.js | |||
// @resource jQUI_CSS https://code.jquery.com/ui/1.11.4/themes/smoothness/jquery-ui.css | // @resource jQUI_CSS https://code.jquery.com/ui/1.11.4/themes/smoothness/jquery-ui.css | ||
// @resource myLogo http://wiki.flightgear.org/images/2/25/Quotes-logo-200x200.png | // @resource myLogo http://wiki.flightgear.org/images/2/25/Quotes-logo-200x200.png | ||
Line 479: | Line 480: | ||
// any conditions, unless such conditions are required by law. | // any conditions, unless such conditions are required by law. | ||
// | // | ||
// This script has a number of dependencies that are implicitly satisfied when run as a user script | |||
// via GreaseMonkey/TamperMonkey; however, these need to be explicitly handled when using a different mode (e.g. firefox/android): | |||
// | |||
// - jQuery - user interface (REQUIRED) | |||
// - genetic-js - genetic programming (OPTIONAL/EXPERIMENTAL) | |||
// - synaptic - neural networks (OPTIONAL/EXPERIMENTAL) | |||
// | |||
// | |||
/* Here are some TODOs | /* Here are some TODOs | ||
Line 517: | Line 526: | ||
confirm: function(msg) {return window.confirm(msg); }, | confirm: function(msg) {return window.confirm(msg); }, | ||
dialog: null, | dialog: null, | ||
selection: null | selection: null, | ||
populateWatchlist: function() { | |||
}, | |||
populateEditSections: function() { | |||
} | |||
}, // default UI mapping (Browser/User script) | }, // default UI mapping (Browser/User script) | ||
Line 558: | Line 574: | ||
validate: function(host) { | validate: function(host) { | ||
if(Environment.scriptEngine !== "Greasemonkey" && host.get_persistent('startup.disable_validation',false)!==true) | if(Environment.scriptEngine !== "Greasemonkey" && host.get_persistent('startup.disable_validation',false)!==true) | ||
console.log("NOTE: This script has not been tested with script engines other than GreaseMonkey recently!"); | |||
var dependencies = [ | |||
{name:'jQuery', test: function() {} }, | |||
{name:'genetic.js', test: function() {} } | |||
]; | |||
}, | }, | ||
Line 826: | Line 847: | ||
}, // downloadPosting() | }, // downloadPosting() | ||
// TODO: add makeAJAXCall, and makeWikiCall here | |||
Line 926: | Line 949: | ||
enabled: false, | enabled: false, | ||
event: 'document.onmouseup', // when to invoke the event handler | event: 'document.onmouseup', // when to invoke the event handler | ||
// TODO: move downloadWatchlist() etc here | |||
event_handler: function () { | event_handler: function () { | ||
console.log('FlightGear wiki handler active (waiting to be populated)'); | console.log('FlightGear wiki handler active (waiting to be populated)'); | ||
Line 1,137: | Line 1,161: | ||
}, // msgbox | }, // msgbox | ||
// this is currently work-in-progress, and will need to be refactored sooner or later | |||
// for now, functionality matters more than elegant design/code :) | |||
jQueryTabbed: function(msg, original) { | jQueryTabbed: function(msg, original) { | ||
// FIXME: using backtics here makes the whole thing require ES6 .... | // FIXME: using backtics here makes the whole thing require ES6 .... | ||
Line 1,152: | Line 1,178: | ||
<div id="content"/> | <div id="content"/> | ||
<div id="options"> | <div id="options"> | ||
<b>Note this is work-in-progress, i.e. not yet fully functional</b><br/> | |||
<label for="article_select">Select an article to update</label> | <label for="article_select">Select an article to update</label> | ||
<select name="article_select" id="article_select"> | <select name="article_select" id="article_select"> | ||
<optgroup id="news" label=" | <optgroup id="news" label="News"/> | ||
<optgroup id="watchlist" label=" | <optgroup id="support" label="Support"/> | ||
<optgroup id="release" label="Release"/> | |||
<optgroup id="develop" label="Development"/> | |||
<optgroup id="watchlist" label="Watchlist"/> | |||
</select> | </select> | ||
<p/> | <p/> | ||
Line 1,163: | Line 1,193: | ||
</div> | </div> | ||
</div> | </div> | ||
<div id="articles">This tab contains articles that you can directly access/edit using the mediawiki API< | <div id="articles">This tab contains articles that you can directly access/edit using the mediawiki API<br/> | ||
Note: The watchlist is retrieved dynamically, so does not need to be edited here<br/> | |||
<label for="article_select">Select an article</label> | <label for="article_select">Select an article</label> | ||
<select name="article_select" id="article_select"> | <select name="article_select" id="article_select"> | ||
<optgroup id="news" label=" | <optgroup id="news" label="News"/> | ||
<optgroup id="watchlist" label=" | <optgroup id="support" label="Support"/> | ||
<optgroup id="develop" label="Development"/> | |||
<optgroup id="release" label="Release"/> | |||
<!-- the watchlist is retrieved dynamically, so omit it here | |||
<optgroup id="watchlist" label="Watchlist"/> | |||
--> | |||
</select> | </select> | ||
Line 1,176: | Line 1,211: | ||
<div id="edit_article"> | <div id="edit_article"> | ||
<label for="article_name">Article</label> | <label for="article_name">Article</label> | ||
<input type="text" id="article_name" name="article_name">< | <input type="text" id="article_name" name="article_name"><br/> | ||
<label for="article_url">Link</label> | <label for="article_url">Link</label> | ||
<input type="text" id="article_url" name="article_url">< | <input type="text" id="article_url" name="article_url"><br/> | ||
<button id="article_save">Save</button> | <button id="article_save">Save</button> | ||
Line 1,200: | Line 1,235: | ||
</div> | </div> | ||
</div> | </div> | ||
<div id="development">This tab is a placeholder for features currently under development | <div id="development">This tab is a placeholder for features currently under development<p/> | ||
<button id="evolve_regex">Evolve regex</button><p/> | |||
<button id="test_perceptron">Test Perceptron</button><p/> | |||
<div id="output"><p/> | |||
<textarea id="devel_output" lines="10"></textarea><p/> | |||
</div> | |||
</div> | </div> | ||
<div id="settings">This tab | <div id="settings">This tab will contain script specific settings | ||
</div> | </div> | ||
<div id="help">One day, this tab may contain help....<p/><button id="helpButton">Instant Cquotes</button> | <div id="help">One day, this tab may contain help....<p/><button id="helpButton">Instant Cquotes</button> | ||
Line 1,211: | Line 1,251: | ||
</div>`); // tabs div | </div>`); // tabs div | ||
var evolve_regex = $('div#development button#evolve_regex', markup); | |||
evolve_regex.click(function() { | |||
alert("Evolve regex"); | |||
}); | |||
var test_perceptron = $('div#development button#test_perceptron', markup); | |||
test_perceptron.click(function() { | |||
alert("Test perceptron"); | |||
}); | |||
// add dynamic elements to each tab | // add dynamic elements to each tab | ||
Line 1,238: | Line 1,288: | ||
// TODO: Currently, this is hard-coded, but should be made customizable via the "articles" tab at some point ... | // TODO: Currently, this is hard-coded, but should be made customizable via the "articles" tab at some point ... | ||
var articles = [ | var articles = [ | ||
{name:'Frequently asked questions', url:' | // NOTE: category must match an existing <optgroup> | ||
{name:'Next newsletter', url:' | {category:'support', name:'Frequently asked questions', url:''}, | ||
{name:'Next changelog', url:' | {category:'support', name:'Asking for help', url:''}, | ||
{name:'Release plan/Lessons learned', url:' | {category:'news', name:'Next newsletter', url:''}, | ||
{category:'news', name:'Next changelog', url:''}, | |||
{category:'release', name:'Release plan/Lessons learned', url:''}, // TODO: use wikimedia template | |||
{category:'develop', name:'Nasal library', url:''} | |||
]; | ]; | ||
Line 1,247: | Line 1,301: | ||
function updateArticleList(selector) { | function updateArticleList(selector) { | ||
$.each(articles, function (i, article) { | $.each(articles, function (i, article) { | ||
$(selector, markup).append($('<option>', { | $(selector+ ' optgroup#'+article.category, markup).append($('<option>', { | ||
value: article.name, // FIXME: just a placeholder for now | value: article.name, // FIXME: just a placeholder for now | ||
text : article.name | text : article.name | ||
Line 1,255: | Line 1,309: | ||
// add the article list to the corresponding dropdown menus | // add the article list to the corresponding dropdown menus | ||
updateArticleList('select#article_select | updateArticleList('select#article_select'); | ||
// populate watchlist (prototype for now) | // populate watchlist (prototype for now) | ||
// TODO: generalize & refactor: url, format | |||
// https://www.mediawiki.org/wiki/API:Watchlist | // https://www.mediawiki.org/wiki/API:Watchlist | ||
Line 1,281: | Line 1,334: | ||
UI.alert(e.message); | UI.alert(e.message); | ||
} | } | ||
}); | }); // download & populate watchlist | ||
// register an event handler for the main tab, so that article specific sections can be retrieved | // register an event handler for the main tab, so that article specific sections can be retrieved | ||
Line 1,326: | Line 1,376: | ||
}); // Host.download() call, i.e. we have a login token | |||
}); // Host.download() call | |||
}); // on select change | }); // on select change | ||
Line 2,084: | Line 2,132: | ||
} | } | ||
// IGNORE | // IGNORE EVERYTHING THAT FOLLOWS: | ||
// This is an experiment to use GA/GP (genetic programming) to help procedurally evolve xpath and regex expressions if/when the underlying websites change | // This is an experiment to use GA/GP (genetic programming) to help procedurally evolve xpath and regex expressions if/when the underlying websites change | ||
// so that we don't have to manually update/edit the script accordingly (this would also work for mobile themes etc) | // so that we don't have to manually update/edit the script accordingly (this would also work for mobile themes etc) | ||
Line 2,177: | Line 2,225: | ||
var validExp = 0.1; | var validExp = 0.1; | ||
var hasToken = 0.1; | var hasToken = 0.1; | ||
var i; | var i; | ||
for (i=0;i<entity.length;++i) { | for (i=0;i<entity.length;++i) { | ||
Line 2,258: | Line 2,288: | ||
*/ | */ | ||
var regexTests = [ | |||
{haystack: "From: John Doe <John@do...> - 2020-07-02 17:36:03", needle: "John Doe"}, | |||
{haystack: "From: Marc Twain <Marc@ta...> - 2010-01-03 07:36:03", needle: "Marc Twain"}, | |||
{haystack: "From: George W. Bush <GWB@wh...> - 2055-11-11 17:33:13", needle: "George W. Bush"} | |||
]; | |||
// the regex we want to evolve | // the regex we want to evolve | ||
var solution = "/From: (.*) <.*@.*>/"; | var solution = "/From: (.*) <.*@.*>/"; | ||
// let's assume, we'd like to evolve a regex expression like this one | // let's assume, we'd like to evolve a regex expression like this one | ||
var userData = { | var userData = { | ||
solution: solution, | solution: solution, | ||
tests: regexTests | |||
}; | }; | ||
Line 2,283: | Line 2,315: | ||
catch (e) { | catch (e) { | ||
console.log("genetic.js error:\n" +e.message); | console.log("genetic.js error:\n" +e.message); | ||
} // catch</syntaxhighlight> | } // catch | ||
if(0) | |||
try { | |||
// https://github.com/cazala/synaptic | |||
var Neuron = synaptic.Neuron, | |||
Layer = synaptic.Layer, | |||
Network = synaptic.Network, | |||
Trainer = synaptic.Trainer, | |||
Architect = synaptic.Architect; | |||
function Perceptron(input, hidden, output) | |||
{ | |||
// create the layers | |||
var inputLayer = new Layer(input); | |||
var hiddenLayer = new Layer(hidden); | |||
var outputLayer = new Layer(output); | |||
// connect the layers | |||
inputLayer.project(hiddenLayer); | |||
hiddenLayer.project(outputLayer); | |||
// set the layers | |||
this.set({ | |||
input: inputLayer, | |||
hidden: [hiddenLayer], | |||
output: outputLayer | |||
}); | |||
} | |||
// extend the prototype chain | |||
Perceptron.prototype = new Network(); | |||
Perceptron.prototype.constructor = Perceptron; | |||
var myPerceptron = new Perceptron(2,3,1); | |||
var myTrainer = new Trainer(myPerceptron); | |||
myTrainer.XOR(); // { error: 0.004998819355993572, iterations: 21871, time: 356 } | |||
myPerceptron.activate([0,0]); // 0.0268581547421616 | |||
myPerceptron.activate([1,0]); // 0.9829673642853368 | |||
myPerceptron.activate([0,1]); // 0.9831714267395621 | |||
myPerceptron.activate([1,1]); // 0.02128894618097928 | |||
console.log("Syntaptic loaded"); | |||
} catch(e) { | |||
UI.alert(e.message); | |||
}</syntaxhighlight> | |||
{{Appendix}} | {{Appendix}} |