@dchighs/dc-core 0.3.0 → 0.4.1

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/README.md ADDED
@@ -0,0 +1,211 @@
1
+ # dc-core
2
+
3
+ `@dchighs/dc-core` is a TypeScript/JavaScript library that simulates core Dragon City game logic.
4
+
5
+ It provides:
6
+
7
+ - **Calculators** for attack damage, feed cost, orb recall gain, and element strengths/weaknesses.
8
+ - **Validation tools** for dragon metadata.
9
+ - **Static configuration** for dragons, islands, sounds, elements, and more.
10
+ - **Enums** for strongly-typed values used across the package.
11
+
12
+ ## Installation
13
+
14
+ ```bash
15
+ npm install @dchighs/dc-core
16
+ ```
17
+
18
+ ## Quick start
19
+
20
+ ```ts
21
+ import {
22
+ calculateAttackDamage,
23
+ calculateDragonFeedCost,
24
+ calculateElementStrengths,
25
+ DragonElement,
26
+ } from "@dchighs/dc-core"
27
+
28
+ const damage = calculateAttackDamage({
29
+ attackPower: 1800,
30
+ dragon: {
31
+ category: 9,
32
+ level: 40,
33
+ rank: 2,
34
+ stars: 3,
35
+ },
36
+ })
37
+
38
+ console.log(damage)
39
+ // { minimum: ..., maximum: ..., average: ..., random: ... }
40
+
41
+ const feedCost = calculateDragonFeedCost({ initialLevel: 1, finalLevel: 40 })
42
+ console.log(feedCost)
43
+
44
+ const strengths = calculateElementStrengths(DragonElement.Legend)
45
+ console.log(strengths)
46
+ ```
47
+
48
+ ## Main exports
49
+
50
+ ### Calculators
51
+
52
+ - `calculateAttackDamage(options)`
53
+ - `calculateDragonFeedCost(options)`
54
+ - `calculateElementStrengths(element)`
55
+ - `calculateElementsStrengths(elements)`
56
+ - `calculateElementWeaknesses(element)`
57
+ - `calculateOrbRecallGain(options)`
58
+
59
+ #### `calculateAttackDamage(options)`
60
+
61
+ Calculates the expected damage range for a dragon attack.
62
+
63
+ - **Input**
64
+ - `attackPower: number`
65
+ - `dragon: { category: number; level: number; rank: number; stars: number }`
66
+ - **Validation**
67
+ - Checks category, rank, and level/stars compatibility.
68
+ - **Output**
69
+ - `{ minimum: number; maximum: number; average: number; random: number }`
70
+ - **Notes**
71
+ - Uses dragon category, level scaling, rank bonus, and star bonus from `dragonSettings`.
72
+ - `random` is sampled from the internal damage variance range.
73
+
74
+ #### `calculateDragonFeedCost(options)`
75
+
76
+ Computes the total food required based on dragon levels.
77
+
78
+ - **Input**
79
+ - `initialLevel: number`
80
+ - `finalLevel: number`
81
+ - **Validation**
82
+ - Validates both levels and throws if `initialLevel > finalLevel`.
83
+ - **Output**
84
+ - `number` (total food cost)
85
+
86
+ #### `calculateElementStrengths(element)`
87
+
88
+ Returns which elements are strong against a single element.
89
+
90
+ - **Input**
91
+ - `element: string` (ideally from `DragonElement`)
92
+ - **Validation**
93
+ - Validates if the element exists in internal settings.
94
+ - **Output**
95
+ - `DragonElement[]`
96
+
97
+ #### `calculateElementsStrengths(elements)`
98
+
99
+ Combines strengths for multiple elements and removes duplicates.
100
+
101
+ - **Input**
102
+ - `elements: string[]`
103
+ - **Validation**
104
+ - Validates each provided element.
105
+ - **Output**
106
+ - `string[]` with unique strengths from all provided elements.
107
+
108
+ #### `calculateElementWeaknesses(element)`
109
+
110
+ Returns which elements can hit the provided element effectively.
111
+
112
+ - **Input**
113
+ - `element: string` (ideally from `DragonElement`)
114
+ - **Validation**
115
+ - Validates if the element exists in internal settings.
116
+ - **Output**
117
+ - `DragonElement[]`
118
+
119
+ #### `calculateOrbRecallGain(options)`
120
+
121
+ Calculates how many orbs are returned when recalling a dragon.
122
+
123
+ - **Input**
124
+ - `level: number`
125
+ - `stars?: number` (defaults to `0`)
126
+ - **Validation**
127
+ - Validates level/stars compatibility.
128
+ - **Output**
129
+ - `number` (total recalled orbs)
130
+ - **Notes**
131
+ - Recall level contribution is capped internally at level `30`.
132
+
133
+ ### Tools
134
+
135
+ - `validateDragonLevelCompatibilityWithStars(options)`
136
+ - `validateDragonCategory(category, options?)`
137
+ - `validateDragonRarity(rarity, options?)`
138
+ - `validateDragonStars(stars, options?)`
139
+ - `validateElementName(element, options?)`
140
+ - `validateDragonLevel(level, options?)`
141
+ - `validateDragonRank(rank, options?)`
142
+ - `getMusicKeyNameFromTag(tag)`
143
+ - `DragonStaticFileUrlParser`
144
+
145
+ ### Settings
146
+
147
+ - `dragonSettings`
148
+ - `feedCostSettings`
149
+ - `orbRecallReturnSettings`
150
+ - `elementSettings`
151
+ - `islandSettings`
152
+ - `soundSettings`
153
+
154
+ ### Enums
155
+
156
+ All enums are exported from the package root, including:
157
+
158
+ - `DragonElement`
159
+ - `DragonRarity`
160
+ - `DragonCategory`
161
+ - `DragonRank`
162
+ - `DragonPhase`
163
+ - `ConfigPlatform`
164
+ - `ConfigLanguage`
165
+
166
+ ## Example: validating values before calculations
167
+
168
+ ```ts
169
+ import {
170
+ validateDragonLevelCompatibilityWithStars,
171
+ validateDragonCategory,
172
+ validateDragonRank,
173
+ } from "@dchighs/dc-core"
174
+
175
+ validateDragonLevelCompatibilityWithStars({
176
+ level: 40,
177
+ stars: 3,
178
+ throwOnError: true,
179
+ })
180
+
181
+ validateDragonCategory(9, { throwOnError: true })
182
+ validateDragonRank(2, { throwOnError: true })
183
+ ```
184
+
185
+ ## Example: parsing static asset URLs
186
+
187
+ ```ts
188
+ import { DragonStaticFileUrlParser } from "@dchighs/dc-core"
189
+
190
+ const spriteUrl = "https://aws-static.socialpointgames.com/static/dragoncity/mobile/ui/dragons/112_terra_3@2x.png"
191
+
192
+ const parsed = DragonStaticFileUrlParser.parseFromSprite(spriteUrl)
193
+ console.log(parsed)
194
+ // {
195
+ // platformPrefix: 'aws',
196
+ // id: 112,
197
+ // imageName: '112_terra',
198
+ // phase: 3,
199
+ // skin: null,
200
+ // imageQuality: '@2x'
201
+ // }
202
+ ```
203
+
204
+ ## Notes
205
+
206
+ - Functions may throw if invalid values are provided and `throwOnError: true` is used.
207
+ - This package is distributed as CommonJS with TypeScript definitions.
208
+
209
+ ## License
210
+
211
+ MIT
@@ -0,0 +1,60 @@
1
+ export type CalculateBreedingResultsParentConfig = {
2
+ id: number;
3
+ elements: string[];
4
+ level: number;
5
+ empowerLevel?: number;
6
+ };
7
+ export type CalculateBreedingResultsConfigOptions = {
8
+ breeding: Array<{
9
+ element_one: string;
10
+ element_two: string;
11
+ dragon_id_1: number;
12
+ empower_1: number;
13
+ dragon_id_2: number;
14
+ empower_2: number;
15
+ dragon_id_3: number;
16
+ empower_3: number;
17
+ dragon_id_4?: number;
18
+ empower_4?: number;
19
+ dragon_id_5?: number;
20
+ empower_5?: number;
21
+ dragon_id_6?: number;
22
+ empower_6?: number;
23
+ dragon_id_7?: number;
24
+ empower_7?: number;
25
+ }>;
26
+ incompatibilities?: Array<{
27
+ element_one: string;
28
+ element_two: string;
29
+ }>;
30
+ soulmates?: Array<{
31
+ parent_1_id: number;
32
+ parent_2_id: number;
33
+ dragon_id: number;
34
+ chance: number;
35
+ level_parents: number;
36
+ }>;
37
+ specialBreeding?: Array<{
38
+ condition1: {
39
+ id: number[];
40
+ };
41
+ condition2: {
42
+ id: number[];
43
+ };
44
+ result: number;
45
+ }>;
46
+ sanctuaryUnlockedDragons?: number[];
47
+ };
48
+ export type CalculateBreedingResultsOptions = {
49
+ parent1: CalculateBreedingResultsParentConfig;
50
+ parent2: CalculateBreedingResultsParentConfig;
51
+ config: CalculateBreedingResultsConfigOptions;
52
+ };
53
+ export type BreedingSource = "soulmate" | "special" | "sanctuary" | "regular";
54
+ export type BreedingResultItem = {
55
+ dragonId: number;
56
+ sources: BreedingSource[];
57
+ requiredEmpower?: number;
58
+ chance?: number;
59
+ };
60
+ export declare function calculateBreedingResults({ parent1, parent2, config }: CalculateBreedingResultsOptions): BreedingResultItem[];
@@ -0,0 +1,84 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.calculateBreedingResults = calculateBreedingResults;
4
+ function calculateBreedingResults({ parent1, parent2, config }) {
5
+ var _a;
6
+ const resultsMap = new Map();
7
+ function addResult(dragonId, source, empower, chance) {
8
+ if (!dragonId)
9
+ return;
10
+ const existing = resultsMap.get(dragonId);
11
+ if (existing) {
12
+ if (!existing.sources.includes(source)) {
13
+ existing.sources.push(source);
14
+ }
15
+ if (empower !== undefined) {
16
+ existing.requiredEmpower = existing.requiredEmpower !== undefined ? Math.min(existing.requiredEmpower, empower) : empower;
17
+ }
18
+ if (chance !== undefined) {
19
+ existing.chance = Math.max(existing.chance || 0, chance);
20
+ }
21
+ }
22
+ else {
23
+ resultsMap.set(dragonId, {
24
+ dragonId,
25
+ sources: [source],
26
+ requiredEmpower: empower,
27
+ chance
28
+ });
29
+ }
30
+ }
31
+ if (config.specialBreeding) {
32
+ for (const special of config.specialBreeding) {
33
+ const matchesP1Cond1 = special.condition1.id.includes(parent1.id);
34
+ const matchesP2Cond2 = special.condition2.id.includes(parent2.id);
35
+ const matchesP1Cond2 = special.condition2.id.includes(parent1.id);
36
+ const matchesP2Cond1 = special.condition1.id.includes(parent2.id);
37
+ if ((matchesP1Cond1 && matchesP2Cond2) || (matchesP1Cond2 && matchesP2Cond1)) {
38
+ addResult(special.result, "special");
39
+ }
40
+ }
41
+ }
42
+ if (config.soulmates) {
43
+ for (const soulmate of config.soulmates) {
44
+ const matches = (soulmate.parent_1_id === parent1.id && soulmate.parent_2_id === parent2.id) ||
45
+ (soulmate.parent_1_id === parent2.id && soulmate.parent_2_id === parent1.id);
46
+ const levelsMatch = parent1.level >= soulmate.level_parents && parent2.level >= soulmate.level_parents;
47
+ if (matches && levelsMatch) {
48
+ addResult(soulmate.dragon_id, "soulmate", undefined, soulmate.chance);
49
+ }
50
+ }
51
+ }
52
+ const incompatibilities = config.incompatibilities || [];
53
+ const isIncompatible = (e1, e2) => {
54
+ return incompatibilities.some(inc => (inc.element_one === e1 && inc.element_two === e2) ||
55
+ (inc.element_one === e2 && inc.element_two === e1));
56
+ };
57
+ for (const e1 of parent1.elements) {
58
+ for (const e2 of parent2.elements) {
59
+ if (isIncompatible(e1, e2)) {
60
+ continue;
61
+ }
62
+ const breedingRule = config.breeding.find(b => (b.element_one === e1 && b.element_two === e2) ||
63
+ (b.element_one === e2 && b.element_two === e1));
64
+ if (breedingRule) {
65
+ const pairs = [
66
+ { id: breedingRule.dragon_id_1, emp: breedingRule.empower_1 },
67
+ { id: breedingRule.dragon_id_2, emp: breedingRule.empower_2 },
68
+ { id: breedingRule.dragon_id_3, emp: breedingRule.empower_3 },
69
+ { id: breedingRule.dragon_id_4, emp: breedingRule.empower_4 },
70
+ { id: breedingRule.dragon_id_5, emp: breedingRule.empower_5 },
71
+ { id: breedingRule.dragon_id_6, emp: breedingRule.empower_6 },
72
+ { id: breedingRule.dragon_id_7, emp: breedingRule.empower_7 },
73
+ ];
74
+ for (const pair of pairs) {
75
+ if (pair.id) {
76
+ const isSanctuary = (_a = config.sanctuaryUnlockedDragons) === null || _a === void 0 ? void 0 : _a.includes(pair.id);
77
+ addResult(pair.id, isSanctuary ? "sanctuary" : "regular", pair.emp || 0);
78
+ }
79
+ }
80
+ }
81
+ }
82
+ }
83
+ return Array.from(resultsMap.values());
84
+ }
@@ -6,9 +6,9 @@ const elements_1 = require("../settings/elements");
6
6
  function calculateElementWeaknesses(element) {
7
7
  (0, validate_element_name_1.validateElementName)(element, { throwOnError: true });
8
8
  const weaknesses = [];
9
- for (const element in elements_1.elementSettings) {
10
- if (elements_1.elementSettings[element].strengths.includes(element)) {
11
- weaknesses.push(element);
9
+ for (const key in elements_1.elementSettings) {
10
+ if (elements_1.elementSettings[key].strengths.includes(element)) {
11
+ weaknesses.push(key);
12
12
  }
13
13
  }
14
14
  return weaknesses;
@@ -4,4 +4,7 @@ import { calculateElementStrengths } from "./calculate-element-strengths";
4
4
  import { calculateDragonFeedCost } from "./calculate-dragon-feed-cost";
5
5
  import { calculateOrbRecallGain } from "./calculate-orb-recall-gain";
6
6
  import { calculateAttackDamage } from "./calculate-attack-damage";
7
- export { calculateOrbRecallGain, calculateAttackDamage, calculateDragonFeedCost, calculateElementsStrengths, calculateElementWeaknesses, calculateElementStrengths };
7
+ import { calculateBreedingResults } from "./calculate-breeding-results";
8
+ export * from "./calculate-breeding-results";
9
+ import { calculateElementResistances } from "./calculate-element-resistances";
10
+ export { calculateElementResistances, calculateOrbRecallGain, calculateAttackDamage, calculateDragonFeedCost, calculateElementsStrengths, calculateElementWeaknesses, calculateElementStrengths, calculateBreedingResults };
@@ -1,6 +1,20 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
2
16
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.calculateElementStrengths = exports.calculateElementWeaknesses = exports.calculateElementsStrengths = exports.calculateDragonFeedCost = exports.calculateAttackDamage = exports.calculateOrbRecallGain = void 0;
17
+ exports.calculateBreedingResults = exports.calculateElementStrengths = exports.calculateElementWeaknesses = exports.calculateElementsStrengths = exports.calculateDragonFeedCost = exports.calculateAttackDamage = exports.calculateOrbRecallGain = exports.calculateElementResistances = void 0;
4
18
  const calculate_elements_strengths_1 = require("./calculate-elements-strengths");
5
19
  Object.defineProperty(exports, "calculateElementsStrengths", { enumerable: true, get: function () { return calculate_elements_strengths_1.calculateElementsStrengths; } });
6
20
  const calculate_element_weaknesses_1 = require("./calculate-element-weaknesses");
@@ -13,3 +27,8 @@ const calculate_orb_recall_gain_1 = require("./calculate-orb-recall-gain");
13
27
  Object.defineProperty(exports, "calculateOrbRecallGain", { enumerable: true, get: function () { return calculate_orb_recall_gain_1.calculateOrbRecallGain; } });
14
28
  const calculate_attack_damage_1 = require("./calculate-attack-damage");
15
29
  Object.defineProperty(exports, "calculateAttackDamage", { enumerable: true, get: function () { return calculate_attack_damage_1.calculateAttackDamage; } });
30
+ const calculate_breeding_results_1 = require("./calculate-breeding-results");
31
+ Object.defineProperty(exports, "calculateBreedingResults", { enumerable: true, get: function () { return calculate_breeding_results_1.calculateBreedingResults; } });
32
+ __exportStar(require("./calculate-breeding-results"), exports);
33
+ const calculate_element_resistances_1 = require("./calculate-element-resistances");
34
+ Object.defineProperty(exports, "calculateElementResistances", { enumerable: true, get: function () { return calculate_element_resistances_1.calculateElementResistances; } });
package/package.json CHANGED
@@ -1,16 +1,19 @@
1
1
  {
2
2
  "name": "@dchighs/dc-core",
3
- "version": "0.3.0",
3
+ "version": "0.4.1",
4
4
  "description": "A library focused on simulating some of the logic of the game Dragon City.",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.js",
7
7
  "types": "./dist/index.d.ts",
8
8
  "files": [
9
9
  "dist/*",
10
- "!/**/__tests__"
10
+ "!/**/__tests__",
11
+ "README.md",
12
+ "LICENSE"
11
13
  ],
12
14
  "scripts": {
13
15
  "test": "jest",
16
+ "test:coverage": "jest --coverage",
14
17
  "build": "tsc"
15
18
  },
16
19
  "keywords": [
@@ -31,6 +34,6 @@
31
34
  },
32
35
  "repository": {
33
36
  "type": "git",
34
- "url": "https://github.com/dchighs/dc-core.git"
37
+ "url": "https://github.com/dc-highs/dc-core.git"
35
38
  }
36
39
  }