Вот пример объектов, с которыми я работал:
{ "index": 2, "name": "Acolyte", "size": "Medium", "type": "humanoid", "subtype": "any race", "alignment": "any alignment", "armor_class": 10, "hit_points": 9, "hit_dice": "2d8", "speed": "30 ft.", "strength": 10, "dexterity": 10, "constitution": 10, "intelligence": 10, "wisdom": 14, "charisma": 11, "medicine": 4, "religion": 2, "damage_vulnerabilities": "", "damage_resistances": "", "damage_immunities": "", "condition_immunities": "", "senses": "Passive Perception 12", "languages": "any one language (usually Common)", "challenge_rating": 0.25, "special_abilities": [{ "name": "Spellcasting", "desc": "The acolyte is a 1st-level spellcaster. Its spellcasting ability is Wisdom (spell save DC 12, +4 to hit with spell attacks). The acolyte has following cleric spells prepared:\n\n• Cantrips (at will): light, sacred flame, thaumaturgy\n• 1st level (3 slots): bless, cure wounds, sanctuary", "attack_bonus": 0 }], "actions": [{ "name": "Club" "desc": "Melee Weapon Attack: +2 to hit, reach 5 ft., one target. Hit: 2 (1d4) bludgeoning damage.", "attack_bonus": 2, "damage_dice": "1d4" }], "url": "http://www.dnd5eapi.co/api/monsters/2" }
За свою ограниченную карьеру программиста у меня был некоторый опыт интерпретации и отображения данных JSON в javascript. Последние две недели я работал над проектом, созданным с помощью React, и обнаружил, что правила немного отличаются от тех, к которым я привык. React использует JSX, который выглядит и пахнет javascript, но это не то же самое.
Проект: Handy D&D (он же Handy Dandy). Цель состоит в том, чтобы предоставить мастерам подземелий простое вспомогательное приложение для проведения кампаний. Нам посчастливилось найти D&D 5e API, который был заполнен данными D&D (также известными как D&D). Я имею в виду, действительно круто: в 5-м издании D&D 325 монстров, в результате получается более 16 тысяч строк кода! Первой задачей, которую я предпринял, было разобрать JSON монстров, чтобы наши DM могли найти необходимую информацию о монстрах.
Один из первых уроков, который я усвоил, заключался в том, что если у одного из объектов-монстров (монстров?) Не было ключа, как у других монстров, попытка отобразить его привела бы к классической «Ошибка компиляции». Чтобы исправить это, я решил использовать операторы «если» для условного рендеринга контента. Однако вы не можете просто вставить вложенные операторы «если» в файл JSX, поэтому моя техника заключалась в том, чтобы вложить операторы «если» в функции, а затем вызвать эти функции для рендеринга контента.
Например:
function sense() { if (monstersJSON.senses) { return ( <div> <p><strong>Senses:</strong> <em>{monstersJSON.senses}</em></p> </div> ) } }
называется внутри фигурных скобок:
function MonsterDisplay(props) { const monsterJSON = props.monster if (monstersJSON) { return ( <div> { sense() } </div> ); } }
D&D имеет несколько значений, которые являются полуматематическими. Один из примеров - очки опыта для рейтингового испытания. У монстров есть рейтинг опыта, который переводится в очки опыта. Поскольку они не следуют простой математической зависимости, я не мог использовать математическую функцию, чтобы определить, сколько опыта нужно отобразить для данного рейтинга сложности.
Вместо этого я создал объект, в котором каждый рейтинг проблемы является ключом, а связанные с ним очки опыта - значением.
const challengeRatingXP = { .125: 25, .25: 50, .5: 100, 1: 200, 2: 450, 3: 700, 4: 1100, 5: 1800, … }
Поступая так, я мог использовать рейтинг сложности от объекта-монстра в качестве ключа для получения очков опыта в качестве значения. Вот как я настроил JSX для отображения искомых значений:
<p>Challenge: {monsterJSON.challenge_rating} ( {challengeRatingXP[monsterJSON.challenge_rating]} XP) </p>
Итак, для монстра с рейтингом сложности 3 приложение отобразит:
Испытание: 3 (700XP)
Используя аналогичную логику, я смог интерпретировать и отображать модификаторы силы, ловкости, телосложения, интеллекта, мудрости и харизмы.
const abilityScoreModifier = { … 8: “-1”, 9: “-1”, 10: “0”, 11: “0”, 12: “+1”, 13: “+1”, … }
Я сохранил значения в виде строк, чтобы отображать их обычным способом D&D: «INT 16 (+2)» или «CHA 5 (-3)». Изучая D&D, я обнаружил, что у каждого монстра есть бонус хитов, который можно добавить к их кубикам атаки. Этот бонус не указан явно в объекте JSON монстра, но рассчитывается путем умножения количества выпавших кубиков на множитель Конституции. Очаровательно, правда ?!
Количество выпавших кубиков сохранялось в виде строки в формате «8d10» (8 десятигранных игральных костей) или «10d6» (10 шестигранных игральных костей). Поэтому я решил, что разделю эту строку на символ «d», вернув только 1-е значение, что приведет к количеству пораженных кубиков в виде строки.
На данный момент у меня есть значение модификатора в виде строки и количество ударов в виде строки, и, конечно же, мне пришлось бы использовать parseFloat () или parseInt (), чтобы получить числовое значение, верно? неправильный! Когда я это сделал, React сразу напомнил мне, что это не функции. Однако, когда я подключил строки к вычислениям, все заработало. Я предполагаю, что у React есть некоторая встроенная «нечеткая» логика для интерпретации длинных чисел.
Кроме того, у монстров есть особые способности, действия и легендарные действия. У любого монстра может быть комбинация всех трех или ни одного. Все эти характеристики представлены в виде массивов. Мой товарищ по команде Джейкоб предусмотрительно использовал функцию карты для отображения этих значений. Я использовал свои уроки из предыдущих характеристик, чтобы объединить три различные функции условной карты до одной, в которой я передал заголовок и местоположение массива, который я искал. Вот функция, которую я использовал:
function mapDisplay(titleString, jsonLocation) { if(jsonLocation) { return( <div> <h2><strong>{titleString}</strong></h2> {jsonLocation.map(location => ( <div> <hr></hr> <p><strong>{location.name + “: “}</strong></p> <p><em>{location.desc}</em></p> </div> ))} </div> ) } }
А вот как я назвал функцию:
{mapDisplay(“Special Abilities” monstersJSON.special_abilities)}{mapDisplay(“Actions”, monstersJSON.actions)} {mapDisplay(“Legendary Actions”, mmonstersJSON.legendary_actions)}
Это был интересный способ узнать как реагировать, так и больше о D&D. Надеюсь, вам понравилось это читать!