@axiapps/gw2-data 0.1.1 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/data/overrides.json +24 -0
- package/package.json +3 -1
- package/src/engine/attributes.js +102 -23
- package/src/engine/boons.js +19 -1
- package/src/engine/constants.js +27 -2
- package/src/engine/index.js +4 -4
- package/src/engine/modifiers.js +57 -21
- package/src/wiki/parser.js +17 -9
- package/scripts/generate-fixtures.js +0 -242
- package/tests/api-client.test.js +0 -138
- package/tests/cache.test.js +0 -108
- package/tests/engine/attributes.test.js +0 -252
- package/tests/engine/boons.test.js +0 -129
- package/tests/engine/combos.test.js +0 -76
- package/tests/engine/constants.test.js +0 -576
- package/tests/engine/fixtures/berserker-thief.json +0 -61
- package/tests/engine/fixtures/berserker-warrior.json +0 -113
- package/tests/engine/fixtures/celestial-firebrand-wvw.json +0 -94
- package/tests/engine/fixtures/harrier-druid.json +0 -119
- package/tests/engine/fixtures/viper-mirage.json +0 -104
- package/tests/engine/graph.test.js +0 -30
- package/tests/engine/integration.test.js +0 -111
- package/tests/engine/modifiers.test.js +0 -473
- package/tests/engine/overrides.test.js +0 -70
- package/tests/engine/snapshot.test.js +0 -53
- package/tests/engine/test-utils.js +0 -20
- package/tests/engine/tooltips.test.js +0 -62
- package/tests/fixtures/capture.js +0 -160
- package/tests/fixtures/fixtures.json +0 -839
- package/tests/integration.test.js +0 -100
- package/tests/match.test.js +0 -176
- package/tests/merge.test.js +0 -128
- package/tests/normalize.test.js +0 -78
- package/tests/parser.test.js +0 -506
- package/tests/real-data.test.js +0 -296
- package/tests/relations.test.js +0 -80
- package/tests/resolver.test.js +0 -721
- package/tests/validate-live.js +0 -191
- package/tests/wiki-client.test.js +0 -468
- package/tests/wiki-integration.test.js +0 -177
- package/tests/wiki-live-validation.test.js +0 -61
- package/tests/wiki-snapshots.test.js +0 -166
|
@@ -1,113 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "Berserker Warrior",
|
|
3
|
-
"description": "Heavy armor, 3-stat, full ascended, signets, Might+Fury assumed",
|
|
4
|
-
"ctx": {
|
|
5
|
-
"profession": "Warrior",
|
|
6
|
-
"specializations": [
|
|
7
|
-
{
|
|
8
|
-
"id": 4,
|
|
9
|
-
"majorChoices": {
|
|
10
|
-
"1": 1444,
|
|
11
|
-
"2": 1449,
|
|
12
|
-
"3": 1437
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
],
|
|
16
|
-
"equipment": {
|
|
17
|
-
"slots": {
|
|
18
|
-
"head": "Berserker's",
|
|
19
|
-
"shoulders": "Berserker's",
|
|
20
|
-
"chest": "Berserker's",
|
|
21
|
-
"gloves": "Berserker's",
|
|
22
|
-
"legs": "Berserker's",
|
|
23
|
-
"boots": "Berserker's",
|
|
24
|
-
"mainhand1": "Berserker's",
|
|
25
|
-
"offhand1": "Berserker's",
|
|
26
|
-
"back": "Berserker's",
|
|
27
|
-
"accessory1": "Berserker's",
|
|
28
|
-
"accessory2": "Berserker's",
|
|
29
|
-
"amulet": "Berserker's",
|
|
30
|
-
"ring1": "Berserker's",
|
|
31
|
-
"ring2": "Berserker's"
|
|
32
|
-
},
|
|
33
|
-
"weapons": {
|
|
34
|
-
"mainhand1": "greatsword"
|
|
35
|
-
},
|
|
36
|
-
"runes": {},
|
|
37
|
-
"infusions": {},
|
|
38
|
-
"enrichment": null,
|
|
39
|
-
"food": null,
|
|
40
|
-
"utility": null
|
|
41
|
-
},
|
|
42
|
-
"gameMode": "pve",
|
|
43
|
-
"underwaterMode": false,
|
|
44
|
-
"activeWeaponSet": 1,
|
|
45
|
-
"skills": {
|
|
46
|
-
"healId": null,
|
|
47
|
-
"utilityIds": [
|
|
48
|
-
9093
|
|
49
|
-
],
|
|
50
|
-
"eliteId": null
|
|
51
|
-
},
|
|
52
|
-
"assumedBoons": {
|
|
53
|
-
"might": 25,
|
|
54
|
-
"fury": true
|
|
55
|
-
},
|
|
56
|
-
"sigilStacks": null
|
|
57
|
-
},
|
|
58
|
-
"catalogs": {
|
|
59
|
-
"traits": [
|
|
60
|
-
{
|
|
61
|
-
"id": 1444,
|
|
62
|
-
"facts": [
|
|
63
|
-
{
|
|
64
|
-
"type": "AttributeAdjust",
|
|
65
|
-
"target": "Power",
|
|
66
|
-
"value": 120
|
|
67
|
-
}
|
|
68
|
-
]
|
|
69
|
-
},
|
|
70
|
-
{
|
|
71
|
-
"id": 1449,
|
|
72
|
-
"facts": []
|
|
73
|
-
},
|
|
74
|
-
{
|
|
75
|
-
"id": 1437,
|
|
76
|
-
"facts": []
|
|
77
|
-
}
|
|
78
|
-
],
|
|
79
|
-
"specializations": [
|
|
80
|
-
{
|
|
81
|
-
"id": 4,
|
|
82
|
-
"minorTraits": []
|
|
83
|
-
}
|
|
84
|
-
],
|
|
85
|
-
"skills": [],
|
|
86
|
-
"runes": [],
|
|
87
|
-
"foods": [],
|
|
88
|
-
"utilities": [],
|
|
89
|
-
"infusions": [],
|
|
90
|
-
"enrichments": []
|
|
91
|
-
},
|
|
92
|
-
"expected": {
|
|
93
|
-
"total": {
|
|
94
|
-
"Power": 3463,
|
|
95
|
-
"Precision": 1982,
|
|
96
|
-
"Toughness": 1000,
|
|
97
|
-
"Vitality": 1000,
|
|
98
|
-
"Ferocity": 982,
|
|
99
|
-
"ConditionDamage": 750,
|
|
100
|
-
"HealingPower": 0,
|
|
101
|
-
"Expertise": 0,
|
|
102
|
-
"Concentration": 0
|
|
103
|
-
},
|
|
104
|
-
"derived": {
|
|
105
|
-
"health": 19212,
|
|
106
|
-
"critChance": 81.76190476190476,
|
|
107
|
-
"critDamage": 215.46666666666667,
|
|
108
|
-
"conditionDuration": 0,
|
|
109
|
-
"boonDuration": 0,
|
|
110
|
-
"armor": 2271
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
}
|
|
@@ -1,94 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "Celestial Firebrand WvW",
|
|
3
|
-
"description": "Heavy armor, 9-stat, WvW Celestial exclusion, rune bonuses",
|
|
4
|
-
"ctx": {
|
|
5
|
-
"profession": "Guardian",
|
|
6
|
-
"specializations": [],
|
|
7
|
-
"equipment": {
|
|
8
|
-
"slots": {
|
|
9
|
-
"head": "Celestial",
|
|
10
|
-
"shoulders": "Celestial",
|
|
11
|
-
"chest": "Celestial",
|
|
12
|
-
"gloves": "Celestial",
|
|
13
|
-
"legs": "Celestial",
|
|
14
|
-
"boots": "Celestial",
|
|
15
|
-
"mainhand1": "Celestial",
|
|
16
|
-
"back": "Celestial",
|
|
17
|
-
"accessory1": "Celestial",
|
|
18
|
-
"accessory2": "Celestial",
|
|
19
|
-
"amulet": "Celestial",
|
|
20
|
-
"ring1": "Celestial",
|
|
21
|
-
"ring2": "Celestial"
|
|
22
|
-
},
|
|
23
|
-
"weapons": {
|
|
24
|
-
"mainhand1": "axe"
|
|
25
|
-
},
|
|
26
|
-
"runes": {
|
|
27
|
-
"head": 24836,
|
|
28
|
-
"shoulders": 24836,
|
|
29
|
-
"chest": 24836,
|
|
30
|
-
"gloves": 24836,
|
|
31
|
-
"legs": 24836,
|
|
32
|
-
"boots": 24836
|
|
33
|
-
},
|
|
34
|
-
"infusions": {},
|
|
35
|
-
"enrichment": null,
|
|
36
|
-
"food": null,
|
|
37
|
-
"utility": null
|
|
38
|
-
},
|
|
39
|
-
"gameMode": "wvw",
|
|
40
|
-
"underwaterMode": false,
|
|
41
|
-
"activeWeaponSet": 1,
|
|
42
|
-
"skills": {
|
|
43
|
-
"healId": null,
|
|
44
|
-
"utilityIds": [],
|
|
45
|
-
"eliteId": null
|
|
46
|
-
},
|
|
47
|
-
"assumedBoons": null,
|
|
48
|
-
"sigilStacks": null
|
|
49
|
-
},
|
|
50
|
-
"catalogs": {
|
|
51
|
-
"traits": [],
|
|
52
|
-
"specializations": [],
|
|
53
|
-
"skills": [],
|
|
54
|
-
"runes": [
|
|
55
|
-
{
|
|
56
|
-
"id": 24836,
|
|
57
|
-
"name": "Superior Rune of the Scholar",
|
|
58
|
-
"bonuses": [
|
|
59
|
-
"+25 Power",
|
|
60
|
-
"+35 Ferocity",
|
|
61
|
-
"+50 Power",
|
|
62
|
-
"+65 Ferocity",
|
|
63
|
-
"+100 Power",
|
|
64
|
-
"+125 Ferocity"
|
|
65
|
-
]
|
|
66
|
-
}
|
|
67
|
-
],
|
|
68
|
-
"foods": [],
|
|
69
|
-
"utilities": [],
|
|
70
|
-
"infusions": [],
|
|
71
|
-
"enrichments": []
|
|
72
|
-
},
|
|
73
|
-
"expected": {
|
|
74
|
-
"total": {
|
|
75
|
-
"Power": 1710,
|
|
76
|
-
"Precision": 1535,
|
|
77
|
-
"Toughness": 1535,
|
|
78
|
-
"Vitality": 1535,
|
|
79
|
-
"Ferocity": 760,
|
|
80
|
-
"ConditionDamage": 535,
|
|
81
|
-
"HealingPower": 535,
|
|
82
|
-
"Expertise": 0,
|
|
83
|
-
"Concentration": 0
|
|
84
|
-
},
|
|
85
|
-
"derived": {
|
|
86
|
-
"health": 16995,
|
|
87
|
-
"critChance": 35.476190476190474,
|
|
88
|
-
"critDamage": 200.66666666666666,
|
|
89
|
-
"conditionDuration": 0,
|
|
90
|
-
"boonDuration": 0,
|
|
91
|
-
"armor": 2806
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
}
|
|
@@ -1,119 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "Harrier Druid",
|
|
3
|
-
"description": "Medium armor, 3-stat healing, enrichment, infusions",
|
|
4
|
-
"ctx": {
|
|
5
|
-
"profession": "Ranger",
|
|
6
|
-
"specializations": [],
|
|
7
|
-
"equipment": {
|
|
8
|
-
"slots": {
|
|
9
|
-
"head": "Harrier's",
|
|
10
|
-
"shoulders": "Harrier's",
|
|
11
|
-
"chest": "Harrier's",
|
|
12
|
-
"gloves": "Harrier's",
|
|
13
|
-
"legs": "Harrier's",
|
|
14
|
-
"boots": "Harrier's",
|
|
15
|
-
"mainhand1": "Harrier's",
|
|
16
|
-
"back": "Harrier's",
|
|
17
|
-
"accessory1": "Harrier's",
|
|
18
|
-
"accessory2": "Harrier's",
|
|
19
|
-
"amulet": "Harrier's",
|
|
20
|
-
"ring1": "Harrier's",
|
|
21
|
-
"ring2": "Harrier's"
|
|
22
|
-
},
|
|
23
|
-
"weapons": {
|
|
24
|
-
"mainhand1": "staff"
|
|
25
|
-
},
|
|
26
|
-
"runes": {},
|
|
27
|
-
"infusions": {
|
|
28
|
-
"head": [
|
|
29
|
-
49432
|
|
30
|
-
],
|
|
31
|
-
"shoulders": [
|
|
32
|
-
49432
|
|
33
|
-
],
|
|
34
|
-
"chest": [
|
|
35
|
-
49432
|
|
36
|
-
],
|
|
37
|
-
"gloves": [
|
|
38
|
-
49432
|
|
39
|
-
],
|
|
40
|
-
"legs": [
|
|
41
|
-
49432
|
|
42
|
-
],
|
|
43
|
-
"boots": [
|
|
44
|
-
49432
|
|
45
|
-
]
|
|
46
|
-
},
|
|
47
|
-
"enrichment": 78061,
|
|
48
|
-
"food": null,
|
|
49
|
-
"utility": null
|
|
50
|
-
},
|
|
51
|
-
"gameMode": "pve",
|
|
52
|
-
"underwaterMode": false,
|
|
53
|
-
"activeWeaponSet": 1,
|
|
54
|
-
"skills": {
|
|
55
|
-
"healId": null,
|
|
56
|
-
"utilityIds": [],
|
|
57
|
-
"eliteId": null
|
|
58
|
-
},
|
|
59
|
-
"assumedBoons": null,
|
|
60
|
-
"sigilStacks": null
|
|
61
|
-
},
|
|
62
|
-
"catalogs": {
|
|
63
|
-
"traits": [],
|
|
64
|
-
"specializations": [],
|
|
65
|
-
"skills": [],
|
|
66
|
-
"runes": [],
|
|
67
|
-
"foods": [],
|
|
68
|
-
"utilities": [],
|
|
69
|
-
"infusions": [
|
|
70
|
-
{
|
|
71
|
-
"id": 49432,
|
|
72
|
-
"name": "+5 Healing Power Infusion",
|
|
73
|
-
"infixUpgrade": {
|
|
74
|
-
"attributes": [
|
|
75
|
-
{
|
|
76
|
-
"attribute": "Healing",
|
|
77
|
-
"modifier": 5
|
|
78
|
-
}
|
|
79
|
-
]
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
],
|
|
83
|
-
"enrichments": [
|
|
84
|
-
{
|
|
85
|
-
"id": 78061,
|
|
86
|
-
"name": "+10 Concentration Enrichment",
|
|
87
|
-
"infixUpgrade": {
|
|
88
|
-
"attributes": [
|
|
89
|
-
{
|
|
90
|
-
"attribute": "BoonDuration",
|
|
91
|
-
"modifier": 10
|
|
92
|
-
}
|
|
93
|
-
]
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
]
|
|
97
|
-
},
|
|
98
|
-
"expected": {
|
|
99
|
-
"total": {
|
|
100
|
-
"Power": 2288,
|
|
101
|
-
"Precision": 1000,
|
|
102
|
-
"Toughness": 1000,
|
|
103
|
-
"Vitality": 1000,
|
|
104
|
-
"Ferocity": 0,
|
|
105
|
-
"ConditionDamage": 0,
|
|
106
|
-
"HealingPower": 922,
|
|
107
|
-
"Expertise": 0,
|
|
108
|
-
"Concentration": 902
|
|
109
|
-
},
|
|
110
|
-
"derived": {
|
|
111
|
-
"health": 15922,
|
|
112
|
-
"critChance": 10,
|
|
113
|
-
"critDamage": 150,
|
|
114
|
-
"conditionDuration": 0,
|
|
115
|
-
"boonDuration": 60.13333333333333,
|
|
116
|
-
"armor": 2118
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
}
|
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "Viper Mirage",
|
|
3
|
-
"description": "Medium armor, 4-stat, trait conversions, food + utility",
|
|
4
|
-
"ctx": {
|
|
5
|
-
"profession": "Mesmer",
|
|
6
|
-
"specializations": [
|
|
7
|
-
{
|
|
8
|
-
"id": 24,
|
|
9
|
-
"majorChoices": {
|
|
10
|
-
"1": 700
|
|
11
|
-
}
|
|
12
|
-
}
|
|
13
|
-
],
|
|
14
|
-
"equipment": {
|
|
15
|
-
"slots": {
|
|
16
|
-
"head": "Viper's",
|
|
17
|
-
"shoulders": "Viper's",
|
|
18
|
-
"chest": "Viper's",
|
|
19
|
-
"gloves": "Viper's",
|
|
20
|
-
"legs": "Viper's",
|
|
21
|
-
"boots": "Viper's",
|
|
22
|
-
"mainhand1": "Viper's",
|
|
23
|
-
"back": "Viper's",
|
|
24
|
-
"accessory1": "Viper's",
|
|
25
|
-
"accessory2": "Viper's",
|
|
26
|
-
"amulet": "Viper's",
|
|
27
|
-
"ring1": "Viper's",
|
|
28
|
-
"ring2": "Viper's"
|
|
29
|
-
},
|
|
30
|
-
"weapons": {
|
|
31
|
-
"mainhand1": "axe"
|
|
32
|
-
},
|
|
33
|
-
"runes": {},
|
|
34
|
-
"infusions": {},
|
|
35
|
-
"enrichment": null,
|
|
36
|
-
"food": 91805,
|
|
37
|
-
"utility": null
|
|
38
|
-
},
|
|
39
|
-
"gameMode": "pve",
|
|
40
|
-
"underwaterMode": false,
|
|
41
|
-
"activeWeaponSet": 1,
|
|
42
|
-
"skills": {
|
|
43
|
-
"healId": null,
|
|
44
|
-
"utilityIds": [],
|
|
45
|
-
"eliteId": null
|
|
46
|
-
},
|
|
47
|
-
"assumedBoons": null,
|
|
48
|
-
"sigilStacks": null
|
|
49
|
-
},
|
|
50
|
-
"catalogs": {
|
|
51
|
-
"traits": [
|
|
52
|
-
{
|
|
53
|
-
"id": 700,
|
|
54
|
-
"facts": [
|
|
55
|
-
{
|
|
56
|
-
"type": "BuffConversion",
|
|
57
|
-
"source": "Vitality",
|
|
58
|
-
"target": "ConditionDamage",
|
|
59
|
-
"percent": 10
|
|
60
|
-
}
|
|
61
|
-
]
|
|
62
|
-
}
|
|
63
|
-
],
|
|
64
|
-
"specializations": [
|
|
65
|
-
{
|
|
66
|
-
"id": 24,
|
|
67
|
-
"minorTraits": []
|
|
68
|
-
}
|
|
69
|
-
],
|
|
70
|
-
"skills": [],
|
|
71
|
-
"runes": [],
|
|
72
|
-
"foods": [
|
|
73
|
-
{
|
|
74
|
-
"id": 91805,
|
|
75
|
-
"name": "Plate of Beef Rendang",
|
|
76
|
-
"buff": "+100 Expertise\n+70 Condition Damage"
|
|
77
|
-
}
|
|
78
|
-
],
|
|
79
|
-
"utilities": [],
|
|
80
|
-
"infusions": [],
|
|
81
|
-
"enrichments": []
|
|
82
|
-
},
|
|
83
|
-
"expected": {
|
|
84
|
-
"total": {
|
|
85
|
-
"Power": 1980,
|
|
86
|
-
"Precision": 1529,
|
|
87
|
-
"Toughness": 1000,
|
|
88
|
-
"Vitality": 1000,
|
|
89
|
-
"Ferocity": 0,
|
|
90
|
-
"ConditionDamage": 1150,
|
|
91
|
-
"HealingPower": 0,
|
|
92
|
-
"Expertise": 629,
|
|
93
|
-
"Concentration": 0
|
|
94
|
-
},
|
|
95
|
-
"derived": {
|
|
96
|
-
"health": 15922,
|
|
97
|
-
"critChance": 35.19047619047619,
|
|
98
|
-
"critDamage": 150,
|
|
99
|
-
"conditionDuration": 41.93333333333333,
|
|
100
|
-
"boonDuration": 0,
|
|
101
|
-
"armor": 1967
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
}
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
const { buildInteractionGraph } = require("../../src/engine/graph");
|
|
4
|
-
|
|
5
|
-
describe("buildInteractionGraph", () => {
|
|
6
|
-
test("builds graph from relations data", () => {
|
|
7
|
-
const relations = new Map([
|
|
8
|
-
[1444, { skills: [5489, 5507], traits: [] }],
|
|
9
|
-
[1449, { skills: [], traits: [1444] }],
|
|
10
|
-
]);
|
|
11
|
-
const graph = buildInteractionGraph(new Set([1444, 1449]), relations);
|
|
12
|
-
expect(graph.get(1444).relatedSkills).toEqual(new Set([5489, 5507]));
|
|
13
|
-
expect(graph.get(1449).relatedTraits).toEqual(new Set([1444]));
|
|
14
|
-
});
|
|
15
|
-
|
|
16
|
-
test("returns empty sets for traits with no relations", () => {
|
|
17
|
-
const relations = new Map();
|
|
18
|
-
const graph = buildInteractionGraph(new Set([100]), relations);
|
|
19
|
-
expect(graph.get(100).relatedSkills.size).toBe(0);
|
|
20
|
-
expect(graph.get(100).relatedTraits.size).toBe(0);
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
test("ignores traits not in activeTraitIds", () => {
|
|
24
|
-
const relations = new Map([
|
|
25
|
-
[999, { skills: [100], traits: [] }],
|
|
26
|
-
]);
|
|
27
|
-
const graph = buildInteractionGraph(new Set([1444]), relations);
|
|
28
|
-
expect(graph.has(999)).toBe(false);
|
|
29
|
-
});
|
|
30
|
-
});
|
|
@@ -1,111 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
const { StatEngine } = require("../../src/engine");
|
|
4
|
-
|
|
5
|
-
function makeCatalogs() {
|
|
6
|
-
return {
|
|
7
|
-
traitById: new Map(),
|
|
8
|
-
skillById: new Map(),
|
|
9
|
-
specializationById: new Map(),
|
|
10
|
-
runeById: new Map(),
|
|
11
|
-
foodById: new Map(),
|
|
12
|
-
utilityById: new Map(),
|
|
13
|
-
infusionById: new Map(),
|
|
14
|
-
enrichmentById: new Map(),
|
|
15
|
-
};
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
function makeCtx(overrides = {}) {
|
|
19
|
-
return {
|
|
20
|
-
profession: "Warrior",
|
|
21
|
-
specializations: [],
|
|
22
|
-
equipment: { slots: {}, weapons: {}, runes: {}, infusions: {} },
|
|
23
|
-
gameMode: "pve",
|
|
24
|
-
underwaterMode: false,
|
|
25
|
-
activeWeaponSet: 1,
|
|
26
|
-
skills: {},
|
|
27
|
-
assumedBoons: null,
|
|
28
|
-
sigilStacks: null,
|
|
29
|
-
...overrides,
|
|
30
|
-
};
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
describe("StatEngine", () => {
|
|
34
|
-
test("constructs with catalogs", () => {
|
|
35
|
-
const engine = new StatEngine(makeCatalogs());
|
|
36
|
-
expect(engine).toBeDefined();
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
test("computeAttributes returns full breakdown", () => {
|
|
40
|
-
const engine = new StatEngine(makeCatalogs());
|
|
41
|
-
const result = engine.computeAttributes(makeCtx());
|
|
42
|
-
expect(result.base.Power).toBe(1000);
|
|
43
|
-
expect(result.total.Power).toBe(1000);
|
|
44
|
-
expect(result.derived.health).toBe(19212);
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
test("collectModifiers returns array", () => {
|
|
48
|
-
const engine = new StatEngine(makeCatalogs());
|
|
49
|
-
const mods = engine.collectModifiers(makeCtx());
|
|
50
|
-
expect(Array.isArray(mods)).toBe(true);
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
test("computeTooltip returns damage for valid skill", () => {
|
|
54
|
-
const catalogs = makeCatalogs();
|
|
55
|
-
const engine = new StatEngine(catalogs);
|
|
56
|
-
const skill = { id: 1, name: "Slash", facts: [{ type: "Damage", dmg_multiplier: 0.8, hit_count: 1 }] };
|
|
57
|
-
const ctx = makeCtx({
|
|
58
|
-
equipment: { slots: {}, weapons: { mainhand1: "sword" }, runes: {}, infusions: {} },
|
|
59
|
-
});
|
|
60
|
-
const result = engine.computeTooltip(ctx, skill, "sword");
|
|
61
|
-
expect(result).toBeDefined();
|
|
62
|
-
expect(result.damage).toBeGreaterThan(0);
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
test("analyzeBoons returns boons and conditions arrays", () => {
|
|
66
|
-
const engine = new StatEngine(makeCatalogs());
|
|
67
|
-
const skills = [{
|
|
68
|
-
name: "Shout", description: "Grant might to allies.", icon: "",
|
|
69
|
-
facts: [{ type: "Buff", status: "Might", apply_count: 3, duration: 8 }],
|
|
70
|
-
}];
|
|
71
|
-
const result = engine.analyzeBoons(skills, []);
|
|
72
|
-
expect(result.boons).toHaveLength(1);
|
|
73
|
-
expect(result.boons[0].name).toBe("Might");
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
test("analyzeCombos returns fields and finishers arrays", () => {
|
|
77
|
-
const engine = new StatEngine(makeCatalogs());
|
|
78
|
-
const skills = [{
|
|
79
|
-
name: "Flame Wall", icon: "", description: "",
|
|
80
|
-
facts: [{ type: "ComboField", field_type: "Fire" }],
|
|
81
|
-
}];
|
|
82
|
-
const result = engine.analyzeCombos(skills, []);
|
|
83
|
-
expect(result.fields).toHaveLength(1);
|
|
84
|
-
});
|
|
85
|
-
|
|
86
|
-
test("full pipeline: equip gear, compute attributes, get tooltip", () => {
|
|
87
|
-
const catalogs = makeCatalogs();
|
|
88
|
-
catalogs.specializationById.set(4, { id: 4, minorTraits: [] });
|
|
89
|
-
catalogs.traitById.set(1444, {
|
|
90
|
-
id: 1444, facts: [{ type: "AttributeAdjust", target: "Power", value: 150 }],
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
const engine = new StatEngine(catalogs);
|
|
94
|
-
const ctx = makeCtx({
|
|
95
|
-
specializations: [{ id: 4, majorChoices: { 1: 1444 } }],
|
|
96
|
-
equipment: {
|
|
97
|
-
slots: { chest: "Berserker's", legs: "Berserker's" },
|
|
98
|
-
weapons: { mainhand1: "greatsword" },
|
|
99
|
-
runes: {}, infusions: {},
|
|
100
|
-
},
|
|
101
|
-
});
|
|
102
|
-
|
|
103
|
-
const attrs = engine.computeAttributes(ctx);
|
|
104
|
-
expect(attrs.total.Power).toBeGreaterThan(1000);
|
|
105
|
-
expect(attrs.traits.Power).toBe(150);
|
|
106
|
-
|
|
107
|
-
const skill = { id: 5489, name: "Fireball", facts: [{ type: "Damage", dmg_multiplier: 0.75, hit_count: 1 }] };
|
|
108
|
-
const tooltip = engine.computeTooltip(ctx, skill, "greatsword");
|
|
109
|
-
expect(tooltip.damage).toBeGreaterThan(0);
|
|
110
|
-
});
|
|
111
|
-
});
|