-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathindex.js
More file actions
102 lines (88 loc) · 2.92 KB
/
Copy pathindex.js
File metadata and controls
102 lines (88 loc) · 2.92 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
'use strict';
(function() {
const emotions = typeof module !== 'undefined' && module.exports ? require('./emotions') : window.EMOTIONS;
/**
* Generate a random emoticon for the given emotion.
*
* @param {string} emotion - The emotion to generate an emoticon for.
* @param {number} [intensity=0.5] - Intensity from 0 (mild) to 1 (intense). 0.5 is uniform random.
* @returns {string} A random emoticon matching the emotion.
* @throws {Error} If the emotion is not recognized.
*
* @example
* emoticon('happy') // => 'ヽ(^◡^)ノ'
* emoticon('angry', 0.8) // => 'ᕙ(╬Д╬)ᕗ' (intense)
* emoticon('angry', 0.2) // => '(•́_•́)' (mild)
*/
function emoticon(emotion, intensity) {
if (typeof emotion !== 'string') {
throw new TypeError(`Emotion must be a string, got ${typeof emotion}`);
}
emotion = emotion.toLowerCase().trim();
const config = emotions[emotion];
if (!config) {
throw new Error(
`Unknown emotion "${emotion}". Available: ${Object.keys(emotions).join(', ')}`
);
}
// Intensity defaults to 0.5 (uniform)
const t = intensity !== undefined && Number.isFinite(+intensity) ? Math.max(0, Math.min(1, +intensity)) : 0.5;
// Pre-composed emoticons (e.g. shrug) — intensity N/A
if (config.preComposed) {
return pick(config.preComposed);
}
// Pick matched pairs for arms and body
const [leftArm, rightArm] = config.arms ? pick(config.arms) : ['', ''];
const [leftBody, rightBody] = pick(config.bodies);
const eye = biasedPick(config.eyes, t);
const mouth = biasedPick(config.mouths, t);
// Cheeks appear ~50% of the time when available
let face;
if (config.cheeks && Math.random() < 0.5) {
const cheek = pick(config.cheeks);
face = `${cheek}${eye}${mouth}${eye}${cheek}`;
} else {
face = `${eye}${mouth}${eye}`;
}
return `${leftArm}${leftBody}${face}${rightBody}${rightArm}`;
}
/**
* Generate a random emoticon for a random emotion.
* @returns {string}
*/
emoticon.random = function () {
const keys = Object.keys(emotions);
return emoticon(pick(keys));
};
/**
* List of all supported emotions.
* @type {string[]}
*/
emoticon.emotions = Object.keys(emotions);
/**
* @private
*/
function pick(arr) {
return arr[Math.floor(Math.random() * arr.length)];
}
/**
* Pick from array biased by intensity.
* intensity 0 = always first element (mildest)
* intensity 1 = always last element (most intense)
* intensity 0.5 = uniform random
* @private
*/
function biasedPick(arr, t) {
if (t === 0.5 || arr.length <= 1) return pick(arr);
const stretch = t < 0.5
? 1 - (1 - 2 * t) * 0.9 // 0.1 → 1.0
: 1 + (2 * t - 1) * 9; // 1.0 → 10
const idx = Math.floor(Math.pow(Math.random(), 1 / stretch) * arr.length);
return arr[Math.min(idx, arr.length - 1)];
}
if (typeof module !== 'undefined' && module.exports) {
module.exports = emoticon;
} else if (typeof window !== 'undefined') {
window.emoticon = emoticon;
}
})();