@baravak/risloo-profile-cli 4.46.3 → 4.70.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/.agents/skills/create-profile/SKILL.md +14 -0
- package/.claude/settings.local.json +1 -3
- package/.claude/skills/create-profile/SKILL.md +80 -0
- package/AGENTS.md +239 -0
- package/CLAUDE.md +2 -185
- package/package.json +1 -1
- package/src/cli-commands/Executor.js +8 -2
- package/src/cli-commands/ExtractExecutor.js +55 -21
- package/src/cli-commands/GiftExecutor.js +1 -0
- package/src/handlebars/importPartials.js +10 -44
- package/src/handlebars/init.js +17 -11
- package/src/publish/json/profiles/BSSI93.json +392 -0
- package/src/publish/json/profiles/FRHPT93.json +2 -2
- package/src/publish/json/profiles/ISKS93.json +288 -0
- package/src/publish/json/profiles/MCMI9A.json +1540 -0
- package/src/publish/json/profiles/NEO93.json +3858 -0
- package/src/publish/json/profiles/NEO9A.json +1159 -1
- package/src/publish/json/profiles/NEO9Q.json +3856 -0
- package/src/publish/json/profiles/NEO9V.json +1157 -0
- package/src/publish/json/profiles/RIASEC9A.json +2775 -0
- package/src/publish/json/profiles/RSI93.json +359 -0
- package/src/samples/AEQ93.js +1 -1
- package/src/samples/AMS93.js +1 -1
- package/src/samples/AMS9A.js +3 -1
- package/src/samples/BAOMEIS93.js +1 -1
- package/src/samples/BEQI93.js +1 -1
- package/src/samples/BSCT93.js +5 -0
- package/src/samples/BSSI93.js +93 -0
- package/src/samples/CAATS93.js +1 -1
- package/src/samples/CERQ93.js +1 -1
- package/src/samples/CRAAS93.js +1 -1
- package/src/samples/DSWLS93.js +1 -1
- package/src/samples/EMSS93.js +1 -1
- package/src/samples/EPQ9A.js +6 -1
- package/src/samples/FACES93.js +6 -0
- package/src/samples/FRHPT93.js +41 -13
- package/src/samples/GMIT93.js +1 -1
- package/src/samples/HPL93.js +1 -1
- package/src/samples/ISKS93.js +62 -0
- package/src/samples/IUS93.js +1 -1
- package/src/samples/JCSI93.js +1 -1
- package/src/samples/JPFQ93.js +5 -0
- package/src/samples/KJGI93.js +1 -1
- package/src/samples/LMIQ93.js +1 -1
- package/src/samples/MMFAD93.js +1 -1
- package/src/samples/MOCI93.js +1 -1
- package/src/samples/NEO93.js +277 -0
- package/src/samples/NEO9A.js +91 -60
- package/src/samples/NEO9Q.js +279 -0
- package/src/samples/NEO9V.js +215 -0
- package/src/samples/OBQ4493.js +1 -1
- package/src/samples/PIES93.js +1 -1
- package/src/samples/PIES9A.js +4 -0
- package/src/samples/PMCIEF93.js +7 -1
- package/src/samples/PSWQ93.js +1 -1
- package/src/samples/RIASEC93.js +1 -1
- package/src/samples/RIASEC9A.js +256 -0
- package/src/samples/RSI93.js +89 -0
- package/src/samples/SASQ93.js +1 -1
- package/src/samples/SDCAQ93.js +1 -1
- package/src/samples/STAIY93.js +1 -1
- package/src/samples/WAQ93.js +1 -1
- package/src/samples/YBOCS93.js +1 -1
- package/src/samples/YPI93.js +5 -1
- package/views/profiles/NEO_long_facets.hbs +125 -0
- package/views/profiles/NEO_main.hbs +150 -0
- package/views/profiles/NEO_short_facets.hbs +82 -0
- package/views/profiles/samples/BSCT93.hbs +17 -17
- package/views/profiles/samples/BSSI93.hbs +102 -0
- package/views/profiles/samples/FRHPT93_1.hbs +568 -87
- package/views/profiles/samples/FRHPT93_2.hbs +90 -76
- package/views/profiles/samples/FRHPT93_3.hbs +2 -2
- package/views/profiles/samples/FRHPT93_4.hbs +2 -2
- package/views/profiles/samples/FRHPT93_5.hbs +103 -0
- package/views/profiles/samples/FRHPT9A.hbs +7 -7
- package/views/profiles/samples/ISKS93.hbs +38 -0
- package/views/profiles/samples/NEO93_1.hbs +14 -0
- package/views/profiles/samples/NEO93_2.hbs +15 -0
- package/views/profiles/samples/NEO93_3.hbs +15 -0
- package/views/profiles/samples/NEO9A.hbs +14 -29
- package/views/profiles/samples/NEO9Q_1.hbs +13 -0
- package/views/profiles/samples/NEO9Q_2.hbs +14 -0
- package/views/profiles/samples/NEO9Q_3.hbs +14 -0
- package/views/profiles/samples/NEO9V_1.hbs +13 -0
- package/views/profiles/samples/NEO9V_2.hbs +3 -0
- package/views/profiles/samples/RIASEC9A_1.hbs +38 -0
- package/views/profiles/samples/RIASEC9A_2.hbs +67 -0
- package/views/profiles/samples/RIASEC9A_3.hbs +93 -0
- package/views/profiles/samples/RSI93.hbs +101 -0
- package/a.json +0 -4805
- package/src/publish/json/profiles/BSCT93_t1.json +0 -512
- package/src/publish/json/profiles/BSCT93_t2.json +0 -512
package/src/samples/FRHPT93.js
CHANGED
|
@@ -19,7 +19,7 @@ const colors = {
|
|
|
19
19
|
|
|
20
20
|
class FRHPT93 extends Profile {
|
|
21
21
|
// Number of pages
|
|
22
|
-
static pages =
|
|
22
|
+
static pages = 5;
|
|
23
23
|
|
|
24
24
|
// Labels of the sample
|
|
25
25
|
labels = {
|
|
@@ -276,15 +276,39 @@ class FRHPT93 extends Profile {
|
|
|
276
276
|
/* calculating its dimensions carefully is of great importance */
|
|
277
277
|
profile: {
|
|
278
278
|
get dimensions() {
|
|
279
|
-
return
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
279
|
+
return [
|
|
280
|
+
{
|
|
281
|
+
width: 895 + 2 * this.padding.x,
|
|
282
|
+
height: 578 + 2 * this.padding.y,
|
|
283
|
+
},
|
|
284
|
+
{
|
|
285
|
+
width: 800 + 2 * this.padding.x,
|
|
286
|
+
height: 657 + 2 * this.padding.y,
|
|
287
|
+
},
|
|
288
|
+
{
|
|
289
|
+
width: 800 + 2 * this.padding.x,
|
|
290
|
+
height: 657 + 2 * this.padding.y,
|
|
291
|
+
},
|
|
292
|
+
{
|
|
293
|
+
width: 800 + 2 * this.padding.x,
|
|
294
|
+
height: 657 + 2 * this.padding.y,
|
|
295
|
+
},
|
|
296
|
+
{
|
|
297
|
+
width: 800 + 2 * this.padding.x,
|
|
298
|
+
height: 657 + 2 * this.padding.y,
|
|
299
|
+
}
|
|
300
|
+
];
|
|
287
301
|
},
|
|
302
|
+
padding: [
|
|
303
|
+
{
|
|
304
|
+
x: 4,
|
|
305
|
+
y: 68,
|
|
306
|
+
},
|
|
307
|
+
{
|
|
308
|
+
x: 52,
|
|
309
|
+
y: 29,
|
|
310
|
+
}
|
|
311
|
+
],
|
|
288
312
|
},
|
|
289
313
|
labels: Object.values(this.labels),
|
|
290
314
|
};
|
|
@@ -324,21 +348,25 @@ class FRHPT93 extends Profile {
|
|
|
324
348
|
})
|
|
325
349
|
}
|
|
326
350
|
let start = 0
|
|
351
|
+
let startx = 0
|
|
327
352
|
validities = validities.map((v,i) => {
|
|
328
353
|
const result ={
|
|
329
354
|
...v,
|
|
330
355
|
start,
|
|
356
|
+
startx,
|
|
331
357
|
last: validities.length - 1 === i
|
|
332
358
|
}
|
|
333
359
|
start += v.length + 54
|
|
360
|
+
startx += v.length + 70
|
|
334
361
|
return result
|
|
335
362
|
})
|
|
336
363
|
const groupList = Object.values(groups).map(r => ({...r, length: r.subs.length}))
|
|
337
364
|
return [
|
|
338
|
-
{ page: 1, titleAppend:' -
|
|
339
|
-
{ page: 2, titleAppend:' -
|
|
340
|
-
{ page: 3, titleAppend:' -
|
|
341
|
-
{ page: 4, titleAppend:' -
|
|
365
|
+
{ page: 1, titleAppend:' - جدول ردهبندی', validityErrors: validities, groups: groupList, indicators },
|
|
366
|
+
{ page: 2, titleAppend:' - 1', groups: groupList, colors, indicators, validityErrors: validities },
|
|
367
|
+
{ page: 3, titleAppend:' - 2', groups: groupList.slice(0, 4).map(rowMap), colors },
|
|
368
|
+
{ page: 4, titleAppend:' - 3', groups: groupList.slice(4, 8).map(rowMap), colors },
|
|
369
|
+
{ page: 5, titleAppend:' - 4', groups: groupList.slice(8, 12).map(rowMap), colors },
|
|
342
370
|
];
|
|
343
371
|
}
|
|
344
372
|
}
|
package/src/samples/GMIT93.js
CHANGED
|
@@ -25,7 +25,7 @@ class GMIT93 extends Profile {
|
|
|
25
25
|
multiProfile: false /* Whether the sample has multiple profiles or not */,
|
|
26
26
|
questions: false /* Determines whether to get questions from inital dataset or not */,
|
|
27
27
|
defaultFields: true /* Determines whether to have default prerequisites in the profile or not */,
|
|
28
|
-
fields: [
|
|
28
|
+
fields: [] /* In case you want to get some additional fields and show in the profile */,
|
|
29
29
|
},
|
|
30
30
|
/* "profile" determines the dimensions of the drawn profile (to be used in svg tag viewbox) */
|
|
31
31
|
/* calculating its dimensions carefully is of great importance */
|
package/src/samples/HPL93.js
CHANGED
|
@@ -24,7 +24,7 @@ class HPL93 extends Profile {
|
|
|
24
24
|
multiProfile: false /* Whether the sample has multiple profiles or not */,
|
|
25
25
|
questions: false /* Determines whether to get questions from inital dataset or not */,
|
|
26
26
|
defaultFields: true /* Determines whether to have default prerequisites in the profile or not */,
|
|
27
|
-
fields: [
|
|
27
|
+
fields: [] /* In case you want to get some additional fields and show in the profile */,
|
|
28
28
|
},
|
|
29
29
|
/* "profile" determines the dimensions of the drawn profile (to be used in svg tag viewbox) */
|
|
30
30
|
/* calculating its dimensions carefully is of great importance */
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
const { Profile } = require("../Profile");
|
|
2
|
+
|
|
3
|
+
class ISKS93 extends Profile {
|
|
4
|
+
static pages = 1;
|
|
5
|
+
|
|
6
|
+
// Single semicircle gauge (0–100 %). `percentage` drives the fill sweep;
|
|
7
|
+
// `raw` + max only feed the gray "X از Y" fraction in the centre.
|
|
8
|
+
// max = 12 items × 5 = 60 (see scoring/ISKS93.py → round(raw / 60, 2)).
|
|
9
|
+
labels = {
|
|
10
|
+
L1: { eng: "raw", max: 60 },
|
|
11
|
+
L2: { eng: "percentage" },
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
profileSpec = {
|
|
15
|
+
sample: {
|
|
16
|
+
name: "مقياس خودشناسی انسجامی",
|
|
17
|
+
multiProfile: false,
|
|
18
|
+
questions: false,
|
|
19
|
+
defaultFields: true,
|
|
20
|
+
fields: [],
|
|
21
|
+
},
|
|
22
|
+
profile: {
|
|
23
|
+
get dimensions() {
|
|
24
|
+
return {
|
|
25
|
+
width: 250 + 2 * this.padding.x, // Chart layer 250 wide
|
|
26
|
+
height: 187 + 2 * this.padding.y, // Chart layer 187 tall
|
|
27
|
+
};
|
|
28
|
+
},
|
|
29
|
+
padding: {
|
|
30
|
+
x: 346.5,
|
|
31
|
+
y: 283.5,
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
labels: Object.values(this.labels),
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
constructor(dataset, options, config = {}) {
|
|
38
|
+
super();
|
|
39
|
+
this._init(dataset, options, config);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
_calcContext() {
|
|
43
|
+
const { dataset } = this;
|
|
44
|
+
const s = dataset.score; // [ {label:{eng:'raw',max:60}, mark}, {label:{eng:'percentage'}, mark} ]
|
|
45
|
+
|
|
46
|
+
const raw = s[0].mark ?? 0;
|
|
47
|
+
const max = s[0].label.max; // 60
|
|
48
|
+
// Clamp to [0,1] so a malformed/out-of-range percentage can never overflow the ring.
|
|
49
|
+
const p = Math.min(Math.max(s[1].mark ?? 0, 0), 1);
|
|
50
|
+
|
|
51
|
+
// Gauge: 0 % at the left base (180°), 100 % at the right base (0°), filling
|
|
52
|
+
// clockwise over the top (sweep = 1, direction = false). The fill's end angle
|
|
53
|
+
// sweeps from left (π) over the top to right (2π): zeta = π·(1 + p).
|
|
54
|
+
const zeta = Math.PI * (1 + p);
|
|
55
|
+
|
|
56
|
+
const total = { raw, max, p, pct: Math.round(p * 100), zeta };
|
|
57
|
+
|
|
58
|
+
return [{ total }];
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
module.exports = ISKS93;
|
package/src/samples/IUS93.js
CHANGED
|
@@ -20,7 +20,7 @@ class IUS93 extends Profile {
|
|
|
20
20
|
multiProfile: false /* Whether the sample has multiple profiles or not */,
|
|
21
21
|
questions: false /* Determines whether to get questions from inital dataset or not */,
|
|
22
22
|
defaultFields: true /* Determines whether to have default prerequisites in the profile or not */,
|
|
23
|
-
fields: [
|
|
23
|
+
fields: [] /* In case you want to get some additional fields and show in the profile */,
|
|
24
24
|
},
|
|
25
25
|
/* "profile" determines the dimensions of the drawn profile (to be used in svg tag viewbox) */
|
|
26
26
|
/* calculating its dimensions carefully is of great importance */
|
package/src/samples/JCSI93.js
CHANGED
|
@@ -24,7 +24,7 @@ class JCSI93 extends Profile {
|
|
|
24
24
|
multiProfile: false /* Whether the sample has multiple profiles or not */,
|
|
25
25
|
questions: false /* Determines whether to get questions from inital dataset or not */,
|
|
26
26
|
defaultFields: true /* Determines whether to have default prerequisites in the profile or not */,
|
|
27
|
-
fields: [
|
|
27
|
+
fields: [] /* In case you want to get some additional fields and show in the profile */,
|
|
28
28
|
},
|
|
29
29
|
/* "profile" determines the dimensions of the drawn profile (to be used in svg tag viewbox) */
|
|
30
30
|
/* calculating its dimensions carefully is of great importance */
|
package/src/samples/JPFQ93.js
CHANGED
|
@@ -4,6 +4,11 @@ class JPFQ93 extends Profile {
|
|
|
4
4
|
// Number of pages
|
|
5
5
|
static pages = 2;
|
|
6
6
|
|
|
7
|
+
static partials = {
|
|
8
|
+
JPFQ93_partial: "samples/JPFQ93_partial.hbs",
|
|
9
|
+
JPFQ93_partial2: "samples/JPFQ93_partial2.hbs",
|
|
10
|
+
};
|
|
11
|
+
|
|
7
12
|
// Labels of the sample
|
|
8
13
|
labels = {
|
|
9
14
|
L1: { eng: "identity", fr: "هویت", fill:"#8B5CF6 ", background:"#EDE9FE", fontColor:"#7C3AED", width: 69},
|
package/src/samples/KJGI93.js
CHANGED
|
@@ -22,7 +22,7 @@ class KJGI93 extends Profile {
|
|
|
22
22
|
multiProfile: false /* Whether the sample has multiple profiles or not */,
|
|
23
23
|
questions: false /* Determines whether to get questions from inital dataset or not */,
|
|
24
24
|
defaultFields: true /* Determines whether to have default prerequisites in the profile or not */,
|
|
25
|
-
fields: [
|
|
25
|
+
fields: [] /* In case you want to get some additional fields and show in the profile */,
|
|
26
26
|
},
|
|
27
27
|
/* "profile" determines the dimensions of the drawn profile (to be used in svg tag viewbox) */
|
|
28
28
|
/* calculating its dimensions carefully is of great importance */
|
package/src/samples/LMIQ93.js
CHANGED
|
@@ -36,7 +36,7 @@ class LMIQ93 extends Profile {
|
|
|
36
36
|
multiProfile: false /* Whether the sample has multiple profiles or not */,
|
|
37
37
|
questions: false /* Determines whether to get questions from inital dataset or not */,
|
|
38
38
|
defaultFields: true /* Determines whether to have default prerequisites in the profile or not */,
|
|
39
|
-
fields: [
|
|
39
|
+
fields: [] /* In case you want to get some additional fields and show in the profile */,
|
|
40
40
|
},
|
|
41
41
|
/* "profile" determines the dimensions of the drawn profile (to be used in svg tag viewbox) */
|
|
42
42
|
/* calculating its dimensions carefully is of great importance */
|
package/src/samples/MMFAD93.js
CHANGED
|
@@ -25,7 +25,7 @@ class MMAFD93 extends Profile {
|
|
|
25
25
|
multiProfile: false /* Whether the sample has multiple profiles or not */,
|
|
26
26
|
questions: false /* Determines whether to get questions from inital dataset or not */,
|
|
27
27
|
defaultFields: true /* Determines whether to have default prerequisites in the profile or not */,
|
|
28
|
-
fields: [
|
|
28
|
+
fields: [] /* In case you want to get some additional fields and show in the profile */,
|
|
29
29
|
},
|
|
30
30
|
/* "profile" determines the dimensions of the drawn profile (to be used in svg tag viewbox) */
|
|
31
31
|
/* calculating its dimensions carefully is of great importance */
|
package/src/samples/MOCI93.js
CHANGED
|
@@ -22,7 +22,7 @@ class MOCI93 extends Profile {
|
|
|
22
22
|
multiProfile: false /* Whether the sample has multiple profiles or not */,
|
|
23
23
|
questions: false /* Determines whether to get questions from inital dataset or not */,
|
|
24
24
|
defaultFields: true /* Determines whether to have default prerequisites in the profile or not */,
|
|
25
|
-
fields: [
|
|
25
|
+
fields: [] /* In case you want to get some additional fields and show in the profile */,
|
|
26
26
|
},
|
|
27
27
|
/* "profile" determines the dimensions of the drawn profile (to be used in svg tag viewbox) */
|
|
28
28
|
/* calculating its dimensions carefully is of great importance */
|
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
const { Profile } = require("../Profile");
|
|
2
|
+
|
|
3
|
+
const DOMAIN_MAX = 192;
|
|
4
|
+
const FACET_MAX = 32;
|
|
5
|
+
const INSIDE_THRESHOLD = 24;
|
|
6
|
+
|
|
7
|
+
const LEVELS = ["", "خیلی پایین", "پایین", "متوسط", "بالا", "خیلی بالا"];
|
|
8
|
+
|
|
9
|
+
const DOMAINS = [
|
|
10
|
+
{ key: "n", fa: "روانآزردهگرایی", letter: "N" },
|
|
11
|
+
{ key: "e", fa: "برونگرایی", letter: "E" },
|
|
12
|
+
{ key: "o", fa: "گشودگی", letter: "O" },
|
|
13
|
+
{ key: "a", fa: "موافق بودن", letter: "A" },
|
|
14
|
+
{ key: "c", fa: "با وجدان بودن", letter: "C" },
|
|
15
|
+
];
|
|
16
|
+
|
|
17
|
+
const FACET_NAMES = {
|
|
18
|
+
n: ["اضطراب", "خصومت", "افسردگی", "کمرویی", "تکانشگری", "آسیبپذیری"],
|
|
19
|
+
e: ["گرم", "معاشرتی", "ابراز وجود", "فعال", "هیجانخواهی", "هیجان مثبت"],
|
|
20
|
+
o: ["تخیل", "زیباییشناسی", "احساسات", "کنشها", "دیدگاهها", "ارزشها"],
|
|
21
|
+
a: ["اعتماد", "رکگویی", "نوعدوستی", "همراهی", "تواضع", "دلرحم"],
|
|
22
|
+
c: ["شایستگی", "نظم و ترتیب", "وظیفهشناسی", "تلاش برای موفقیت", "خویشتنداری", "محتاط"],
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
const COLOR_THEMES = {
|
|
26
|
+
female: {
|
|
27
|
+
light: "#E9D5FF",
|
|
28
|
+
dark: "#7E22CE",
|
|
29
|
+
accent: "#9333EA",
|
|
30
|
+
stroke: "#C084FC",
|
|
31
|
+
},
|
|
32
|
+
male: {
|
|
33
|
+
light: "#BFDBFE",
|
|
34
|
+
dark: "#1D4ED8",
|
|
35
|
+
accent: "#2563EB",
|
|
36
|
+
stroke: "#60A5FA",
|
|
37
|
+
},
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
const FACTOR_LABELS = {};
|
|
41
|
+
for (const { key } of DOMAINS) {
|
|
42
|
+
for (const suffix of ["raw", "score", "level"]) {
|
|
43
|
+
FACTOR_LABELS[`${key}_${suffix}`] = { eng: `${key}_${suffix}` };
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
for (let index = 1; index <= 6; index += 1) {
|
|
47
|
+
for (const suffix of ["raw", "score", "level"]) {
|
|
48
|
+
FACTOR_LABELS[`${key}${index}_${suffix}`] = {
|
|
49
|
+
eng: `${key}${index}_${suffix}`,
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function clamp(value, min, max) {
|
|
56
|
+
const number = Number(value);
|
|
57
|
+
if (!Number.isFinite(number)) return min;
|
|
58
|
+
return Math.min(max, Math.max(min, number));
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function layoutIndicators(indicators) {
|
|
62
|
+
let start = 0;
|
|
63
|
+
|
|
64
|
+
return indicators.map((indicator, index) => {
|
|
65
|
+
const positioned = {
|
|
66
|
+
...indicator,
|
|
67
|
+
start,
|
|
68
|
+
last: index === indicators.length - 1,
|
|
69
|
+
};
|
|
70
|
+
start += indicator.length + 54;
|
|
71
|
+
return positioned;
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
class NEO93 extends Profile {
|
|
76
|
+
static pages = 3;
|
|
77
|
+
|
|
78
|
+
static partials = {
|
|
79
|
+
NEO_main: "NEO_main.hbs",
|
|
80
|
+
NEO_long_facets: "NEO_long_facets.hbs",
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
labels = {
|
|
84
|
+
...FACTOR_LABELS,
|
|
85
|
+
validity: { eng: "validity" },
|
|
86
|
+
options_3_count: { eng: "options_3_count" },
|
|
87
|
+
acquiescence: { eng: "acquiescence" },
|
|
88
|
+
nay_saying: { eng: "nay_saying" },
|
|
89
|
+
random_responding: { eng: "random_responding" },
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
profileSpec = {
|
|
93
|
+
sample: {
|
|
94
|
+
name: "پرسشنامه شخصیت نئو فرم بلند (گروسی)",
|
|
95
|
+
multiProfile: false,
|
|
96
|
+
questions: false,
|
|
97
|
+
defaultFields: true,
|
|
98
|
+
fields: [],
|
|
99
|
+
},
|
|
100
|
+
profile: {
|
|
101
|
+
get dimensions() {
|
|
102
|
+
const [page1, page2, page3] = this.padding;
|
|
103
|
+
return [
|
|
104
|
+
{
|
|
105
|
+
width: 800 + 2 * page1.x,
|
|
106
|
+
height: 674 + 2 * page1.y,
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
width: 811 + 2 * page2.x,
|
|
110
|
+
height: 662 + 2 * page2.y,
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
width: 811 + 2 * page3.x,
|
|
114
|
+
height: 458 + 2 * page3.y,
|
|
115
|
+
},
|
|
116
|
+
];
|
|
117
|
+
},
|
|
118
|
+
padding: [
|
|
119
|
+
{ x: 71.5, y: 40 },
|
|
120
|
+
{ x: 66, y: 46 },
|
|
121
|
+
{ x: 66, y: 148 },
|
|
122
|
+
],
|
|
123
|
+
},
|
|
124
|
+
labels: Object.values(this.labels),
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
constructor(dataset, options, config = {}) {
|
|
128
|
+
super();
|
|
129
|
+
this._init(dataset, options, config);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
_calcContext() {
|
|
133
|
+
const { dataset } = this;
|
|
134
|
+
const scoreByKey = new Map(dataset.score.map((item) => [item.label.eng, item]));
|
|
135
|
+
|
|
136
|
+
// Dataset._extractData drops a numeric zero, so every read deliberately
|
|
137
|
+
// restores it with ?? 0 before converting it to a drawing value.
|
|
138
|
+
const mark = (eng) => scoreByKey.get(eng)?.mark ?? 0;
|
|
139
|
+
const number = (eng) => {
|
|
140
|
+
const value = Number(mark(eng));
|
|
141
|
+
return Number.isFinite(value) ? value : 0;
|
|
142
|
+
};
|
|
143
|
+
const ratio = (eng) => clamp(number(eng), 0, 1);
|
|
144
|
+
|
|
145
|
+
const genderField = (dataset.info.fields ?? []).find((field) => field?.eng === "gender");
|
|
146
|
+
const isFemale = Number(genderField?.user_answered) === 1;
|
|
147
|
+
const gender = isFemale ? "female" : "male";
|
|
148
|
+
const colors = COLOR_THEMES[gender];
|
|
149
|
+
const sharedContext = {
|
|
150
|
+
gender,
|
|
151
|
+
isFemale,
|
|
152
|
+
theme: gender,
|
|
153
|
+
colors,
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
const items = DOMAINS.map(({ key, fa, letter }) => {
|
|
157
|
+
const raw = number(`${key}_raw`);
|
|
158
|
+
const score = ratio(`${key}_score`);
|
|
159
|
+
const level = number(`${key}_level`);
|
|
160
|
+
const percentage = Math.round(score * 100);
|
|
161
|
+
|
|
162
|
+
return {
|
|
163
|
+
key,
|
|
164
|
+
fa,
|
|
165
|
+
letter,
|
|
166
|
+
raw,
|
|
167
|
+
mark: raw,
|
|
168
|
+
max: DOMAIN_MAX,
|
|
169
|
+
score,
|
|
170
|
+
p: score,
|
|
171
|
+
percentage,
|
|
172
|
+
barW: (500 * percentage) / 100,
|
|
173
|
+
inside: percentage >= INSIDE_THRESHOLD,
|
|
174
|
+
level,
|
|
175
|
+
levelText: LEVELS[level] ?? "-",
|
|
176
|
+
};
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
const redErrors = [];
|
|
180
|
+
if (number("validity") === 0) {
|
|
181
|
+
redErrors.push({ text: "پاسخ سؤالات اعتبار", length: 108 });
|
|
182
|
+
}
|
|
183
|
+
if (number("options_3_count") >= 41) {
|
|
184
|
+
redErrors.push({ text: "تعداد پاسخهای «نظری ندارم»", length: 170 });
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
const yellowErrors = [];
|
|
188
|
+
if (number("acquiescence") === 1) {
|
|
189
|
+
yellowErrors.push({ text: "احتمال تمایل به پاسخ مثبت", length: 155 });
|
|
190
|
+
}
|
|
191
|
+
if (number("nay_saying") === 1) {
|
|
192
|
+
yellowErrors.push({ text: "احتمال تمایل به پاسخ منفی", length: 143 });
|
|
193
|
+
}
|
|
194
|
+
if (number("random_responding") === 1) {
|
|
195
|
+
yellowErrors.push({ text: "احتمال پاسخ تصادفی", length: 105 });
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
const blocks = DOMAINS.map(({ key, fa, letter }, domainIndex) => {
|
|
199
|
+
const raw = number(`${key}_raw`);
|
|
200
|
+
const score = ratio(`${key}_score`);
|
|
201
|
+
const level = number(`${key}_level`);
|
|
202
|
+
const percentage = Math.round(score * 100);
|
|
203
|
+
|
|
204
|
+
const facets = FACET_NAMES[key].map((facetName, facetIndex) => {
|
|
205
|
+
const factorKey = `${key}${facetIndex + 1}`;
|
|
206
|
+
const facetRaw = number(`${factorKey}_raw`);
|
|
207
|
+
const facetScore = ratio(`${factorKey}_score`);
|
|
208
|
+
const facetLevel = number(`${factorKey}_level`);
|
|
209
|
+
const facetPercentage = Math.round(facetScore * 100);
|
|
210
|
+
|
|
211
|
+
return {
|
|
212
|
+
key: factorKey,
|
|
213
|
+
fa: facetName,
|
|
214
|
+
raw: facetRaw,
|
|
215
|
+
mark: facetRaw,
|
|
216
|
+
max: FACET_MAX,
|
|
217
|
+
score: facetScore,
|
|
218
|
+
p: facetScore,
|
|
219
|
+
percentage: facetPercentage,
|
|
220
|
+
barW: (300 * facetPercentage) / 100,
|
|
221
|
+
inside: facetPercentage >= INSIDE_THRESHOLD,
|
|
222
|
+
level: facetLevel,
|
|
223
|
+
levelText: LEVELS[facetLevel] ?? "-",
|
|
224
|
+
};
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
return {
|
|
228
|
+
key,
|
|
229
|
+
fa,
|
|
230
|
+
letter,
|
|
231
|
+
raw,
|
|
232
|
+
mark: raw,
|
|
233
|
+
max: DOMAIN_MAX,
|
|
234
|
+
score,
|
|
235
|
+
p: score,
|
|
236
|
+
percentage,
|
|
237
|
+
barW: (500 * percentage) / 100,
|
|
238
|
+
inside: percentage >= INSIDE_THRESHOLD,
|
|
239
|
+
level,
|
|
240
|
+
levelText: LEVELS[level] ?? "-",
|
|
241
|
+
isPrimary: domainIndex % 2 === 0,
|
|
242
|
+
isBlue: domainIndex % 2 === 0,
|
|
243
|
+
facetOffsetY: 0,
|
|
244
|
+
facets,
|
|
245
|
+
};
|
|
246
|
+
});
|
|
247
|
+
|
|
248
|
+
return [
|
|
249
|
+
{
|
|
250
|
+
...sharedContext,
|
|
251
|
+
page: 1,
|
|
252
|
+
titleAppend: "",
|
|
253
|
+
items,
|
|
254
|
+
redErrors: layoutIndicators(redErrors),
|
|
255
|
+
yellowErrors: layoutIndicators(yellowErrors),
|
|
256
|
+
showRed: redErrors.length > 0,
|
|
257
|
+
showYellow: yellowErrors.length > 0,
|
|
258
|
+
},
|
|
259
|
+
{
|
|
260
|
+
...sharedContext,
|
|
261
|
+
page: 2,
|
|
262
|
+
titleAppend: " - 2",
|
|
263
|
+
blocks: blocks.slice(0, 3),
|
|
264
|
+
gridBottom: 658.5,
|
|
265
|
+
},
|
|
266
|
+
{
|
|
267
|
+
...sharedContext,
|
|
268
|
+
page: 3,
|
|
269
|
+
titleAppend: " - 3",
|
|
270
|
+
blocks: blocks.slice(3, 5),
|
|
271
|
+
gridBottom: 454.5,
|
|
272
|
+
},
|
|
273
|
+
];
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
module.exports = NEO93;
|