Single Page Application Project

Posted by Kelly on May 15, 2020

The fourth project for Flatiron is a single page application with a rails backend and an object oriented javascript and HTML frontend. My project is a Dungeons and Dragons character generator, using the rules of the Dungeons and Dragons handbook to generate ability scores and modifiers, along with other class/race/background specific information.

I found this very nice D&D character form online that I used as the “read” and “update” part of the CRUD actions for a new character: https://codepen.io/anon/pen/dWKdvm/

My character class inherits from an original class of UniversalCharacter that looks like this: ```class UniversalCharacter { constructor() { this.dexterity = this.getAbilityScore() this.constitution = this.getAbilityScore() this.wisdom = this.getAbilityScore() this.intellect = this.getAbilityScore() this.charisma = this.getAbilityScore() this.strength = this.getAbilityScore() // half elf has 2 extra ability points to spend wherever you want… make this its own function this.free_ability_pts = 0 this.speed = 25 this.hp = 0 this.alignment= “”; this.language= [“Common”]; this.proficiencies = []; // these are for editing for people who want to save this stuff to DB this.personality_traits = “”; this.ideals = “”; this.bonds = “”; this.flaws = “”; this.features_and_traits = “”; this.equipment = “”; this.attacks_and_spells = “”; this.background = “”; this.saving_throws = []

}   // roll 4 six-sided dice, add the top 3 numbers.
getAbilityScore(){
  let arr = [Math.floor(Math.random()*6+1), Math.floor(Math.random()*6+1), Math.floor(Math.random()*6+1), Math.floor(Math.random()*6+1)].sort();
  let arr1 = arr.slice(0,3);
  return arr1.reduce((total, element) => {return total + element}, 0)
}
// calculate ability modifier
// why is this not avail on an instance of a character?  char.modifier(10) method not defined
modifier(value) {
  return Math.floor((value - 10) / 2)
}   }   ```

The Race class inherits from the UniversalCharacter class:
``` class Race extends UniversalCharacter {
constructor(race) {
  super()
  this.race = race
  this.selectRaceModifiers()
}
  
selectRaceModifiers(){
  // console.log('in race modifier ' + this.hp);
  switch (this.race) {
    case 'Dwarf':
      this.constitution += 2;
      this.hp += 1;
      this.alignment += "Lawful";
      this.proficiencies = this.proficiencies.push("History");
      // console.log('hp under race class is' + this.hp);
      break;
    case 'Elf':
      this.dexterity += 2;
      this.speed += 5;
      this.language = this.language.push("Elvish");
      this.alignment += "Chaotic G/E";
      this.proficiencies = this.proficiencies.push("Perception");
      break;
    case 'Halfling':
      this.language = this.language.push("Halfling");
      this.alignment += "Lawful Good";
      this.dexterity += 2;
      break;
    case 'Human':
      this.language = this.language.push("Any one other");
      this.alignment += "any";
      this.dexterity += 1;
      this.wisdom += 1;
      this.intellect += 1;
      this.charisma += 1;
      this.strength += 1;
      this.constitution += 1;
      this.speed += 5;
      break;
    case 'Dragonborn':
      this.language = this.language.push("Draconic");
      this.alignment = "Chaotic G/E";
      this.strength += 2;
      this.charisma += 1;
      this.speed += 5;
      break;
    case 'Gnome':
      this.language = this.language.push("Gnomish");
      this.alignment = "Neutral Good";
      this.intellect += 2;
      break;
    case 'Half-Elf':
      this.language = this.language.push("Elvish", "one more");
      this.proficiencies = this.proficiencies.push("any two");
      this.free_ability_pts += 2;
      this.charisma += 2;
      this.speed += 5;
      break;
    case 'Half-Orc':
      this.language = this.language.push("Orcish");
      this.proficiencies = this.proficiencies.push("Intimidation");
      this.strength += 1;
      this.constitution += 1;
      this.speed += 5;
      break;
    case 'Tiefling':
      this.alignment += "Chaotic Evil";
      this.language = this.language.push("Infernal");
      this.intellect += 1;
      this.charisma += 2;
      this.speed += 5;
      break;
  }
}   }   ```
The CharClass inherits from the race class:
```

class CharClass extends Race { constructor(race, charClass) { super(race) this.charClass = charClass this.selectClassModifiers() } selectClassModifiers(){ // if(this.charClass == “Paladin”) { // this.hitDice = “1d10” // this.hp = 10 + this.modifier(this.constitution) // } switch (this.charClass) { case ‘Barbarian’: this.hitDice = “1d12”; this.hp += Math.floor(Math.random()12+1) + this.modifier(this.constitution); this.saving_throws.push(“Strength”, “Constitution”); // console.log(hp under class is ${this.hp}); break; case ‘Bard’: this.hitDice = “1d8”; this.hp += Math.floor(Math.random()8+1) + this.modifier(this.constitution); this.saving_throws.push(“Dexterity”, “Charisma”); break; case ‘Cleric’: this.hitDice = “1d8”; this.hp += Math.floor(Math.random()8+1) + this.modifier(this.constitution); this.saving_throws.push(“Wisdom”, “Charisma”); break; case ‘Druid’: this.hitDice = “1d8”; this.hp += Math.floor(Math.random()8+1) + this.modifier(this.constitution); this.saving_throws.push(“Intellect”, “Wisdom”); break; case ‘Fighter’: this.hitDice = “1d10”; this.hp += Math.floor(Math.random()10+1) + this.modifier(this.constitution); this.saving_throws.push(“Strength”, “Constitution”); break; case ‘Monk’: this.hitDice = “1d8”; this.hp += Math.floor(Math.random()8+1) + this.modifier(this.constitution); this.saving_throws.push(“Strength”, “Dexterity”); break; case ‘Paladin’: this.hitDice = “1d10”; this.hp += Math.floor(Math.random()10+1) + this.modifier(this.constitution); this.saving_throws.push(“Wisdom”, “Charisma”); break; case ‘Ranger’: this.hitDice = “1d10”; this.hp += Math.floor(Math.random()10+1) + this.modifier(this.constitution); this.saving_throws.push(“Strength”, “Dexterity”); break; case ‘Rogue’: this.hitDice = “1d8”; this.hp += Math.floor(Math.random()8+1) + this.modifier(this.constitution); this.saving_throws.push(“Dexterity”, “Intellect”); break; case ‘Sorcerer’: this.hitDice = “1d6”; this.hp += Math.floor(Math.random()6+1) + this.modifier(this.constitution); this.saving_throws.push(“Charisma”, “Constitution”); break; case ‘Warlock’: this.hitDice = “1d8”; this.hp += Math.floor(Math.random()8+1) + this.modifier(this.constitution); this.saving_throws.push(“Wisdom”, “Charisma”); break; case ‘Wizard’: this.hitDice = “1d6”; this.hp += Math.floor(Math.random()6+1) + this.modifier(this.constitution); this.saving_throws.push(“Intellect”, “Wisdom”); break; } } } and the Background class inherits from the race class, and finally the Character class inherits from the background class: class Character extends Background { constructor(name, race, charClass, background, player, id) { super(race, charClass, background) this.name = name this.id = id this.player = player } } ```

The ability scores follow the D&D handbook where you roll four 6-sided dice, take the top 3 rolls and add them together, the function can be found in the UniversalCharacter Class.

A Player can have many characters, so I made a list of players available to all, and the ability to create a new character using a fetch Post to the backend database. 

Right now the app is a Minimal Viable Product, and I added potential to add many more features, as making a D&D character can get quite complicated, I did not implement all of the features that can be offered.  I am leaving it open to improvement later on.

My biggest challenge was getting object oriented JS to be organized the way I wanted.  This MVP version of the app is not organized exactly how I would like, but it works and I can edit and organize later as I see fit.  I made many different versions of classes fought with them until ultimately deciding to get the app working and leaving it open to editing and refactoring later on.