I am Bored Posted February 8, 2015 Report Share Posted February 8, 2015 (edited) First off, I do intend to clean up this post a bit later and make the tool a bit more usable, but that will have to wait until I'm not asleep. First up, the sane code. Looks like pretty normal PHP to me. <? (locations 1_-1x3_1) // This is the key we give the user. $MDS_Key = "iab-quiz-key"; // This is the key used for the storage. $Storage_Key = "iabTestKey"; // All answers should be stored lowercase. $Questions = array( 1 => array( "What is this?", "clicky" ), 2 => array( "Who made this?", "orvid" ) ); // List of users who have completed the quiz. $usersFinished = mds_storage($Storage_Key, "toau", array()); if (uv("name") == "Orvid") { if (count($usersFinished) > 0) { echo "<p>The following users have completed the challenge:<br/>"; for ($i = 0; $i < count($usersFinished); $i++) { echo $usersFinished[$i] . "<br/>"; } echo "</p><br/><br/>"; } // Uncomment the next line to reset the storage to remove all users. //$usersFinished = array(); } if (mds_has_rpcq_keys($MDS_Key)) { // Uncomment the ne_xt line to reset your key sta_te for testing. //mds_take_rpcq_keys($MDS_Key); echo "You have already completed the quiz!"; } else { echo "<form method='post' action=''>"; $currentQuestion = 0; if (isset($input['page']) AND $input['page'] == "front") { $currentQuestion = 1; } else if (isset($input['q'])) { $currentQuestion = $input['q']; if (!isset($Questions[$currentQuestion])) $currentQuestion = 0; } if (isset($input['answer'])) { if ($Questions[$currentQuestion][1] == strtolower($input['answer'])) { // Check if this was the last question if (!isset($Questions[$currentQuestion + 1])) { // This was the last question, so add the users' name to our // list, and give them a key to prevent them from re-taking // the quiz. echo "<p>Congratulations! You've completed the quiz!</p>"; $currentQuestion = -1; $usersFinished[] = uv("name"); mds_give_rpcq_keys($MDS_Key); } else { // Not the last question, continue. echo "<p>You answered correctly!</p><br/><br/>"; $currentQuestion++; } } else { echo "<p>Incorrect! Try again!</p><br/><br/>"; } } if ($currentQuestion > 0 && isset($Questions[$currentQuestion])) { echo $Questions[$currentQuestion][0]; ?> <br /> <input type='text' id='answer' name='answer' value='' /><br /> <input type='hidden' name='q' value='<?=$currentQuestion?>' /> <input name='button' type='submit' value='Submit Answer' /> <script type="application/javascript"> $('#answer').focus(); </script> <? } else if ($currentQuestion != -1) { ?> Welcome!<br/> <input type="hidden" name="page" value="front" /> <input name="button" type="submit" value="Continue" /> <? } echo "</form>"; } ?> Now, the code to transform this into a form that MDScript will accept. This code could be trivially accomplished in most other languages with a regex engine, but I chose to write it in D. It is currently hard coded to a specific file, and is only really intended as a reference for those looking to write their own form of the tool. module main; import std.algorithm : any, filter, map; import std.array : array, join, split; import std.conv : to; import std.datetime : nsecs, StopWatch; import std.file : readText, write; import std.regex : ctRegex, regex, replaceAll; import std.stdio : writeln, writefln; import std.string : strip, toLower; enum InputFile = `F:\MD\ClickableQuiz.omds`; void main(string[] args) { processFile(InputFile); } template cRegex(string pattern, string flags) { debug enum cRegex = regex(pattern, flags); else alias cRegex = ctRegex!(pattern, flags); } __gshared contentEqualRegex = cRegex!(`\?>([^]*?)<\?=([^]*?)(?=\?>)`, "g"); __gshared contentRegex = cRegex!(`\?>([^]*?)<\?(?!=)`, "g"); __gshared storageRegex = cRegex!(`\$([a-zA-Z0-9_]+)\s*=\s*mds_storage\(([^]*?),\s*("[at]o[at]u")\s*,([^]*?)\)\s*;`, "g"); __gshared variableRegex = cRegex!(`\$([a-zA-Z0-9_]+)`, "g"); __gshared stringRegex = cRegex!(`"(?:\"|.)*?"`, "g"); __gshared commentRegex = cRegex!(`//.*?$`, "gm"); __gshared documentStartRegex = cRegex!(`^\s*<\?`, "g"); __gshared documentEndRegex = cRegex!(`\?>\s*$`, "g"); string generateRegexTree(string[] str) { static class Node { char leaf; Node[] children; this() { this.leaf = '\0'; } this(char c) { this.leaf = c; } static Node buildNode(string child, Node parent) { if (child == "") { auto n = new Node('\0'); parent.children ~= n; return n; } foreach (c; parent.children) { if (c.leaf == child[0]) return buildNode(child[1..$], c); } auto n = new Node(child[0]); parent.children ~= n; return buildNode(child[1..$], n); } string build() { string ret = ""; if (leaf != '\0') ret ~= leaf; bool hasEndNode = children.any!(c => c.leaf == '\0'); if (children.length == 1 && hasEndNode) hasEndNode = false; bool addGrouping = children.length > 1 || hasEndNode; if (addGrouping) ret ~= "(?:"; ret ~= children.filter!(c => c.leaf != '\0').map!(c => c.build()).join('|'); if (addGrouping) ret ~= ')'; if (hasEndNode) ret ~= "?"; return ret; } } Node root = new Node(); foreach (c; str) root.buildNode(c, root); return root.build(); } enum knownReservedWords = import("KnownReservedWords.txt").split('\n').map!(i => i.strip()).array; __gshared knownReservedWordsRegex = cRegex!(generateRegexTree(knownReservedWords), "gi"); void processFile(string inputFile) { auto sw = StopWatch(); auto txt = readText(inputFile); sw.start(); // First, extract the content sections. string[] contentSections; txt = txt.replaceAll!((match) { contentSections ~= match[1]; auto tmp = `echo @content[` ~ (contentSections.length - 1).to!string() ~ "];\r\n"; return tmp ~ `echo "" . (` ~ match[2] ~ ");\r\n"; })(contentEqualRegex); txt = txt.replaceAll!((match) { contentSections ~= match[1]; return `echo @content[` ~ (contentSections.length - 1).to!string() ~ "];\r\n"; })(contentRegex); // And remove the opening and closing tags of the document (if present). txt = txt.replaceAll(documentStartRegex, ""); txt = txt.replaceAll(documentEndRegex, ""); // Next, remap the variables, with special handling for storage. string[string] variableMap = [ "input": "@input", ]; txt = txt.replaceAll!((match) { if (match[1] in variableMap) throw new Exception("Already mapped variable '" ~ match[1] ~ "'!"); auto vIdx = `@va[` ~ variableMap.length.to!string() ~ `]`; auto tmp = vIdx ~ ` = mds_storage(` ~ match[2] ~ `, ` ~ match[3] ~ ");\r\n"; tmp ~= `if (!isset(@storage[` ~ vIdx ~ "]))\r\n"; tmp ~= "\t@storage[" ~ vIdx ~ `] = ` ~ match[4] ~ ";\r\n"; variableMap[match[1]] = `@storage[` ~ vIdx ~ `]`; return tmp; })(storageRegex); txt = txt.replaceAll!((match) { if (match[1] in variableMap) return variableMap[match[1]]; return (variableMap[match[1]] = `@va[` ~ variableMap.length.to!string() ~ `]`); })(variableRegex); // Now to deal with reserved words. txt = txt.replaceAll!((match) { return match[0].replaceAll!((match) { auto half = match[0].length / 2; return match[0][0..half] ~ `" . "` ~ match[0][half..$]; })(knownReservedWordsRegex); })(stringRegex); txt = txt.replaceAll!((match) { return match[0].replaceAll!((match) { auto half = match[0].length / 2; return match[0][0..half] ~ `_` ~ match[0][half..$]; })(knownReservedWordsRegex); })(commentRegex); sw.stop(); writefln("Took %s ms to format '%s'", cast(real)sw.peek().nsecs / 1_000_000f, inputFile); write(inputFile ~ ".html", contentSections.join("<!-- content separator -->")); write(inputFile ~ ".php", txt); } And, lastly, the content of KnownReservedWords.txt: call error ext fprintf inf ini is_a mod move open parse read split sprintf stat t_as t_sr try use val Have fun, and may all your vars be @va. Edited February 8, 2015 by I am Bored DARK DEMON 1 Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.