Случайный генератор одежды

В течение последних четырех лет я посещал частную школу, в которой его ученики нуждались в связях. Я обнаружил, что гораздо легче понять, какая комбинация рубашки, брюк и галстука, которые собираются вместе накануне, поскольку иногда это может быть утомительным процессом. Чтобы упростить этот процесс, у меня возникла идея создать скрипт для автоматического создания новых комбинаций подходящей одежды.

На данный момент я ввожу всю свою одежду в файл JSON, разделенный на массивы, представляющие категории (рубашки, штаны, галстуки). Первым элементом каждого массива является другой массив, заполненный всеми доступными цветами /шаблонами в этой категории (красный, синий и т. Д.). Для каждого цвета есть массив ID'd по его цвету, состоящий из объекта, описывающего, какие цветные /узорные штаны /галстуки /свитера идут с этим цветом рубашки. Наконец, есть массив с именами каждого типа предмета одежды, который подпадает под этот цвет. В случае, если вы не выполнили никаких действий, вот раздел моего JSON файла ( полный здесь ):

"shirts": [{
    "colors": [
        "red"
    ],
    "red": [{
            "pants": [
                "navy",
                "khaki"
            ],
            "sweaters": [
                "navy",
                "grey"
            ],
            "ties": [
                "all"
            ]
        },
        [
            "Red Flannel",
            "That Other Red Flannel"
        ]
    ]
}],
...

Это довольно утомительная структура (IMO), но я не могу думать о лучшей реализации, так как существует множество критериев, которые должны соответствовать соответствующей одежде. Мой метод создания случайной комбинации также утомительно:

$.getJSON("clothes.json", function (clothes) {
    window.clothes = clothes;
    var colors = clothes["shirts"][0]["colors"];
    $(colors).each(function (i) {
        $("#color").append("<option>" + colors[i] + "</option>");
    });
});

function randomArrayValue(array) {
    var array = eval(array);
    return array[Math.floor(Math.random() * array.length)];
}

function randomClothes(times, color, sweater, tie) {
    $("#output").html("");
    // Objects for everything
    var shirts = clothes["shirts"][0];
    pants = clothes["pants"][0];
    sweaters = clothes["sweaters"][0];
    ties = clothes["ties"][0];
    shoes = clothes["shoes"][0];
    for (var x = 0; x < times; x++) {
        if (color) {
            startShirt = shirts[color];
        } else {
            startShirt = shirts[randomArrayValue(shirts["colors"])]
        }
        shirt_optionsPants = startShirt[0]["pants"];
        shirt_optionsSweaters = startShirt[0]["sweaters"];
        shirt_optionsTies = startShirt[0]["ties"];
        // Array to hold random combinations
        combination = new Array();
        for (var i = 0; i < shirt_optionsPants.length; i++) {
            var currentPantColor = shirt_optionsPants[i];
            var pant_optionsSweaters = pants[currentPantColor][0]["sweaters"];
            if (tie) {
                var pant_optionsTies = pants[currentPantColor][0]["ties"];
            } else {
                var pant_optionsTies = new Array("all");
            }
            // Availible ties between pants and shirt, tie color has to be both present in shirt and pant or it wont be added
            var availableShirtPantTies = new Array();
            $(shirt_optionsTies).each(function (i) {
                var currentShirtTie = shirt_optionsTies[i];
                if (pant_optionsTies[0] === "all") {
                    availableShirtPantTies.push(currentShirtTie);
                } else {
                    $(pant_optionsTies).each(function (i) {
                        if (pant_optionsTies[i] === currentShirtTie) {
                            availableShirtPantTies.push(currentShirtTie);
                        } else if (currentShirtTie === "all") {
                            availableShirtPantTies.push(pant_optionsTies[i]);
                        }
                    });
                }
            });
            for (var k = 0; k < pant_optionsSweaters.length; k++) {
                var currentSweaterColor = pant_optionsSweaters[k];
                var sweater_optionsTies = sweaters[currentSweaterColor][0]["ties"];
                // Check if there are any ties that matches both the pants and shirt
                if (availableShirtPantTies.length > 0) {
                    if (sweater) {
                        var availableShirtPantSweaterTies = new Array();
                        $(sweater_optionsTies).each(function (i) {
                            var currentSweaterTie = sweater_optionsTies[i];
                            if ($.inArray(currentSweaterTie, availableShirtPantTies) >= 0) {
                                availableShirtPantSweaterTies.push(currentSweaterTie)
                            } else if (currentSweaterTie === "all") {
                                $(availableShirtPantTies).each(function (i) {
                                    availableShirtPantSweaterTies.push(availableShirtPantTies[i]);
                                });
                            } else {
                                if (sweater_optionsTies[i] === sweater_optionsTies[i]) {
                                    availableShirtPantSweaterTies.push(sweater_optionsTies[i]);
                                }
                            }
                        });
                    } else {
                        availableShirtPantSweaterTies = availableShirtPantTies;
                    }
                    $(availableShirtPantSweaterTies).each(function (i) {
                        // Assign any tie to a color
                        if (tie) {
                            if (availableShirtPantSweaterTies[i] === "all") {
                                currentTieColor = randomArrayValue(ties["colors"]);
                            } else {
                                currentTieColor = availableShirtPantSweaterTies[i];
                            }
                        } else {
                            currentTieColor = ties["colors"][0];
                        }
                        //Result object
                        var result = new Object();
                        result.shoes = randomArrayValue(pants[currentPantColor][0]["shoes"]);
                        result.pants = currentPantColor;
                        result.sweater = currentSweaterColor;
                        result.tie = currentTieColor;
                        combination.push(result);
                    });
                }
            }
        }
        var randomCombination = randomArrayValue(combination);
        pantsColor = randomCombination["pants"];
        sweaterColor = randomCombination["sweater"];
        tieColor = randomCombination["tie"];
        shoesColor = randomCombination["shoes"];
        var randomShirt = randomArrayValue(startShirt[1]);
        randomPants = randomArrayValue(pants[pantsColor][1]);
        randomSweater = randomArrayValue(sweaters[sweaterColor][1]);
        randomTie = randomArrayValue(ties[tieColor][0]);
        randomShoes = randomArrayValue(shoes[shoesColor][0]);
        //Debugging
        //console.log(randomShirt, randomPants, randomSweater, randomTie, randomShoes);
        if (sweater) {
            var sweaterContent = "Sweater: " + randomSweater + "<br />";
        } else {
            var sweaterContent = "";
        }
        if (tie) {
            var tieContent = "Tie: " + randomTie + "<br />";
        } else {
            var tieContent = "";
        }
        var content = "Shirt: " + randomShirt + "<br />Pants: " + randomPants + "<br />" + sweaterContent + tieContent + "Shoes: " + randomShoes + "<br /><br />";
        $("#output").append(content);
    }
}
$("#random").click(function () {
    randomClothes(1, "", true, true);
});

Это не то, что я действительно кодировал раньше, и я не лучший, когда дело доходит до визуализации случайности. Мой оригинальный метод кодирования этого не учитывал, что некоторые рубашки могут идти с определенными связями, но эти рубашки могут идти с свитерами, которых нет у галстуков или брюк. Следовательно, код довольно большой. Однако я должен верить, что есть намного лучшее решение того, чего я пытаюсь достичь. Также , я хотел бы добавить в реализации для обычных футболок или что-нибудь в этом роде, но, как сейчас, структура слишком строгая, чтобы допускать значительную модификацию.

О да, если бы это было не ясно, код оторвался от рубашки. Поэтому он выбирает случайную рубашку, а затем видит, что соответствует ей. Если бы код был не таким строгим, было бы неплохо начать с любого предмета одежды, такого как штаны.

34 голоса | спросил Charlie 8 FebruaryEurope/MoscowbSat, 08 Feb 2014 21:17:17 +0400000000pmSat, 08 Feb 2014 21:17:17 +040014 2014, 21:17:17

2 ответа


22

Хорошая идея. Мне очень нравится то, что вы сделали, но некоторые из ваших реализаций могут быть определенно улучшены. Начнем с JSON.

  • Некоторые из этих массивов не нужны. Вы обертываете каждый элемент clothes в [], нет необходимости в этом, так как в массиве есть только один элемент! Фактически вы должны использовать только массивы, чтобы группировать элементы like. Я также избавлюсь от вашего цветового массива, поскольку он кажется лишним (подробнее об этом позже). Рассмотрите эту редизайн;

    "shirts": {
        "red": {
           "items": [ 
             "Red Flannel",
             "That Other Red Flannel"
           ],
           "matches": {
             "pants": [
               "navy",
               "khaki"
             ],
             "sweaters": [
               "navy",
               "grey"
             ],
             "ties": [
               "all"
             ]
           }
        }
    }
    

    Вы видите, как это мгновенно облегчает нам просмотр предметов и повторение матчей?

    Теперь вы можете удалить все аксессоры [0]:

    Теперь вы можете выбирать цвета с помощью: shirts[color] и перебирать совпадения с;

     for (var match in shirts[color].matches) { 
    
     }
    

    Это подводит меня к следующему пункту.

  • Кажется, вы много используете для записи элементов в объекте. Когда аксессор не является переменной, вы можете использовать точечную нотацию.

    shirts[color]['matches'] === shirts[color].matches
    

    Различие помогает нам отличить, как мы обращаемся к собственности с первого взгляда.

  • Функция randomArrayValue использует ненужный eval. Eval не требуется большую часть времени, и его часто неправильно используют новые JavaScript-разработчики. Вы могли бы просто сделать:

    function randomArrayValue(arr) {
      return arr[Math.floor(Math.random() * arr.length)];
    }
    

    В стороне вы также можете использовать ~~ вместо Math.floor, и это немного быстрее.

  • Вам не хватает лота операторов var. Обычно это плохо, поскольку объявленные переменные без var устанавливаются как глобальные, доступные из любого места. Нет ничего такого же раздражающего, как ошибки глобальной переменной. Вы можете получить такие проблемы, как это, включив строку 'use strict'; в верхней части программы. Это говорит браузеру быть более строгим с компиляцией.

  • Рассмотрим литералы вместо новых объектов. Например:

    combination = new Array(); // okay
    combination = [];          // better
    
    result = new Object(); // not great
    result = {};           // awesome
    
  • Для вашего объекта результата вам будет намного лучше создавать литерал Object;

    var result = {
      shoes: randomArrayValue(pants[currentPantColor].shoes),
      pants: currentPantColor,
      sweater: currentSweaterColor,
      tie: currentTieColor
    };
    combination.push(result);
    
  • Возврат к этому цветному объекту ... Вы можете получить ключи объекта, используя Object.keys(obj). Поэтому, если вы хотите знать все цвета, в которые входят ваши рубашки, вы можете вызвать Object.keys(clothes.shirts). Если вы хотите перебрать все цвета, вы можете for...in:

    for (var colour in clothes.shirts) {
      var items = clothes.shirts[colour].items,
        matches = clothes.shirts[colour].matches;
    }
    

Достаточно для начала, дайте мне знать, хотите ли вы, чтобы я указал, как вы можете использовать некоторые из этих проектов в своем решении.

ответил Jivings 9 FebruaryEurope/MoscowbSun, 09 Feb 2014 17:56:07 +0400000000pmSun, 09 Feb 2014 17:56:07 +040014 2014, 17:56:07
6

Чтобы выполнить то, что вы просите, вам нужно переключить свой подход на функциональный подход и значительно переписать свой код. То, что вы ищете, лучше всего решает концепция складчатости.

Проверьте это!

Вы вызываете функцию, которая находит соответствие для выбранной вами рубашки. Вы говорите: «Эй, вот рубашка, найдите мне подходящие штаны!» Затем он возвращает не только несколько подходящих штанов, но и предмет, содержащий как рубашку, так и штаны, которые он только что нашел для вас, и вот почему ... Затем вы поворачиваетесь и передаете этот объект в одну и ту же функцию, говоря: «yo, вот что я пока вы выбрали подходящий свитер! Ваша функция добавляет случайное совпадение к тому, что у вас есть, и до сих пор возвращает всю вашу экипировку, которая затем передается следующей функции.

Проверьте метод уменьшения массива. https://developer.mozilla.org/en-US/docs/Web /JavaScript /Справка /Global_Objects /Array /Уменьшить

Если вы используете это, вы можете создать массив, содержащий список элементов, которые хотите получить, а затем вызвать сокращение на нем, например. ["shirt", "tie", "sweater"].reduce(findMatches);, где findMatches - ваша функция обратного вызова.

У этого также есть дополнительный бонус, позволяющий сохранить всю вашу логику в одном месте. И, пока ваши данные будут правильно обновлены, добавление новых предметов одежды так же просто, как добавление строки в массив!

ответил moarboilerplate 24 WedEurope/Moscow2014-12-24T23:26:22+03:00Europe/Moscow12bEurope/MoscowWed, 24 Dec 2014 23:26:22 +0300 2014, 23:26:22

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132