-
{specNames[specId]}
+
+
{specNames[specId]} ({getPointsInSpec(specId, knownTalents)})
{talents.map((talent, index) =>
)}
-
- Spent: {getTreePointCount(spentPoints)}
)
-}
\ No newline at end of file
+}
+
+(TalentTree as any).whyDidYouRender = true
\ No newline at end of file
diff --git a/src/data/talents.ts b/src/data/talents.ts
index a0d4c22..96207f2 100644
--- a/src/data/talents.ts
+++ b/src/data/talents.ts
@@ -3742,4 +3742,13 @@ export const talentsBySpec: Root = {
}]
}
}
-}
\ No newline at end of file
+}
+
+export const talentToSpec: {[key: number]: number} = {}
+for (let specId in talentsBySpec) {
+ for (let talentId in talentsBySpec[specId]) {
+ talentToSpec[talentId] = parseInt(specId, 10)
+ }
+}
+
+console.log(talentToSpec)
\ No newline at end of file
diff --git a/src/index.tsx b/src/index.tsx
index 87d1be5..272e93e 100644
--- a/src/index.tsx
+++ b/src/index.tsx
@@ -4,6 +4,11 @@ import './index.css';
import App from './App';
import * as serviceWorker from './serviceWorker';
+if (process.env.NODE_ENV !== 'production') {
+ const whyDidYouRender = require('@welldone-software/why-did-you-render')
+ whyDidYouRender(React)
+}
+
ReactDOM.render(
, document.getElementById('root'));
// If you want your app to work offline and load faster, you can change
diff --git a/src/lib/tree.test.ts b/src/lib/tree.test.ts
index fb6834a..a556689 100644
--- a/src/lib/tree.test.ts
+++ b/src/lib/tree.test.ts
@@ -1,40 +1,40 @@
import im from 'immutable'
import {
- setTalentPointsInTree,
- getTreePointCount
+ // setTalentPointsInTree,
+ getPointsInSpec
} from './tree'
-describe('setTalentPointsInTree', () => {
- it('sets points on an empty tree', () => {
- const tree = im.List()
- expect(setTalentPointsInTree(tree, 2, 5).toJS()).toEqual([0, 0, 5])
- })
+// describe('setTalentPointsInTree', () => {
+// it('sets points on an empty tree', () => {
+// const tree = im.List()
+// expect(setTalentPointsInTree(tree, 2, 5).toJS()).toEqual([0, 0, 5])
+// })
- it('sets points in the end of the current range', () => {
- const tree = im.List([0, 1])
- expect(setTalentPointsInTree(tree, 2, 5).toJS()).toEqual([0, 1, 5])
- })
+// it('sets points in the end of the current range', () => {
+// const tree = im.List([0, 1])
+// expect(setTalentPointsInTree(tree, 2, 5).toJS()).toEqual([0, 1, 5])
+// })
- it('sets points in the middle of the current range', () => {
- const tree = im.List([0, 0, 0, 0, 0, 0, 5])
- expect(setTalentPointsInTree(tree, 2, 5).toJS()).toEqual([0, 0, 5, 0, 0, 0, 5])
- })
+// it('sets points in the middle of the current range', () => {
+// const tree = im.List([0, 0, 0, 0, 0, 0, 5])
+// expect(setTalentPointsInTree(tree, 2, 5).toJS()).toEqual([0, 0, 5, 0, 0, 0, 5])
+// })
- it('does not mutate the tree for points already set', () => {
- const tree = im.List([0, 3, 2, 0, 5])
- expect(setTalentPointsInTree(tree, 1, 3)).toStrictEqual(tree)
- })
-})
+// it('does not mutate the tree for points already set', () => {
+// const tree = im.List([0, 3, 2, 0, 5])
+// expect(setTalentPointsInTree(tree, 1, 3)).toStrictEqual(tree)
+// })
+// })
-describe('getTreePointCount', () => {
- it('returns proper count', () => {
- const result = getTreePointCount(im.List([0, 0, 4, 5, 3, 0, 0]))
- expect(result).toBe(12)
- })
+// describe('getTreePointCount', () => {
+// it('returns proper count', () => {
+// const result = getPointsInSpec(im.List([0, 0, 4, 5, 3, 0, 0]))
+// expect(result).toBe(12)
+// })
- it('returns 0 for empty list', () => {
- const result = getTreePointCount(im.List())
- expect(result).toBe(0)
- })
-})
\ No newline at end of file
+// it('returns 0 for empty list', () => {
+// const result = getPointsInSpec(im.List())
+// expect(result).toBe(0)
+// })
+// })
\ No newline at end of file
diff --git a/src/lib/tree.ts b/src/lib/tree.ts
index 1686420..e520f1e 100644
--- a/src/lib/tree.ts
+++ b/src/lib/tree.ts
@@ -1,91 +1,102 @@
import { List, Map, fromJS } from 'immutable'
+import { talentsBySpec, talentToSpec } from '../data/talents';
-/**
- * Sets proper values for a tree, filling in 0s in between.
- */
-export function setTalentPointsInTree(tree: List
, talentIndex: number, points: number): List {
- // Ensure all values until `index` are set, otherwise set to 0
- for (let i = tree.size; i < talentIndex; i++) {
- tree = tree.set(i, 0)
- }
- return tree.set(talentIndex, points)
-}
+export const MAX_POINTS = 51
/**
* Returns the overall points spent in the tree.
*/
-export function getTreePointCount(tree: List): number {
- return tree.reduce((reduction, value) => value + reduction, 0)
+export function getPointsInSpec(specId: number, known: Map): number {
+ // TODO: Hard to test this method when referencing talents from a file. Improve this.
+ return Object.values(talentsBySpec[specId]).reduce((prev: number, current: TalentData) => {
+ return prev + known.get(current.id, 0)
+ }, 0)
}
-export function canRemovePoint() {
-
+export function calcAvailablePoints(known: Map): number {
+ return Math.max(0, MAX_POINTS - known.reduce((prev, current) => prev + current, 0))
}
-export function canSetPoint() {
+/**
+ * Returns whether a talent's other talent requirements are met.
+ */
+export function calcMeetsRequirements(talent: TalentData, known: Map): boolean {
+ if (talent.requires.length === 0) {
+ return true
+ }
+ return talent.requires.reduce((prev, current) => {
+ if (!prev) return false
+ return known.get(current.id, 0) >= current.qty
+ }, true)
+}
+
+/**
+ * Adds a single talent point to the Map, if possible.
+ */
+export const addTalentPoint = (known: Map, talent: TalentData): Map => {
+ const currentPoints = known.get(talent.id, 0)
-}
-
-export const modifyPointsInTree = (tree: List, talent: TalentData, talentIndex: number, modifier: 1 | -1): List => {
- const currentPoints = tree.get(talentIndex, 0)
-
- // TODO: We should prevent reducing talent points on a row when it is a dependency for points already spent in the next row.
+ // Support for specific Talent dependency requirement.
+ if (talent.requires.length > 0 && !calcMeetsRequirements(talent, known)) {
+ return known
+ }
+
+ // Spend a maximum of 51 points
+ if (calcAvailablePoints(known) === 0) {
+ return known
+ }
- // TODO: Support for specific Talent dependency requirement.
-
- // TODO: Spend a maximum of 51 points
-
// Check we have the required amount of points spent in the tree for this talent
const requiredPoints = talent.row * 5
- const spentPointCount = getTreePointCount(tree)
- if (requiredPoints > spentPointCount) return tree
-
- let newPoints = currentPoints
- if (modifier === 1) {
- if (currentPoints === talent.ranks.length) return tree
- newPoints = currentPoints + 1
- } else if (modifier === -1) {
- if (currentPoints === 0) return tree
- newPoints = currentPoints - 1
+ const pointsInSpec = getPointsInSpec(talentToSpec[talent.id], known)
+ if (requiredPoints > pointsInSpec) {
+ return known
}
-
- return setTalentPointsInTree(tree, talentIndex, newPoints)
-}
-
-export const modifyKnownTalents = (known: Map, talent: TalentData, modifier: 1 | -1): Map => {
- const currentPoints = known.get(talent.id, 0)
-
- // TODO: We should prevent reducing talent points on a row when it is a dependency for points already spent in the next row.
- // TODO: Support for specific Talent dependency requirement.
-
- // TODO: Spend a maximum of 51 points
-
- // TODO: Check we have the required amount of points spent in the tree for this talent
- const requiredPoints = talent.row * 5
- // const spentPointCount = known.get(talent.id, 0)
- // if (requiredPoints > spentPointCount) return tree
-
- let newPoints = currentPoints
- if (modifier === 1) {
- if (currentPoints === talent.ranks.length) return known
- newPoints = currentPoints + 1
- } else if (modifier === -1) {
- if (currentPoints === 0) return known
- newPoints = currentPoints - 1
+ // Reached the max rank?
+ if (currentPoints >= talent.ranks.length) {
+ return known
}
- return newPoints === 0
- ? known.remove(talent.id)
- : known.set(talent.id, newPoints)
+ return known.set(talent.id, currentPoints + 1)
}
+/**
+ * Removes a single talent point from the Map, if possible.
+ */
+export const removeTalentPoint = (known: Map, talent: TalentData): Map => {
+ const currentPoints = known.get(talent.id, 0)
+
+ // TODO: We should prevent reducing talent points on a row when it is a dependency for points already spent in the next row.
+
+ // Already no points for this talent
+ if (currentPoints === 0) {
+ return known
+ }
+
+ return currentPoints === 1
+ ? known.remove(talent.id)
+ : known.set(talent.id, currentPoints - 1)
+}
+
+/**
+ * Either adds or removes a talent point based on the modifier.
+ */
+export const modifyTalentPoint = (known: Map, talent: TalentData, modifier: 1 | -1): Map => {
+ if (modifier === 1) {
+ return addTalentPoint(known, talent)
+ } else {
+ return removeTalentPoint(known, talent)
+ }
+}
+
+// TODO
export function parsePointString(str: string): List> {
const list: Array = []
const trees = str.split('-')
trees.map((stringForTree, index) => {
- const points = stringForTree.split('').map(a => parseInt(a, 2))
+ const points = stringForTree.split('').map(a => parseInt(a, 10))
list[index] = points
})
diff --git a/yarn.lock b/yarn.lock
index 630df66..a7dc46d 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1505,6 +1505,13 @@
"@webassemblyjs/wast-parser" "1.8.5"
"@xtuc/long" "4.2.2"
+"@welldone-software/why-did-you-render@^3.2.1":
+ version "3.2.1"
+ resolved "http://npm.soundtrackyourbrand.com/@welldone-software%2fwhy-did-you-render/-/why-did-you-render-3.2.1.tgz#9dc6fd8f8cb1640fbd386694290dbf9244a3a354"
+ integrity sha512-7rCVpFyE5Pnm0qyO8ByWfiFAKONvq6GAUUFuGjdJiOXnsAokdotu5EJ6VDBraV1I7UiVj9+TQRbwvrfsFKU0sw==
+ dependencies:
+ lodash "^4"
+
"@xtuc/ieee754@^1.2.0":
version "1.2.0"
resolved "https://registry.yarnpkg.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790"
@@ -2498,6 +2505,11 @@ class-utils@^0.3.5:
isobject "^3.0.0"
static-extend "^0.1.1"
+classnames@^2.2.6:
+ version "2.2.6"
+ resolved "http://npm.soundtrackyourbrand.com/classnames/-/classnames-2.2.6.tgz#43935bffdd291f326dad0a205309b38d00f650ce"
+ integrity sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q==
+
clean-css@4.2.x:
version "4.2.1"
resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-4.2.1.tgz#2d411ef76b8569b6d0c84068dabe85b0aa5e5c17"
@@ -6070,7 +6082,7 @@ lodash.uniq@^4.5.0:
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.11.tgz#b39ea6229ef607ecd89e2c8df12536891cac9b8d"
integrity sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==
-lodash@^4.0.0, lodash@~4.17.10:
+lodash@^4, lodash@^4.0.0, lodash@~4.17.10:
version "4.17.14"
resolved "http://npm.soundtrackyourbrand.com/lodash/-/lodash-4.17.14.tgz#9ce487ae66c96254fe20b599f21b6816028078ba"
integrity sha512-mmKYbW3GLuJeX+iGP+Y7Gp1AiGHGbXHCOh/jZmrawMmsE7MS4znI3RL2FsjbqOyMayHInjOeykW7PEajUk1/xw==