Pre-build item -> category mapping and simplify / optimize all the generation code...
authorJoe Wreschnig <joe.wreschnig@gmail.com>
Mon, 8 Jul 2013 00:19:31 +0000 (02:19 +0200)
committerJoe Wreschnig <joe.wreschnig@gmail.com>
Mon, 8 Jul 2013 00:19:31 +0000 (02:19 +0200)
acnl-outfit.js
acnl-wearables-list.js

index c09c3a251c5e411a4dc8b95ff03f9429b3abe1b6..50b98325c5481e81e52af03850c983ae30c83079 100644 (file)
@@ -6,12 +6,6 @@
 
 "use strict";
 
-Array.prototype.firstWhere = function (callback, thisArg) {
-    for (var i = 0; i < this.length; ++i)
-        if (callback.call(thisArg, this[i]))
-            return this[i];
-};
-
 Array.prototype.contains = function (o) {
     return this.indexOf(o) >= 0;
 };
@@ -47,56 +41,50 @@ function choice (os) {
     return os[Math.floor(os.length * Math.random())];
 }
 
-function category (item) {
-    return Object.keys(ACNL_WEARABLES).firstWhere(function (type) {
-        return ACNL_WEARABLES[type].contains(item);
-    });
-}
+var flatten1 = Array.prototype.concat.apply.bind(Array.prototype.concat, []);
 
-function notLewd (outfit) {
-    var categories = outfit.map(category);
-    return (categories.contains("wetsuits")
-            || categories.contains("dresses")
-            || categories.containsSubset(["tops", "bottoms"]));
+function get (attr) {
+    return this[attr];
 }
 
-function buildArray (a, l) {
-    return (a || []).concat(l);
+var category = get.bind(ACNL_WEARABLES_CATEGORY);
+var wearables = get.bind(ACNL_WEARABLES);
+
+function isLewd (outfit) {
+    return ![["wetsuits"], ["dresses"], ["tops", "bottoms"]].some(
+        Array.prototype.containsSubset, outfit.map(category));
 }
 
-function impossibilities (categories) {
-    return categories.map(function (c) { return BLOCKS[c]; }
-           ).reduce(buildArray, []);
+function impossibilities (outfit) {
+    return flatten1(outfit.map(category).map(get, BLOCKS));
 }
 
 function possibilities (outfit) {
-    return Object.keys(ACNL_WEARABLES
-           ).filter(Array.prototype.lacks, impossibilities(outfit.map(category))
-           ).map(function (k) { return ACNL_WEARABLES[k] }
-           ).reduce(buildArray, []);
+    return Object.keys(ACNL_WEARABLES).filter(
+        Array.prototype.lacks, impossibilities(outfit));
 }
 
-function isFinished(outfit) {
-    return notLewd(outfit) && Math.random() > 0.5;
+function outfit () {
+    var ps = [];
+    while (isLewd(ps))
+        ps.push(choice(flatten1(possibilities(ps).map(wearables))));
+    return ps;
 }
 
-function nextItem (outfit) {
-    return !isFinished(outfit) && choice(possibilities(outfit));
+function isPosessive (item) {
+    return item[0].toUpperCase() === item[0] && item.indexOf("'s") >= 0;
 }
 
-function outfit () {
-    var ps = [];
-    var next;
-    while (next = nextItem(ps))
-        ps.push(next);
-    return ps;
+function isPlural (item) {
+    return (item.substr(-1) === "s"
+            && item.substr(-2) !== "ss"
+            && item.substr(-6) !== "cosmos"); // :(
 }
 
 function article (item) {
     if (item[0].toUpperCase() === item[0] && item.indexOf("'s") >= 0)
         return "";
-    else if (item.substr(-1) === "s" && item.substr(-2) !== "ss"
-            && item.substr(-6) !== "cosmos") // :(
+    else if (isPlural(item))
         return "";
     else if ("aeiouAEIO".indexOf(item[0]) >= 0
              || ("FHLMNRSX".indexOf(item[0]) >= 0
index 303233c9637a87a51f9271a0b6e1a550bd93c281..8cb2d2e7af830130bae7d563457caf618bb3a2ea 100644 (file)
@@ -1216,3 +1216,10 @@ var ACNL_WEARABLES = {
         "white wet suit"
     ]
 };
+
+var ACNL_WEARABLES_CATEGORY = {};
+Object.keys(ACNL_WEARABLES).forEach(function (category) {
+    ACNL_WEARABLES[category].forEach(function (value) {
+        ACNL_WEARABLES_CATEGORY[value] = category;
+    });
+});