verseluft-dnd-library 0.1.0 → 0.2.0
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 +1 -0
- package/docs/ai/README.md +2 -1
- package/docs/ai/api/index.md +1 -0
- package/docs/ai/api/tools/name-picker.md +112 -0
- package/docs/ai/changelog.md +17 -0
- package/docs/ai/overview.md +2 -1
- package/docs/human/README.md +2 -1
- package/docs/human/api/index.md +1 -0
- package/docs/human/api/tools/name-picker.md +125 -0
- package/docs/human/changelog.md +17 -0
- package/docs/human/overview.md +3 -1
- package/package.json +5 -3
- package/src/data/nameDatabase.js +104 -0
- package/src/index.js +1 -0
- package/src/tools/name-picker.js +83 -0
package/README.md
CHANGED
|
@@ -14,6 +14,7 @@ A small JavaScript library for DnD-style apps and websites.
|
|
|
14
14
|
- [Human docs](./docs/human/README.md)
|
|
15
15
|
- [AI docs](./docs/ai/README.md)
|
|
16
16
|
- [Dice tool](./docs/human/api/tools/dice.md)
|
|
17
|
+
- [Name picker tool](./docs/human/api/tools/name-picker.md)
|
|
17
18
|
- The published npm package includes both doc sets
|
|
18
19
|
- Build the standalone wiki with `npm run wiki:build`
|
|
19
20
|
|
package/docs/ai/README.md
CHANGED
package/docs/ai/api/index.md
CHANGED
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
# AI Name Picker Reference
|
|
2
|
+
|
|
3
|
+
This file is the AI-specific reference for the name picker tool.
|
|
4
|
+
|
|
5
|
+
## Exported functions
|
|
6
|
+
|
|
7
|
+
- `pickName(options?, randomFn?)`
|
|
8
|
+
- `getSupportedNameRaces()`
|
|
9
|
+
- `listNameData()`
|
|
10
|
+
|
|
11
|
+
## Source files
|
|
12
|
+
|
|
13
|
+
- [src/tools/name-picker.js](/D:/Projects/Verseluft-Core/src/tools/name-picker.js)
|
|
14
|
+
- [src/data/nameDatabase.js](/D:/Projects/Verseluft-Core/src/data/nameDatabase.js)
|
|
15
|
+
|
|
16
|
+
## Supported races
|
|
17
|
+
|
|
18
|
+
- `human`
|
|
19
|
+
- `elf`
|
|
20
|
+
- `dwarf`
|
|
21
|
+
- `halfling`
|
|
22
|
+
- `gnome`
|
|
23
|
+
- `dragonborn`
|
|
24
|
+
- `tiefling`
|
|
25
|
+
- `aasimar`
|
|
26
|
+
- `goliath`
|
|
27
|
+
- `orc`
|
|
28
|
+
|
|
29
|
+
## Behavior summary
|
|
30
|
+
|
|
31
|
+
### `pickName(options?, randomFn?)`
|
|
32
|
+
- Normalizes `race` to lowercase
|
|
33
|
+
- Unknown races fall back to `human`
|
|
34
|
+
- Normalizes `sex` to `male`, `female`, or `any`
|
|
35
|
+
- Normalizes `mode` to `full`, `first`, `surname`, or `split`
|
|
36
|
+
- If `sex` is `any`, the tool randomly chooses a male or female bucket first
|
|
37
|
+
- Returns output based on `mode`
|
|
38
|
+
|
|
39
|
+
### Example
|
|
40
|
+
|
|
41
|
+
```js
|
|
42
|
+
import { pickName } from "verseluft-dnd-library";
|
|
43
|
+
|
|
44
|
+
const name = pickName({ race: "dwarf", sex: "male" });
|
|
45
|
+
/*
|
|
46
|
+
{
|
|
47
|
+
race: "dwarf",
|
|
48
|
+
sex: "male",
|
|
49
|
+
firstName: "Baern",
|
|
50
|
+
surname: "Amberaxe",
|
|
51
|
+
fullName: "Baern Amberaxe"
|
|
52
|
+
}
|
|
53
|
+
*/
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### Output modes
|
|
57
|
+
|
|
58
|
+
- `full`: returns `race`, `sex`, `firstName`, `surname`, and `fullName`
|
|
59
|
+
- `first`: returns `race`, `sex`, and `firstName`
|
|
60
|
+
- `surname`: returns `race`, `sex`, and `surname`
|
|
61
|
+
- `split`: returns `race`, `sex`, `firstName`, and `surname`
|
|
62
|
+
|
|
63
|
+
### `getSupportedNameRaces()`
|
|
64
|
+
- Returns the supported species keys from the internal database
|
|
65
|
+
|
|
66
|
+
### Example
|
|
67
|
+
|
|
68
|
+
```js
|
|
69
|
+
import { getSupportedNameRaces } from "verseluft-dnd-library";
|
|
70
|
+
|
|
71
|
+
getSupportedNameRaces();
|
|
72
|
+
// ["human", "elf", "dwarf", "halfling", "gnome", "dragonborn", "tiefling", "aasimar", "goliath", "orc"]
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### `listNameData()`
|
|
76
|
+
- Returns a cloned copy of the whole database
|
|
77
|
+
- Intended for inspection, not mutation of the source data
|
|
78
|
+
|
|
79
|
+
### Example
|
|
80
|
+
|
|
81
|
+
```js
|
|
82
|
+
import { listNameData } from "verseluft-dnd-library";
|
|
83
|
+
|
|
84
|
+
const data = listNameData();
|
|
85
|
+
// data.human.male.first[0] === "Aren"
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## Data model
|
|
89
|
+
|
|
90
|
+
The database is organized as:
|
|
91
|
+
|
|
92
|
+
```js
|
|
93
|
+
{
|
|
94
|
+
[race]: {
|
|
95
|
+
male: { first: string[], surname: string[] },
|
|
96
|
+
female: { first: string[], surname: string[] }
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## Test guidance
|
|
102
|
+
|
|
103
|
+
- Use a deterministic `randomFn` when testing
|
|
104
|
+
- Verify the race fallback path for unknown values
|
|
105
|
+
- Verify that `sex: "any"` can select either bucket
|
|
106
|
+
- Verify the output mode behavior for `first`, `surname`, `split`, and `full`
|
|
107
|
+
|
|
108
|
+
## Edit boundaries
|
|
109
|
+
|
|
110
|
+
- If name logic changes, update this file and the human version together
|
|
111
|
+
- If the database changes, update examples or supported race notes
|
|
112
|
+
- Do not touch the dice docs when editing the name picker
|
package/docs/ai/changelog.md
CHANGED
|
@@ -7,6 +7,23 @@
|
|
|
7
7
|
- Starter content and tests added
|
|
8
8
|
- Standalone wiki generator added
|
|
9
9
|
|
|
10
|
+
## 0.1.1
|
|
11
|
+
|
|
12
|
+
- Added the name picker tool
|
|
13
|
+
- Added the internal name database for the supported species
|
|
14
|
+
- Added human and AI docs for the name picker tool
|
|
15
|
+
|
|
16
|
+
## 0.1.2
|
|
17
|
+
|
|
18
|
+
- Added output modes for the name picker tool
|
|
19
|
+
- The picker can now return first-only, surname-only, split, or full-name output
|
|
20
|
+
|
|
21
|
+
## 0.2.0
|
|
22
|
+
|
|
23
|
+
- Added the name picker tool as a packaged database-backed feature
|
|
24
|
+
- Added first-name-only, surname-only, split, and full output modes
|
|
25
|
+
- Expanded docs for both human and AI readers
|
|
26
|
+
|
|
10
27
|
AI editing notes:
|
|
11
28
|
|
|
12
29
|
- Keep changelog entries short and factual
|
package/docs/ai/overview.md
CHANGED
|
@@ -5,7 +5,7 @@ Project: Verseluft DnD Library
|
|
|
5
5
|
Purpose:
|
|
6
6
|
|
|
7
7
|
- Small JavaScript toolkit for DnD-style apps and websites
|
|
8
|
-
- Current scope
|
|
8
|
+
- Current scope includes the dice tool and the name picker tool
|
|
9
9
|
|
|
10
10
|
Agent guidance:
|
|
11
11
|
|
|
@@ -19,5 +19,6 @@ Documentation map:
|
|
|
19
19
|
- `docs/ai/changelog.md`
|
|
20
20
|
- `docs/ai/api/index.md`
|
|
21
21
|
- `docs/ai/api/tools/dice.md`
|
|
22
|
+
- `docs/ai/api/tools/name-picker.md`
|
|
22
23
|
|
|
23
24
|
Do not add new tool docs without explicit scope changes.
|
package/docs/human/README.md
CHANGED
package/docs/human/api/index.md
CHANGED
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
# Name Picker Tool
|
|
2
|
+
|
|
3
|
+
The name picker tool generates fantasy names based on race and sex.
|
|
4
|
+
|
|
5
|
+
## Purpose
|
|
6
|
+
|
|
7
|
+
Use this tool to:
|
|
8
|
+
|
|
9
|
+
- Pick a first name and surname
|
|
10
|
+
- Generate names for common DnD species
|
|
11
|
+
- Keep the output simple and readable for games, apps, or character tools
|
|
12
|
+
- Return first-only, surname-only, split, or full-name output
|
|
13
|
+
|
|
14
|
+
## Supported races
|
|
15
|
+
|
|
16
|
+
The current built-in database supports:
|
|
17
|
+
|
|
18
|
+
- `human`
|
|
19
|
+
- `elf`
|
|
20
|
+
- `dwarf`
|
|
21
|
+
- `halfling`
|
|
22
|
+
- `gnome`
|
|
23
|
+
- `dragonborn`
|
|
24
|
+
- `tiefling`
|
|
25
|
+
- `aasimar`
|
|
26
|
+
- `goliath`
|
|
27
|
+
- `orc`
|
|
28
|
+
|
|
29
|
+
## Exports
|
|
30
|
+
|
|
31
|
+
- `pickName(options?, randomFn?)`
|
|
32
|
+
- `getSupportedNameRaces()`
|
|
33
|
+
- `listNameData()`
|
|
34
|
+
|
|
35
|
+
## `pickName(options?, randomFn?)`
|
|
36
|
+
|
|
37
|
+
Returns a generated name for the selected race and sex.
|
|
38
|
+
|
|
39
|
+
### Input
|
|
40
|
+
|
|
41
|
+
- `options.race`: the race/species name, such as `human`, `elf`, or `dwarf`
|
|
42
|
+
- `options.sex`: `male`, `female`, or `any`
|
|
43
|
+
- `options.mode`: `full`, `first`, `surname`, or `split`
|
|
44
|
+
- `randomFn`: optional random function, defaults to `Math.random`
|
|
45
|
+
|
|
46
|
+
### Output
|
|
47
|
+
|
|
48
|
+
```js
|
|
49
|
+
{
|
|
50
|
+
race: string,
|
|
51
|
+
sex: string,
|
|
52
|
+
firstName: string,
|
|
53
|
+
surname: string,
|
|
54
|
+
fullName: string
|
|
55
|
+
}
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### Example
|
|
59
|
+
|
|
60
|
+
```js
|
|
61
|
+
import { pickName } from "verseluft-dnd-library";
|
|
62
|
+
|
|
63
|
+
const name = pickName({ race: "elf", sex: "female" });
|
|
64
|
+
// { race: "elf", sex: "female", firstName: "Ayla", surname: "Galanodel", fullName: "Ayla Galanodel" }
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### Example result
|
|
68
|
+
|
|
69
|
+
```js
|
|
70
|
+
{
|
|
71
|
+
race: "elf",
|
|
72
|
+
sex: "female",
|
|
73
|
+
firstName: "Ayla",
|
|
74
|
+
surname: "Galanodel",
|
|
75
|
+
fullName: "Ayla Galanodel"
|
|
76
|
+
}
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Output modes
|
|
80
|
+
|
|
81
|
+
```js
|
|
82
|
+
pickName({ race: "elf", sex: "female", mode: "first" });
|
|
83
|
+
// { race: "elf", sex: "female", firstName: "Ayla" }
|
|
84
|
+
|
|
85
|
+
pickName({ race: "elf", sex: "female", mode: "surname" });
|
|
86
|
+
// { race: "elf", sex: "female", surname: "Galanodel" }
|
|
87
|
+
|
|
88
|
+
pickName({ race: "elf", sex: "female", mode: "split" });
|
|
89
|
+
// { race: "elf", sex: "female", firstName: "Ayla", surname: "Galanodel" }
|
|
90
|
+
|
|
91
|
+
pickName({ race: "elf", sex: "female", mode: "full" });
|
|
92
|
+
// { race: "elf", sex: "female", firstName: "Ayla", surname: "Galanodel", fullName: "Ayla Galanodel" }
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
If you do not pass `mode`, the default is `full`.
|
|
96
|
+
|
|
97
|
+
## `getSupportedNameRaces()`
|
|
98
|
+
|
|
99
|
+
Returns the supported race list used by the current database.
|
|
100
|
+
|
|
101
|
+
### Example
|
|
102
|
+
|
|
103
|
+
```js
|
|
104
|
+
import { getSupportedNameRaces } from "verseluft-dnd-library";
|
|
105
|
+
|
|
106
|
+
getSupportedNameRaces();
|
|
107
|
+
// ["human", "elf", "dwarf", "halfling", "gnome", "dragonborn", "tiefling", "aasimar", "goliath", "orc"]
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## `listNameData()`
|
|
111
|
+
|
|
112
|
+
Returns a copy of the full internal name database.
|
|
113
|
+
|
|
114
|
+
### Example
|
|
115
|
+
|
|
116
|
+
```js
|
|
117
|
+
import { listNameData } from "verseluft-dnd-library";
|
|
118
|
+
|
|
119
|
+
const data = listNameData();
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
## Editing rule
|
|
123
|
+
|
|
124
|
+
If you change the name picker behavior, update this file and the AI version together.
|
|
125
|
+
If the public API changes, update the central index and changelog too.
|
package/docs/human/changelog.md
CHANGED
|
@@ -7,6 +7,23 @@
|
|
|
7
7
|
- Added starter content modules
|
|
8
8
|
- Added package tests and a browser playground
|
|
9
9
|
|
|
10
|
+
## 0.1.1
|
|
11
|
+
|
|
12
|
+
- Added the name picker tool
|
|
13
|
+
- Added a small built-in name database for 2024-style DnD species
|
|
14
|
+
- Added human and AI documentation for the new tool
|
|
15
|
+
|
|
16
|
+
## 0.1.2
|
|
17
|
+
|
|
18
|
+
- Added output modes for the name picker tool
|
|
19
|
+
- The picker can now return first-only, surname-only, split, or full-name output
|
|
20
|
+
|
|
21
|
+
## 0.2.0
|
|
22
|
+
|
|
23
|
+
- Added the name picker tool as a packaged database-backed feature
|
|
24
|
+
- Added first-name-only, surname-only, split, and full output modes
|
|
25
|
+
- Expanded docs for both human and AI readers
|
|
26
|
+
|
|
10
27
|
## Documentation notes
|
|
11
28
|
|
|
12
29
|
- The docs are organized by topic so AI edits can stay isolated
|
package/docs/human/overview.md
CHANGED
|
@@ -5,6 +5,7 @@ Verseluft DnD Library is a small JavaScript toolkit for DnD-style apps and websi
|
|
|
5
5
|
Right now, this documentation set focuses on a single tool:
|
|
6
6
|
|
|
7
7
|
- Dice tools
|
|
8
|
+
- Name picker tools
|
|
8
9
|
|
|
9
10
|
## What this docs set is for
|
|
10
11
|
|
|
@@ -18,8 +19,9 @@ Right now, this documentation set focuses on a single tool:
|
|
|
18
19
|
- `docs/human/changelog.md` for version notes
|
|
19
20
|
- `docs/human/api/index.md` for the API map
|
|
20
21
|
- `docs/human/api/tools/dice.md` for the dice tool
|
|
22
|
+
- `docs/human/api/tools/name-picker.md` for the name picker tool
|
|
21
23
|
|
|
22
24
|
## Current scope
|
|
23
25
|
|
|
24
|
-
This docs set intentionally covers only the
|
|
26
|
+
This docs set intentionally covers only the current tools for now.
|
|
25
27
|
Other tools and modules can be added later as separate files.
|
package/package.json
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "verseluft-dnd-library",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "A small DnD utility library with reusable content modules
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "A small DnD utility library with reusable content modules, dice tools, and a name picker for apps and websites.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"dnd",
|
|
8
8
|
"rpg",
|
|
9
9
|
"library",
|
|
10
|
+
"name-generator",
|
|
10
11
|
"javascript",
|
|
11
12
|
"browser"
|
|
12
13
|
],
|
|
@@ -16,7 +17,8 @@
|
|
|
16
17
|
".": "./src/index.js",
|
|
17
18
|
"./modules/*": "./src/modules/*.js",
|
|
18
19
|
"./tools/*": "./src/tools/*.js",
|
|
19
|
-
"./content/*": "./src/content/*.js"
|
|
20
|
+
"./content/*": "./src/content/*.js",
|
|
21
|
+
"./data/*": "./src/data/*.js"
|
|
20
22
|
},
|
|
21
23
|
"files": [
|
|
22
24
|
"src",
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
export const nameDatabase = {
|
|
2
|
+
human: {
|
|
3
|
+
male: {
|
|
4
|
+
first: ["Aren", "Darin", "Gavin", "Joran", "Theron"],
|
|
5
|
+
surname: ["Ashford", "Black", "Rivers", "Stone", "Vale"],
|
|
6
|
+
},
|
|
7
|
+
female: {
|
|
8
|
+
first: ["Elira", "Mira", "Nora", "Selene", "Talia"],
|
|
9
|
+
surname: ["Ashford", "Dawn", "Frost", "Hart", "Vale"],
|
|
10
|
+
},
|
|
11
|
+
},
|
|
12
|
+
elf: {
|
|
13
|
+
male: {
|
|
14
|
+
first: ["Aelar", "Erevan", "Faelar", "Laucian", "Soveliss"],
|
|
15
|
+
surname: ["Amakiir", "Galanodel", "Liadon", "Nailo", "Xiloscient"],
|
|
16
|
+
},
|
|
17
|
+
female: {
|
|
18
|
+
first: ["Ayla", "Dayereth", "Keyleth", "Leshanna", "Thia"],
|
|
19
|
+
surname: ["Amakiir", "Galanodel", "Liadon", "Nailo", "Xiloscient"],
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
dwarf: {
|
|
23
|
+
male: {
|
|
24
|
+
first: ["Baern", "Dain", "Eberk", "Harbek", "Orsik"],
|
|
25
|
+
surname: ["Amberaxe", "Balderk", "Fireforge", "Ironfist", "Strakeln"],
|
|
26
|
+
},
|
|
27
|
+
female: {
|
|
28
|
+
first: ["Amber", "Diesa", "Eldeth", "Falkrunn", "Vistra"],
|
|
29
|
+
surname: ["Amberaxe", "Balderk", "Fireforge", "Ironfist", "Strakeln"],
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
halfling: {
|
|
33
|
+
male: {
|
|
34
|
+
first: ["Ander", "Corrin", "Eldon", "Milo", "Osborn"],
|
|
35
|
+
surname: ["Brushgather", "Goodbarrel", "Greenbottle", "High-hill", "Tealeaf"],
|
|
36
|
+
},
|
|
37
|
+
female: {
|
|
38
|
+
first: ["Callie", "Lavinia", "Merla", "Piper", "Rosie"],
|
|
39
|
+
surname: ["Brushgather", "Goodbarrel", "Greenbottle", "High-hill", "Tealeaf"],
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
gnome: {
|
|
43
|
+
male: {
|
|
44
|
+
first: ["Alston", "Boddynock", "Dimble", "Fonkin", "Wrenn"],
|
|
45
|
+
surname: ["Beren", "Nackle", "Murnig", "Scheppen", "Timbers"],
|
|
46
|
+
},
|
|
47
|
+
female: {
|
|
48
|
+
first: ["Bree", "Caramip", "Ella", "Lidda", "Nissa"],
|
|
49
|
+
surname: ["Beren", "Nackle", "Murnig", "Scheppen", "Timbers"],
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
dragonborn: {
|
|
53
|
+
male: {
|
|
54
|
+
first: ["Arjhan", "Balasar", "Donaar", "Ghesh", "Kriv"],
|
|
55
|
+
surname: ["Clethtinthiallor", "Daardendrian", "Delmirev", "Norixius", "Saariv"],
|
|
56
|
+
},
|
|
57
|
+
female: {
|
|
58
|
+
first: ["Akra", "Biri", "Kava", "Sora", "Zykro"],
|
|
59
|
+
surname: ["Clethtinthiallor", "Daardendrian", "Delmirev", "Norixius", "Saariv"],
|
|
60
|
+
},
|
|
61
|
+
},
|
|
62
|
+
tiefling: {
|
|
63
|
+
male: {
|
|
64
|
+
first: ["Akmenos", "Barakas", "Mordai", "Skamos", "Zef"],
|
|
65
|
+
surname: ["Ashspear", "Nightbloom", "Silverthread", "Duskwalker", "Stormeye"],
|
|
66
|
+
},
|
|
67
|
+
female: {
|
|
68
|
+
first: ["Astra", "Bryseis", "Kallista", "Lerissa", "Vesper"],
|
|
69
|
+
surname: ["Ashspear", "Nightbloom", "Silverthread", "Duskwalker", "Stormeye"],
|
|
70
|
+
},
|
|
71
|
+
},
|
|
72
|
+
aasimar: {
|
|
73
|
+
male: {
|
|
74
|
+
first: ["Aurel", "Caelum", "Irian", "Mikael", "Seraph"],
|
|
75
|
+
surname: ["Brightsoul", "Dawnwatch", "Starfall", "Lightborn", "Sunveil"],
|
|
76
|
+
},
|
|
77
|
+
female: {
|
|
78
|
+
first: ["Arielle", "Celeste", "Ilyra", "Mirael", "Seren"],
|
|
79
|
+
surname: ["Brightsoul", "Dawnwatch", "Starfall", "Lightborn", "Sunveil"],
|
|
80
|
+
},
|
|
81
|
+
},
|
|
82
|
+
goliath: {
|
|
83
|
+
male: {
|
|
84
|
+
first: ["Aukan", "Eglath", "Gathak", "Keth", "Thuun"],
|
|
85
|
+
surname: ["Cloudseer", "Ironpeak", "Stoneward", "Thunderborn", "Wolfrun"],
|
|
86
|
+
},
|
|
87
|
+
female: {
|
|
88
|
+
first: ["Ena", "Gunna", "Helli", "Orla", "Zanna"],
|
|
89
|
+
surname: ["Cloudseer", "Ironpeak", "Stoneward", "Thunderborn", "Wolfrun"],
|
|
90
|
+
},
|
|
91
|
+
},
|
|
92
|
+
orc: {
|
|
93
|
+
male: {
|
|
94
|
+
first: ["Dench", "Gell", "Henk", "Ront", "Shump"],
|
|
95
|
+
surname: ["Bloodjaw", "Ironhide", "Skullcrusher", "Stonefang", "Warborn"],
|
|
96
|
+
},
|
|
97
|
+
female: {
|
|
98
|
+
first: ["Baggi", "Emen", "Engong", "Myev", "Ovak"],
|
|
99
|
+
surname: ["Bloodjaw", "Ironhide", "Skullcrusher", "Stonefang", "Warborn"],
|
|
100
|
+
},
|
|
101
|
+
},
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
export const supportedSpecies = Object.keys(nameDatabase);
|
package/src/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export { createDnDLibrary } from "./core/createDnDLibrary.js";
|
|
2
2
|
export { rollDice, parseDiceExpression, averageRoll } from "./tools/dice.js";
|
|
3
|
+
export { pickName, getSupportedNameRaces, listNameData } from "./tools/name-picker.js";
|
|
3
4
|
export { getMonsterById, listMonsters } from "./modules/monsters.js";
|
|
4
5
|
export { getSpellById, listSpells } from "./modules/spells.js";
|
|
5
6
|
export { getItemById, listItems } from "./modules/items.js";
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { nameDatabase, supportedSpecies } from "../data/nameDatabase.js";
|
|
2
|
+
|
|
3
|
+
function normalizeSpecies(race) {
|
|
4
|
+
const value = String(race ?? "human").trim().toLowerCase();
|
|
5
|
+
return supportedSpecies.includes(value) ? value : "human";
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
function normalizeSex(sex) {
|
|
9
|
+
const value = String(sex ?? "any").trim().toLowerCase();
|
|
10
|
+
if (value === "male" || value === "female") {
|
|
11
|
+
return value;
|
|
12
|
+
}
|
|
13
|
+
return "any";
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function normalizeMode(mode) {
|
|
17
|
+
const value = String(mode ?? "full").trim().toLowerCase();
|
|
18
|
+
if (value === "first" || value === "surname" || value === "split" || value === "full") {
|
|
19
|
+
return value;
|
|
20
|
+
}
|
|
21
|
+
return "full";
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function pickFrom(items, randomFn) {
|
|
25
|
+
if (!Array.isArray(items) || items.length === 0) {
|
|
26
|
+
throw new Error("No names available for the selected category.");
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const index = Math.floor(randomFn() * items.length);
|
|
30
|
+
return items[index];
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function pickSexBucket(speciesData, sex, randomFn) {
|
|
34
|
+
if (sex === "male" || sex === "female") {
|
|
35
|
+
return speciesData[sex];
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return randomFn() < 0.5 ? speciesData.male : speciesData.female;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export function getSupportedNameRaces() {
|
|
42
|
+
return [...supportedSpecies];
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export function pickName(options = {}, randomFn = Math.random) {
|
|
46
|
+
const race = normalizeSpecies(options.race);
|
|
47
|
+
const sex = normalizeSex(options.sex);
|
|
48
|
+
const mode = normalizeMode(options.mode);
|
|
49
|
+
const speciesData = nameDatabase[race] ?? nameDatabase.human;
|
|
50
|
+
const sexBucket = pickSexBucket(speciesData, sex, randomFn);
|
|
51
|
+
const firstName = pickFrom(sexBucket.first, randomFn);
|
|
52
|
+
const surname = pickFrom(sexBucket.surname, randomFn);
|
|
53
|
+
|
|
54
|
+
const result = {
|
|
55
|
+
race,
|
|
56
|
+
sex,
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
if (mode === "first") {
|
|
60
|
+
result.firstName = firstName;
|
|
61
|
+
return result;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if (mode === "surname") {
|
|
65
|
+
result.surname = surname;
|
|
66
|
+
return result;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
if (mode === "split") {
|
|
70
|
+
result.firstName = firstName;
|
|
71
|
+
result.surname = surname;
|
|
72
|
+
return result;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
result.firstName = firstName;
|
|
76
|
+
result.surname = surname;
|
|
77
|
+
result.fullName = `${firstName} ${surname}`;
|
|
78
|
+
return result;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export function listNameData() {
|
|
82
|
+
return structuredClone(nameDatabase);
|
|
83
|
+
}
|