@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/PIES9A.js
CHANGED
|
@@ -24,6 +24,10 @@ const customConfig = {
|
|
|
24
24
|
// This profile is partially identical to PIES93
|
|
25
25
|
|
|
26
26
|
class PIES9A extends PIES93 {
|
|
27
|
+
static partials = {
|
|
28
|
+
PIES93: "samples/PIES93.hbs",
|
|
29
|
+
};
|
|
30
|
+
|
|
27
31
|
constructor(dataset, options, config = customConfig) {
|
|
28
32
|
super(dataset, options, config);
|
|
29
33
|
}
|
package/src/samples/PMCIEF93.js
CHANGED
|
@@ -1,12 +1,18 @@
|
|
|
1
1
|
const { Profile, FS } = require("../Profile");
|
|
2
2
|
const JPFQ93 = require("./JPFQ93");
|
|
3
3
|
const FACES93 = require("./FACES93");
|
|
4
|
-
const Handlebars = require("handlebars");
|
|
5
4
|
|
|
6
5
|
class PMCIEF93 extends Profile {
|
|
7
6
|
// Number of pages
|
|
8
7
|
static pages = 1;
|
|
9
8
|
|
|
9
|
+
static partials = {
|
|
10
|
+
JPFQ93_partial: "samples/JPFQ93_partial.hbs",
|
|
11
|
+
FACES93_1_partial: "samples/FACES93_1_partial.hbs",
|
|
12
|
+
FACES93_2_1_partial: "samples/FACES93_2_1_partial.hbs",
|
|
13
|
+
FACES93_2_2_partial: "samples/FACES93_2_2_partial.hbs",
|
|
14
|
+
};
|
|
15
|
+
|
|
10
16
|
// Labels of the sample
|
|
11
17
|
labels = {
|
|
12
18
|
L1 : {"eng" : "axis_2_raw", "fr" : ""},
|
package/src/samples/PSWQ93.js
CHANGED
|
@@ -19,7 +19,7 @@ class PSWQ93 extends Profile {
|
|
|
19
19
|
multiProfile: false /* Whether the sample has multiple profiles or not */,
|
|
20
20
|
questions: false /* Determines whether to get questions from inital dataset or not */,
|
|
21
21
|
defaultFields: true /* Determines whether to have default prerequisites in the profile or not */,
|
|
22
|
-
fields: [
|
|
22
|
+
fields: [] /* In case you want to get some additional fields and show in the profile */,
|
|
23
23
|
},
|
|
24
24
|
/* "profile" determines the dimensions of the drawn profile (to be used in svg tag viewbox) */
|
|
25
25
|
/* calculating its dimensions carefully is of great importance */
|
package/src/samples/RIASEC93.js
CHANGED
|
@@ -23,7 +23,7 @@ class RIASEC93 extends Profile {
|
|
|
23
23
|
multiProfile: false /* Whether the sample has multiple profiles or not */,
|
|
24
24
|
questions: true /* Determines whether to get questions from inital dataset or not */,
|
|
25
25
|
defaultFields: true /* Determines whether to have default prerequisites in the profile or not */,
|
|
26
|
-
fields: [
|
|
26
|
+
fields: [] /* In case you want to get some additional fields and show in the profile */,
|
|
27
27
|
},
|
|
28
28
|
/* "profile" determines the dimensions of the drawn profile (to be used in svg tag viewbox) */
|
|
29
29
|
/* calculating its dimensions carefully is of great importance */
|
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
const { Profile, Mappings } = require("../Profile");
|
|
2
|
+
|
|
3
|
+
class RIASEC9A extends Profile {
|
|
4
|
+
// Number of pages
|
|
5
|
+
static pages = 3;
|
|
6
|
+
|
|
7
|
+
// Labels of the sample
|
|
8
|
+
labels = {
|
|
9
|
+
L1_0: { eng: "realistic_raw", fr: "واقعگرا", short: "و", enShort:"R" },
|
|
10
|
+
L1_1: { eng: "realistic_percentage" },
|
|
11
|
+
L1_2: { eng: "realistic_rank" },
|
|
12
|
+
L1_3: { eng: "realistic_congruence" },
|
|
13
|
+
L1_4: { eng: "realistic_calibrated" },
|
|
14
|
+
L2_0: { eng: "investigative_raw", fr: "جستجوگر", short: "ج", enShort:"I" },
|
|
15
|
+
L2_1: { eng: "investigative_percentage" },
|
|
16
|
+
L2_2: { eng: "investigative_rank" },
|
|
17
|
+
L2_3: { eng: "investigative_congruence" },
|
|
18
|
+
L2_4: { eng: "investigative_calibrated" },
|
|
19
|
+
L3_0: { eng: "artistic_raw", fr: "هنری", short: "هـ", enShort:"A" },
|
|
20
|
+
L3_1: { eng: "artistic_percentage" },
|
|
21
|
+
L3_2: { eng: "artistic_rank" },
|
|
22
|
+
L3_3: { eng: "artistic_congruence" },
|
|
23
|
+
L3_4: { eng: "artistic_calibrated" },
|
|
24
|
+
L4_0: { eng: "social_raw", fr: "اجتماعی", short: "الف", enShort:"S" },
|
|
25
|
+
L4_1: { eng: "social_percentage" },
|
|
26
|
+
L4_2: { eng: "social_rank" },
|
|
27
|
+
L4_3: { eng: "social_congruence" },
|
|
28
|
+
L4_4: { eng: "social_calibrated" },
|
|
29
|
+
L5_0: { eng: "enterprising_raw", fr: "متهور", short: "م", enShort:"E" },
|
|
30
|
+
L5_1: { eng: "enterprising_percentage" },
|
|
31
|
+
L5_2: { eng: "enterprising_rank" },
|
|
32
|
+
L5_3: { eng: "enterprising_congruence" },
|
|
33
|
+
L5_4: { eng: "enterprising_calibrated" },
|
|
34
|
+
L6_0: { eng: "conventional_raw", fr: "قراردادی", short: "ق", enShort:"C" },
|
|
35
|
+
L6_1: { eng: "conventional_percentage" },
|
|
36
|
+
L6_2: { eng: "conventional_rank" },
|
|
37
|
+
L6_3: { eng: "conventional_congruence" },
|
|
38
|
+
L6_4: { eng: "conventional_calibrated" },
|
|
39
|
+
Llt: { eng: "code_letters_abbr" },
|
|
40
|
+
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
profileSpec = {
|
|
44
|
+
/* "sample" determines some important info about the sample and profile */
|
|
45
|
+
/* Default prerequisites: 1. gender, 2. age, 3. education */
|
|
46
|
+
/* "prerequisites" is synonym to "fields" in our program */
|
|
47
|
+
sample: {
|
|
48
|
+
name: "پرسشنامه رغبتسنج تحصیلی - شغلی هالند - ویرایش حوزه" /* Name of the sample */,
|
|
49
|
+
multiProfile: false /* Whether the sample has multiple profiles or not */,
|
|
50
|
+
questions: true /* Determines whether to get questions from inital dataset or not */,
|
|
51
|
+
defaultFields: true /* Determines whether to have default prerequisites in the profile or not */,
|
|
52
|
+
fields: [] /* In case you want to get some additional fields and show in the profile */,
|
|
53
|
+
},
|
|
54
|
+
/* "profile" determines the dimensions of the drawn profile (to be used in svg tag viewbox) */
|
|
55
|
+
/* calculating its dimensions carefully is of great importance */
|
|
56
|
+
profile: {
|
|
57
|
+
get dimensions() {
|
|
58
|
+
return [
|
|
59
|
+
{
|
|
60
|
+
width: 602 + 2 * this.padding[0].x,
|
|
61
|
+
height: 595 + 2 * this.padding[0].y,
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
width: 592 + 2 * this.padding[1].x,
|
|
65
|
+
height: 523 + 2 * this.padding[1].y,
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
width: 686 + 2 * this.padding[2].x,
|
|
69
|
+
height: 404 + 2 * this.padding[2].y,
|
|
70
|
+
},
|
|
71
|
+
];
|
|
72
|
+
},
|
|
73
|
+
padding: [
|
|
74
|
+
{
|
|
75
|
+
x: 0,
|
|
76
|
+
y: 51,
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
x: 147,
|
|
80
|
+
y: 96,
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
x: 109,
|
|
84
|
+
y: 155,
|
|
85
|
+
},
|
|
86
|
+
],
|
|
87
|
+
},
|
|
88
|
+
/* "items" is the general term used for independent data elements to be drawn in the profile */
|
|
89
|
+
items: {
|
|
90
|
+
offsetY: 32 /* Horizontal offset between two top items */,
|
|
91
|
+
get distanceY() {
|
|
92
|
+
return this.offsetY + this.rect.body.height;
|
|
93
|
+
} /* Horizontal distance between two top items */,
|
|
94
|
+
maxValue: 50 /* Maximum value of items */,
|
|
95
|
+
rect: {
|
|
96
|
+
base: {
|
|
97
|
+
height: 4,
|
|
98
|
+
},
|
|
99
|
+
body: {
|
|
100
|
+
height: 8,
|
|
101
|
+
brs: {
|
|
102
|
+
tl: 0,
|
|
103
|
+
tr: 4,
|
|
104
|
+
bl: 0,
|
|
105
|
+
br: 0,
|
|
106
|
+
},
|
|
107
|
+
},
|
|
108
|
+
widthCoeff: 500 / 56,
|
|
109
|
+
opacityMappings: new Mappings()
|
|
110
|
+
.addMapping("1-10", 0.6)
|
|
111
|
+
.addMapping("11-20", 0.7)
|
|
112
|
+
.addMapping("21-30", 0.8)
|
|
113
|
+
.addMapping("31-40", 0.9)
|
|
114
|
+
.addMapping("41-50", 1) /* Opacity mapping for marks */,
|
|
115
|
+
},
|
|
116
|
+
},
|
|
117
|
+
/* "labels" part which has to be provided for each profile */
|
|
118
|
+
labels: Object.values(this.labels),
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
constructor(dataset, options, config = {}) {
|
|
122
|
+
super();
|
|
123
|
+
this._init(dataset, options, config);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
_calcContext() {
|
|
127
|
+
const {
|
|
128
|
+
spec: { parameters: spec },
|
|
129
|
+
dataset,
|
|
130
|
+
} = this;
|
|
131
|
+
|
|
132
|
+
// Deconstructing the Spec of the Profile
|
|
133
|
+
const { items: itemsSpec } = spec;
|
|
134
|
+
const Items = [];
|
|
135
|
+
for (let i = 0; i < 30; i += 5) {
|
|
136
|
+
const item = dataset.score[i];
|
|
137
|
+
item.percentage = dataset.score[i + 1].mark ?? 0;
|
|
138
|
+
item.rank = dataset.score[i + 2].mark ?? 0;
|
|
139
|
+
item.congruence = dataset.score[i + 3].mark ?? 0;
|
|
140
|
+
item.calibrated = dataset.score[i + 4].mark ?? 0;
|
|
141
|
+
Items.push(item);
|
|
142
|
+
}
|
|
143
|
+
const map = new Map(Items.map(i => [i.label.enShort, i.label.short]))
|
|
144
|
+
const reportMap = dataset.score[30].mark.split('-').map(r => {
|
|
145
|
+
return r.split(',').map(key => map.get(key)).join(' - ')
|
|
146
|
+
}).reverse()
|
|
147
|
+
// Gathering required info for page 1 items
|
|
148
|
+
const items = Items.map((data) => ({
|
|
149
|
+
label: data.label,
|
|
150
|
+
mark: data.mark,
|
|
151
|
+
width: data.mark * itemsSpec.rect.widthCoeff,
|
|
152
|
+
opacity: itemsSpec.rect.opacityMappings.map(data.mark),
|
|
153
|
+
percentage: data.percentage,
|
|
154
|
+
rank: data.rank,
|
|
155
|
+
congruence: data.congruence,
|
|
156
|
+
calibrated: data.calibrated,
|
|
157
|
+
}));
|
|
158
|
+
const questionItems = [
|
|
159
|
+
{
|
|
160
|
+
label: "فعالیتها",
|
|
161
|
+
marks: Array(6)
|
|
162
|
+
.fill(11)
|
|
163
|
+
.map((n, index) =>
|
|
164
|
+
dataset.questions
|
|
165
|
+
.slice(index * n, (index + 1) * n)
|
|
166
|
+
.reduce((sum, { user_answered }) => sum + (+user_answered !== 2 ? 1 : 0), 0)
|
|
167
|
+
),
|
|
168
|
+
},
|
|
169
|
+
{
|
|
170
|
+
label: "تجربهها",
|
|
171
|
+
marks: Array(6)
|
|
172
|
+
.fill(11)
|
|
173
|
+
.map((n, index) =>
|
|
174
|
+
dataset.questions
|
|
175
|
+
.slice(66 + index * n, 66 + (index + 1) * n)
|
|
176
|
+
.reduce((sum, { user_answered }) => sum + (+user_answered !== 2 ? 1 : 0), 0)
|
|
177
|
+
),
|
|
178
|
+
},
|
|
179
|
+
{
|
|
180
|
+
label: "مشاغل",
|
|
181
|
+
marks: Array(6)
|
|
182
|
+
.fill(14)
|
|
183
|
+
.map((n, index) =>
|
|
184
|
+
dataset.questions
|
|
185
|
+
.slice(132 + index * n, 132 + (index + 1) * n)
|
|
186
|
+
.reduce((sum, { user_answered }) => sum + (+user_answered !== 2 ? 1 : 0), 0)
|
|
187
|
+
),
|
|
188
|
+
},
|
|
189
|
+
{
|
|
190
|
+
label: "خودسنجی ۱",
|
|
191
|
+
marks: dataset.questions.slice(216, 216 + 6).map((q) => +q.user_answered),
|
|
192
|
+
},
|
|
193
|
+
{
|
|
194
|
+
label: "خودسنجی ۲",
|
|
195
|
+
marks: dataset.questions.slice(222, 222 + 6).map((q) => +q.user_answered),
|
|
196
|
+
},
|
|
197
|
+
];
|
|
198
|
+
const itemObject = {};
|
|
199
|
+
let last = undefined;
|
|
200
|
+
const list = items
|
|
201
|
+
.map((item) => item.mark)
|
|
202
|
+
.sort((a, b) => b - a)
|
|
203
|
+
.filter((mark, i) => {
|
|
204
|
+
if (i <= 2) {
|
|
205
|
+
last = mark;
|
|
206
|
+
return true;
|
|
207
|
+
}
|
|
208
|
+
if (mark === last) {
|
|
209
|
+
return true;
|
|
210
|
+
} else {
|
|
211
|
+
return false;
|
|
212
|
+
}
|
|
213
|
+
});
|
|
214
|
+
items.forEach((item) => (itemObject[item.label.eng.slice(0, -4)] = item));
|
|
215
|
+
const itemRadians = [
|
|
216
|
+
itemObject.artistic,
|
|
217
|
+
itemObject.social,
|
|
218
|
+
itemObject.enterprising,
|
|
219
|
+
itemObject.conventional,
|
|
220
|
+
itemObject.realistic,
|
|
221
|
+
itemObject.investigative,
|
|
222
|
+
].map((item, i) => {
|
|
223
|
+
const mark = ((item.mark ?? 0) * 207) / 56;
|
|
224
|
+
item.rad = pointsToCoordinates(mark - 14, i * 60);
|
|
225
|
+
item.bold = list.includes(item.mark);
|
|
226
|
+
item.percentageText = Math.floor(item.percentage * 100);
|
|
227
|
+
return item;
|
|
228
|
+
});
|
|
229
|
+
return [
|
|
230
|
+
{
|
|
231
|
+
items: [...items].sort((item1, item2) => item2.mark - item1.mark),
|
|
232
|
+
questionItems,
|
|
233
|
+
titleAppend: " - ۱",
|
|
234
|
+
},
|
|
235
|
+
{
|
|
236
|
+
itemRadians,
|
|
237
|
+
titleAppend: " - ۲",
|
|
238
|
+
},
|
|
239
|
+
{
|
|
240
|
+
items: [...items].reverse(),
|
|
241
|
+
reportMap,
|
|
242
|
+
titleAppend: " - ۳",
|
|
243
|
+
},
|
|
244
|
+
];
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
function pointsToCoordinates(mark, angle) {
|
|
249
|
+
angle = (angle * Math.PI) / 180;
|
|
250
|
+
const start = [296 + 31 * Math.cos(angle), 261.5 + 31 * Math.sin(angle)];
|
|
251
|
+
const end = [start[0] + mark * Math.cos(angle), start[1] + mark * Math.sin(angle)];
|
|
252
|
+
const value = [end[0] + 12 * Math.cos(angle), end[1] + 12 * Math.sin(angle)];
|
|
253
|
+
return { start, end, value };
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
module.exports = RIASEC9A;
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
const { Profile } = require("../Profile");
|
|
2
|
+
|
|
3
|
+
class RSI93 extends Profile {
|
|
4
|
+
static pages = 1;
|
|
5
|
+
|
|
6
|
+
// RSI93 — "تصور از خدا" (خسروی). Chart has two halves:
|
|
7
|
+
// • Left : two mirrored donut-ring gauges (pink = negative image, green = positive image).
|
|
8
|
+
// • Right : two horizontal bars (god_in_life, god_cares) — the two sub-factors whose
|
|
9
|
+
// sum is the positive-image score (per the designer).
|
|
10
|
+
// Maxes = items × 5 (scoring/RSI93.py → round(raw / (count·5), 2)):
|
|
11
|
+
// negative_image 6→30, positive_image 21→105, god_in_life 11→55, god_cares 10→50.
|
|
12
|
+
// Each factor exposes _raw + _percentage; we read raw for the "X از Y" fraction and the
|
|
13
|
+
// 0–1 percentage for the fill sweep + the "٪ NN" label (designer: "محاسبه با درصد").
|
|
14
|
+
labels = {
|
|
15
|
+
L1_1: { eng: "negative_image_raw", max: 30 },
|
|
16
|
+
L1_2: { eng: "negative_image_percentage" },
|
|
17
|
+
|
|
18
|
+
L2_1: { eng: "positive_image_raw", max: 105 },
|
|
19
|
+
L2_2: { eng: "positive_image_percentage" },
|
|
20
|
+
|
|
21
|
+
L3_1: { eng: "god_in_life_raw", max: 55, title: "حضور خدا در زندگی" },
|
|
22
|
+
L3_2: { eng: "god_in_life_percentage" },
|
|
23
|
+
|
|
24
|
+
L4_1: { eng: "god_cares_raw", max: 50, title: "مراقبت خداوند" },
|
|
25
|
+
L4_2: { eng: "god_cares_percentage" },
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
profileSpec = {
|
|
29
|
+
sample: {
|
|
30
|
+
name: "پرسشنامه تصور از خدا (خسروی)",
|
|
31
|
+
multiProfile: false,
|
|
32
|
+
questions: false,
|
|
33
|
+
defaultFields: true,
|
|
34
|
+
fields: [],
|
|
35
|
+
},
|
|
36
|
+
profile: {
|
|
37
|
+
get dimensions() {
|
|
38
|
+
return {
|
|
39
|
+
width: 740 + 2 * this.padding.x, // Chart layer 740 wide → 943 page
|
|
40
|
+
height: 318 + 2 * this.padding.y, // Chart layer 318 tall → 754 page
|
|
41
|
+
};
|
|
42
|
+
},
|
|
43
|
+
padding: {
|
|
44
|
+
x: 101.5, // (943 − 740) / 2
|
|
45
|
+
y: 218, // (754 − 318) / 2
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
labels: Object.values(this.labels),
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
constructor(dataset, options, config = {}) {
|
|
52
|
+
super();
|
|
53
|
+
this._init(dataset, options, config);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
_calcContext() {
|
|
57
|
+
const { dataset } = this;
|
|
58
|
+
const s = dataset.score;
|
|
59
|
+
|
|
60
|
+
const neg = packItem(s[0], s[1]); // negative image → left ring (pink)
|
|
61
|
+
const pos = packItem(s[2], s[3]); // positive image → right ring (green)
|
|
62
|
+
|
|
63
|
+
// Ring fill sweep. Both rings: 0 % at the bottom base (90°), 100 % at the top.
|
|
64
|
+
// • Left ring fills clockwise up the LEFT (increasing θ): zeta = π/2 + p·π (direction false).
|
|
65
|
+
// • Right ring fills counter-cw up the RIGHT (decreasing θ): zeta = π/2 − p·π (direction true).
|
|
66
|
+
neg.zeta = Math.PI / 2 + neg.p * Math.PI;
|
|
67
|
+
pos.zeta = Math.PI / 2 - pos.p * Math.PI;
|
|
68
|
+
|
|
69
|
+
const bars = [
|
|
70
|
+
packItem(s[4], s[5]), // god_in_life
|
|
71
|
+
packItem(s[6], s[7]), // god_cares
|
|
72
|
+
];
|
|
73
|
+
|
|
74
|
+
return [{ neg, pos, bars }];
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// Merge a factor's _raw and _percentage score entries into one drawing item.
|
|
79
|
+
function packItem(raw, percentage) {
|
|
80
|
+
return {
|
|
81
|
+
label: raw.label,
|
|
82
|
+
max: raw.label.max,
|
|
83
|
+
mark: raw.mark ?? 0,
|
|
84
|
+
percentage: Math.round((percentage.mark ?? 0) * 100),
|
|
85
|
+
p: percentage.mark ?? 0,
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
module.exports = RSI93;
|
package/src/samples/SASQ93.js
CHANGED
|
@@ -19,7 +19,7 @@ class SASQ93 extends Profile {
|
|
|
19
19
|
multiProfile: false /* Whether the sample has multiple profiles or not */,
|
|
20
20
|
questions: false /* Determines whether to get questions from inital dataset or not */,
|
|
21
21
|
defaultFields: true /* Determines whether to have default prerequisites in the profile or not */,
|
|
22
|
-
fields: [
|
|
22
|
+
fields: [] /* In case you want to get some additional fields and show in the profile */,
|
|
23
23
|
},
|
|
24
24
|
/* "profile" determines the dimensions of the drawn profile (to be used in svg tag viewbox) */
|
|
25
25
|
/* calculating its dimensions carefully is of great importance */
|
package/src/samples/SDCAQ93.js
CHANGED
|
@@ -23,7 +23,7 @@ class SDCAQ93 extends Profile {
|
|
|
23
23
|
multiProfile: false /* Whether the sample has multiple profiles or not */,
|
|
24
24
|
questions: false /* Determines whether to get questions from inital dataset or not */,
|
|
25
25
|
defaultFields: true /* Determines whether to have default prerequisites in the profile or not */,
|
|
26
|
-
fields: [
|
|
26
|
+
fields: [] /* In case you want to get some additional fields and show in the profile */,
|
|
27
27
|
},
|
|
28
28
|
/* "profile" determines the dimensions of the drawn profile (to be used in svg tag viewbox) */
|
|
29
29
|
/* calculating its dimensions carefully is of great importance */
|
package/src/samples/STAIY93.js
CHANGED
|
@@ -19,7 +19,7 @@ class STAIY93 extends Profile {
|
|
|
19
19
|
multiProfile: false /* Whether the sample has multiple profiles or not */,
|
|
20
20
|
questions: false /* Determines whether to get questions from inital dataset or not */,
|
|
21
21
|
defaultFields: true /* Determines whether to have default prerequisites in the profile or not */,
|
|
22
|
-
fields: [
|
|
22
|
+
fields: [] /* In case you want to get some additional fields and show in the profile */,
|
|
23
23
|
},
|
|
24
24
|
/* "profile" determines the dimensions of the drawn profile (to be used in svg tag viewbox) */
|
|
25
25
|
/* calculating its dimensions carefully is of great importance */
|
package/src/samples/WAQ93.js
CHANGED
|
@@ -25,7 +25,7 @@ class WAQ93 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/YBOCS93.js
CHANGED
|
@@ -398,7 +398,7 @@ class YBOCS93 extends Profile {
|
|
|
398
398
|
multiProfile: true /* Whether the sample has multiple profiles or not */,
|
|
399
399
|
questions: true /* Determines whether to get questions from inital dataset or not */,
|
|
400
400
|
defaultFields: true /* Determines whether to have default prerequisites in the profile or not */,
|
|
401
|
-
fields: [
|
|
401
|
+
fields: [] /* In case you want to get some additional fields and show in the profile */,
|
|
402
402
|
},
|
|
403
403
|
/* "profile" determines the dimensions of the drawn profile (to be used in svg tag viewbox) */
|
|
404
404
|
/* calculating its dimensions carefully is of great importance */
|
package/src/samples/YPI93.js
CHANGED
|
@@ -3,6 +3,10 @@ class YPI93 extends Profile {
|
|
|
3
3
|
// Number of pages
|
|
4
4
|
static pages = 2;
|
|
5
5
|
|
|
6
|
+
static partials = {
|
|
7
|
+
YPI93_factors: "samples/YPI93_factors.hbs",
|
|
8
|
+
};
|
|
9
|
+
|
|
6
10
|
// Labels of the sample
|
|
7
11
|
labels = {
|
|
8
12
|
L1_fs: { eng: "ab_father_score", group: 1},
|
|
@@ -347,4 +351,4 @@ const Items = {
|
|
|
347
351
|
60:f15,61:f15,62:f15,63:f15,64:f15,
|
|
348
352
|
65:f16,66:f16,67:f16,68:f16,
|
|
349
353
|
69:f17,70:f17,71:f17,72:f17
|
|
350
|
-
}
|
|
354
|
+
}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
<defs>
|
|
2
|
+
<linearGradient id="neoLongPrimary" x1="0" y1="0" x2="1" y2="0">
|
|
3
|
+
<stop stop-color="{{colors.light}}"/>
|
|
4
|
+
<stop offset="1" stop-color="{{colors.dark}}"/>
|
|
5
|
+
</linearGradient>
|
|
6
|
+
<linearGradient id="neoLongSecondary" x1="0" y1="0" x2="1" y2="0">
|
|
7
|
+
<stop stop-color="#C7D2FE"/>
|
|
8
|
+
<stop offset="1" stop-color="#4338CA"/>
|
|
9
|
+
</linearGradient>
|
|
10
|
+
<clipPath id="neoLongBarClip">
|
|
11
|
+
{{bar trackW 16 (object tl=0 bl=0 tr=2 br=2) (toRad 0)}}
|
|
12
|
+
</clipPath>
|
|
13
|
+
<filter id="neoLongSplit" x="352" y="{{math gridTop '-' 3.5}}" width="7" height="{{math (math gridBottom '-' gridTop) '+' 7}}" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
|
14
|
+
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
|
15
|
+
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
|
|
16
|
+
<feOffset dx="1"/>
|
|
17
|
+
<feGaussianBlur stdDeviation="1.5"/>
|
|
18
|
+
<feComposite in2="hardAlpha" operator="out"/>
|
|
19
|
+
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0"/>
|
|
20
|
+
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1"/>
|
|
21
|
+
<feBlend mode="normal" in="SourceGraphic" in2="effect1" result="shape"/>
|
|
22
|
+
</filter>
|
|
23
|
+
</defs>
|
|
24
|
+
|
|
25
|
+
<g transform="translate({{padding.x}}, {{padding.y}})">
|
|
26
|
+
{{#if tAxis}}
|
|
27
|
+
<text x="374.5" y="9" font-size="12" font-weight="400" fill="#94A3B8" text-anchor="middle">20</text>
|
|
28
|
+
<text x="464.5" y="9" font-size="12" font-weight="400" fill="#94A3B8" text-anchor="middle">35</text>
|
|
29
|
+
<text x="524.5" y="9" font-size="12" font-weight="400" fill="#94A3B8" text-anchor="middle">45</text>
|
|
30
|
+
<text x="584.5" y="9" font-size="12" font-weight="400" fill="#94A3B8" text-anchor="middle">55</text>
|
|
31
|
+
<text x="644.5" y="9" font-size="12" font-weight="400" fill="#94A3B8" text-anchor="middle">65</text>
|
|
32
|
+
<text x="734.5" y="9" font-size="12" font-weight="400" fill="#94A3B8" text-anchor="middle">80</text>
|
|
33
|
+
|
|
34
|
+
<text x="419.5" y="23" font-size="12" font-weight="400" fill="#94A3B8" text-anchor="middle">بسیار پایین</text>
|
|
35
|
+
<text x="494.5" y="23" font-size="12" font-weight="400" fill="#94A3B8" text-anchor="middle">پایین</text>
|
|
36
|
+
<text x="554.5" y="23" font-size="12" font-weight="400" fill="#94A3B8" text-anchor="middle">طبیعی</text>
|
|
37
|
+
<text x="614.5" y="23" font-size="12" font-weight="400" fill="#94A3B8" text-anchor="middle">بالا</text>
|
|
38
|
+
<text x="689.5" y="23" font-size="12" font-weight="400" fill="#94A3B8" text-anchor="middle">بسیار بالا</text>
|
|
39
|
+
{{else}}
|
|
40
|
+
<text x="354.5" y="14" font-size="12" font-weight="400" fill="#94A3B8" text-anchor="middle">0</text>
|
|
41
|
+
<text x="504.5" y="14" font-size="12" font-weight="400" fill="#94A3B8" text-anchor="middle">50 ٪</text>
|
|
42
|
+
<text x="654.5" y="14" font-size="12" font-weight="400" fill="#94A3B8" text-anchor="start">100 ٪</text>
|
|
43
|
+
{{/if}}
|
|
44
|
+
|
|
45
|
+
<text x="{{rawCenter}}" y="9" font-size="12" font-weight="400" fill="#64748B" text-anchor="middle">نمره خام</text>
|
|
46
|
+
<text x="{{rawCenter}}" y="23" font-size="12" font-weight="400" fill="#64748B" text-anchor="middle">از 32</text>
|
|
47
|
+
|
|
48
|
+
{{#each blocks as |block blockIndex|}}
|
|
49
|
+
<g transform="translate(0, {{math blockIndex '*' 204}})">
|
|
50
|
+
{{#if block.isBlue}}
|
|
51
|
+
<rect y="{{../cardY}}" width="811" height="188" rx="8" fill="#F8FAFC"/>
|
|
52
|
+
<g transform="translate(0, {{../cardY}})">
|
|
53
|
+
{{bar 180 188 (object tr=0 br=0 tl=8 bl=8) (toRad 0) fill='#F1F5F9'}}
|
|
54
|
+
</g>
|
|
55
|
+
{{/if}}
|
|
56
|
+
|
|
57
|
+
<text x="90" y="{{math ../cardY '+' 48}}" dy=".3em" font-size="12" font-weight="500" fill="#64748B" text-anchor="middle">{{block.letter}}</text>
|
|
58
|
+
<text x="90" y="{{math ../cardY '+' 68}}" dy=".3em" font-size="15" font-weight="500" fill="#334155" text-anchor="middle">{{block.fa}}</text>
|
|
59
|
+
<rect x="50" y="{{math ../cardY '+' 88.5}}" width="80" height="1" rx="0.5" fill="#E2E8F0"/>
|
|
60
|
+
<rect x="{{../domainChipX}}" y="{{math ../cardY '+' 101.5}}" width="{{../domainChipW}}" height="20" rx="4" fill="{{ternary block.isBlue ../colors.accent '#4F46E5'}}"/>
|
|
61
|
+
{{#if ../tAxis}}
|
|
62
|
+
<text x="90" y="{{math ../cardY '+' 112}}" dy=".3em" font-size="14" font-weight="600" fill="white" text-anchor="middle">{{block.score}}</text>
|
|
63
|
+
{{else}}
|
|
64
|
+
<text x="90" y="{{math ../cardY '+' 112}}" dy=".3em" font-size="14" font-weight="600" fill="white" text-anchor="middle">{{block.percentage}} ٪</text>
|
|
65
|
+
{{/if}}
|
|
66
|
+
<text x="90" y="{{math ../cardY '+' 138}}" dy=".3em" text-anchor="middle"><tspan font-size="15" font-weight="500" fill="#334155">{{block.mark}}</tspan><tspan font-size="13" font-weight="500" fill="#64748B"> از 192</tspan></text>
|
|
67
|
+
|
|
68
|
+
</g>
|
|
69
|
+
{{/each}}
|
|
70
|
+
|
|
71
|
+
{{#if tAxis}}
|
|
72
|
+
<line x1="374.5" y1="{{gridTop}}" x2="374.5" y2="{{gridBottom}}" stroke="#E2E8F0" stroke-linecap="round" stroke-dasharray="6 6"/>
|
|
73
|
+
<line x1="464.5" y1="{{gridTop}}" x2="464.5" y2="{{gridBottom}}" stroke="#E2E8F0" stroke-linecap="round" stroke-dasharray="6 6"/>
|
|
74
|
+
<line x1="524.5" y1="{{gridTop}}" x2="524.5" y2="{{gridBottom}}" stroke="#E2E8F0" stroke-linecap="round" stroke-dasharray="6 6"/>
|
|
75
|
+
<line x1="584.5" y1="{{gridTop}}" x2="584.5" y2="{{gridBottom}}" stroke="#E2E8F0" stroke-linecap="round" stroke-dasharray="6 6"/>
|
|
76
|
+
<line x1="644.5" y1="{{gridTop}}" x2="644.5" y2="{{gridBottom}}" stroke="#E2E8F0" stroke-linecap="round" stroke-dasharray="6 6"/>
|
|
77
|
+
<line x1="734.5" y1="{{gridTop}}" x2="734.5" y2="{{gridBottom}}" stroke="#E2E8F0" stroke-linecap="round" stroke-dasharray="6 6"/>
|
|
78
|
+
{{else}}
|
|
79
|
+
<line x1="429.5" y1="{{gridTop}}" x2="429.5" y2="{{gridBottom}}" stroke="#E2E8F0" stroke-linecap="round" stroke-dasharray="6 6"/>
|
|
80
|
+
<line x1="504.5" y1="{{gridTop}}" x2="504.5" y2="{{gridBottom}}" stroke="#E2E8F0" stroke-linecap="round" stroke-dasharray="6 6"/>
|
|
81
|
+
<line x1="579.5" y1="{{gridTop}}" x2="579.5" y2="{{gridBottom}}" stroke="#E2E8F0" stroke-linecap="round" stroke-dasharray="6 6"/>
|
|
82
|
+
<line x1="654.5" y1="{{gridTop}}" x2="654.5" y2="{{gridBottom}}" stroke="#E2E8F0" stroke-linecap="round" stroke-dasharray="6 6"/>
|
|
83
|
+
{{/if}}
|
|
84
|
+
|
|
85
|
+
{{#each blocks as |block blockIndex|}}
|
|
86
|
+
<g transform="translate(0, {{math blockIndex '*' 204}})">
|
|
87
|
+
<g transform="translate(0, {{block.facetOffsetY}})">
|
|
88
|
+
{{#each block.facets as |facet facetIndex|}}
|
|
89
|
+
<g transform="translate(0, {{math facetIndex '*' 28}})">
|
|
90
|
+
<g transform="translate(355, {{math ../../cardY '+' 16}})">
|
|
91
|
+
{{bar ../../trackW 16 (object tl=0 bl=0 tr=2 br=2) (toRad 0) fill='#E2E8F0' fill-opacity='0.5'}}
|
|
92
|
+
</g>
|
|
93
|
+
<text x="348" y="{{math ../../cardY '+' 24}}" dy=".3em" font-size="13" font-weight="400" fill="#475569" text-anchor="start">{{facet.fa}}</text>
|
|
94
|
+
<rect x="{{../../rawX}}" y="{{math ../../cardY '+' 16.5}}" width="35" height="15" rx="3.5" stroke="{{ternary block.isBlue ../../colors.stroke '#818CF8'}}" fill="none"/>
|
|
95
|
+
<text x="{{../../rawCenter}}" y="{{math ../../cardY '+' 24}}" dy=".3em" font-size="13" font-weight="500" fill="{{ternary block.isBlue ../../colors.accent '#4F46E5'}}" text-anchor="middle">{{facet.mark}}</text>
|
|
96
|
+
{{#unless ../../tAxis}}
|
|
97
|
+
<text x="{{../../levelX}}" y="{{math ../../cardY '+' 24}}" dy=".3em" font-size="12" font-weight="400" fill="#64748B" text-anchor="middle">{{facet.levelText}}</text>
|
|
98
|
+
{{/unless}}
|
|
99
|
+
</g>
|
|
100
|
+
{{/each}}
|
|
101
|
+
</g>
|
|
102
|
+
</g>
|
|
103
|
+
{{/each}}
|
|
104
|
+
|
|
105
|
+
{{#each blocks as |block blockIndex|}}
|
|
106
|
+
<g transform="translate(0, {{math blockIndex '*' 204}})">
|
|
107
|
+
<g transform="translate(0, {{block.facetOffsetY}})">
|
|
108
|
+
{{#each block.facets as |facet facetIndex|}}
|
|
109
|
+
<g transform="translate(355, {{math (math facetIndex '*' 28) '+' (math ../../cardY '+' 16)}})">
|
|
110
|
+
{{bar facet.barW 16 (object tl=0 bl=0 tr=2 br=2) (toRad 0) fill=(ternary block.isBlue 'url(#neoLongPrimary)' 'url(#neoLongSecondary)') clip-path='url(#neoLongBarClip)'}}
|
|
111
|
+
{{#if ../../tAxis}}
|
|
112
|
+
<text x="{{math facet.barW '+' (ternary facet.inside -4 6)}}" y="8" dy=".3em" font-size="13" font-weight="500" fill="{{ternary facet.inside 'white' (ternary block.isBlue ../../colors.dark '#4338CA')}}" text-anchor="{{ternary facet.inside 'start' 'end'}}">{{facet.score}}</text>
|
|
113
|
+
{{else}}
|
|
114
|
+
<text x="{{math facet.barW '+' (ternary (boolean facet.percentage '<' 24) 6 -4)}}" y="8" dy=".3em" font-size="13" font-weight="500" fill="{{ternary (boolean facet.percentage '<' 24) (ternary block.isBlue ../../colors.dark '#4338CA') 'white'}}" text-anchor="{{ternary (boolean facet.percentage '<' 24) 'end' 'start'}}">{{facet.percentage}} ٪</text>
|
|
115
|
+
{{/if}}
|
|
116
|
+
</g>
|
|
117
|
+
{{/each}}
|
|
118
|
+
</g>
|
|
119
|
+
</g>
|
|
120
|
+
{{/each}}
|
|
121
|
+
|
|
122
|
+
<g opacity="0.5" filter="url(#neoLongSplit)">
|
|
123
|
+
<line x1="354.5" y1="{{gridTop}}" x2="354.5" y2="{{gridBottom}}" stroke="white" stroke-linecap="round"/>
|
|
124
|
+
</g>
|
|
125
|
+
</g>
|