@baravak/risloo-profile-cli 4.83.0 → 4.85.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.md +21 -0
- package/package.json +1 -1
- package/src/publish/json/profiles/JSS93.json +684 -0
- package/src/publish/json/profiles/PSQI93.json +365 -0
- package/src/samples/JSS93.js +132 -0
- package/src/samples/PSQI93.js +135 -0
- package/views/profiles/samples/JSS93.hbs +131 -0
- package/views/profiles/samples/PSQI93.hbs +110 -0
|
@@ -0,0 +1,365 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "$X1HXXXXX",
|
|
3
|
+
"scale": {
|
|
4
|
+
"id": "$PSQI-93",
|
|
5
|
+
"title": "شاخص کیفیت خواب پیتزبورگ"
|
|
6
|
+
},
|
|
7
|
+
"chain": null,
|
|
8
|
+
"version": "1",
|
|
9
|
+
"edition": "فرهی مقدم",
|
|
10
|
+
"edition_version": null,
|
|
11
|
+
"client": {
|
|
12
|
+
"id": "GH966XXXX",
|
|
13
|
+
"name": "مراجع"
|
|
14
|
+
},
|
|
15
|
+
"room": {
|
|
16
|
+
"id": "RS96XXXX",
|
|
17
|
+
"manager": {
|
|
18
|
+
"id": "GH9XXXXX",
|
|
19
|
+
"name": "درمانگر",
|
|
20
|
+
"user_id": "IR9XXXX"
|
|
21
|
+
},
|
|
22
|
+
"center": {
|
|
23
|
+
"id": "RS966XXXX",
|
|
24
|
+
"acceptation": null,
|
|
25
|
+
"status": "active",
|
|
26
|
+
"type": "personal_clinic",
|
|
27
|
+
"detail": {
|
|
28
|
+
"title": "درمانگر"
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
"acceptation": null,
|
|
32
|
+
"status": "active",
|
|
33
|
+
"type": "personal_clinic"
|
|
34
|
+
},
|
|
35
|
+
"case": null,
|
|
36
|
+
"code": null,
|
|
37
|
+
"created_at": 1694157079,
|
|
38
|
+
"started_at": 1694157198,
|
|
39
|
+
"scored_at": 1694242467,
|
|
40
|
+
"closed_at": 1694160574,
|
|
41
|
+
"total_amount": 100000,
|
|
42
|
+
"prepayment": true,
|
|
43
|
+
"purchased": true,
|
|
44
|
+
"amount": 100000,
|
|
45
|
+
"description": "سؤالات زیر مربوط به عادات معمول خواب شما **فقط** در ماه گذشته میباشد. جوابهای شما باید مشخصکننده صحیحترین پاسخ در **اکثر** ایام ماه گذشته باشد، لطفاً به تمام سؤالات پاسخ دهید.",
|
|
46
|
+
"items": [
|
|
47
|
+
{
|
|
48
|
+
"type": "text",
|
|
49
|
+
"text": "در طی ماه گذشته معمولاً شبها ساعت چند به رختخواب میرفتید؟ (ساعت را به صورت عددی بین ۰ تا ۲۳ بنویسید)",
|
|
50
|
+
"description": "ساعت رفتن به رختخواب",
|
|
51
|
+
"answer": {
|
|
52
|
+
"type": "number"
|
|
53
|
+
},
|
|
54
|
+
"user_answered": "23"
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
"type": "text",
|
|
58
|
+
"text": "در طی ماه گذشته معمولاً هر شب چقدر طول میکشید تا به خواب بروید (به دقیقه)؟",
|
|
59
|
+
"description": "تعداد دقایق",
|
|
60
|
+
"answer": {
|
|
61
|
+
"type": "number"
|
|
62
|
+
},
|
|
63
|
+
"user_answered": "40"
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
"type": "text",
|
|
67
|
+
"text": "در طی ماه گذشته معمولاً صبحها چه ساعتی از رختخواب بلند شدهاید؟ (ساعت را به صورت عددی بین ۰ تا ۲۳ بنویسید)",
|
|
68
|
+
"description": "ساعت بلند شدن",
|
|
69
|
+
"answer": {
|
|
70
|
+
"type": "number"
|
|
71
|
+
},
|
|
72
|
+
"user_answered": "7"
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
"type": "text",
|
|
76
|
+
"text": "در طی ماه گذشته هر شب عملاً چند ساعت خوابیدهاید؟ (ممکن است با تعداد ساعتهایی که در رختخواب گذراندهاید متفاوت باشد)",
|
|
77
|
+
"description": "تعداد ساعات خواب در هر شب — به ساعت؛ کسر ساعت را اعشاری وارد کنید، مثلاً 6.5 برای شش ساعت و نیم",
|
|
78
|
+
"answer": {
|
|
79
|
+
"type": "number"
|
|
80
|
+
},
|
|
81
|
+
"user_answered": "5.5"
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
"type": "text",
|
|
85
|
+
"text": "به خواب نرفتن در عرض 30 دقیقه",
|
|
86
|
+
"category": "برای سؤالات باقیمانده بهترین پاسخ را علامت بزنید. لطفاً به تمام سؤالات پاسخ دهید.\n\nدر طی ماه گذشته چند بار به دلایل زیر در خوابیدن مشکل داشتهاید (تعداد دفعات را مشخص بفرمایید):",
|
|
87
|
+
"answer": {
|
|
88
|
+
"type": "optional",
|
|
89
|
+
"options": [
|
|
90
|
+
"هیچ مورد در طی ماه گذشته",
|
|
91
|
+
"کمتر از یک مورد در هفته",
|
|
92
|
+
"یک یا دو بار در هفته",
|
|
93
|
+
"سه بار یا بیشتر در هفته"
|
|
94
|
+
]
|
|
95
|
+
},
|
|
96
|
+
"user_answered": "3"
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
"type": "text",
|
|
100
|
+
"text": "بیدار شدن در نیمهشب یا صبح زود",
|
|
101
|
+
"category": "برای سؤالات باقیمانده بهترین پاسخ را علامت بزنید. لطفاً به تمام سؤالات پاسخ دهید.\n\nدر طی ماه گذشته چند بار به دلایل زیر در خوابیدن مشکل داشتهاید (تعداد دفعات را مشخص بفرمایید):",
|
|
102
|
+
"answer": {
|
|
103
|
+
"type": "optional",
|
|
104
|
+
"options": [
|
|
105
|
+
"هیچ مورد در طی ماه گذشته",
|
|
106
|
+
"کمتر از یک مورد در هفته",
|
|
107
|
+
"یک یا دو بار در هفته",
|
|
108
|
+
"سه بار یا بیشتر در هفته"
|
|
109
|
+
]
|
|
110
|
+
},
|
|
111
|
+
"user_answered": "4"
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
"type": "text",
|
|
115
|
+
"text": "بلند شدن از رختخواب برای رفتن به دستشویی",
|
|
116
|
+
"category": "برای سؤالات باقیمانده بهترین پاسخ را علامت بزنید. لطفاً به تمام سؤالات پاسخ دهید.\n\nدر طی ماه گذشته چند بار به دلایل زیر در خوابیدن مشکل داشتهاید (تعداد دفعات را مشخص بفرمایید):",
|
|
117
|
+
"answer": {
|
|
118
|
+
"type": "optional",
|
|
119
|
+
"options": [
|
|
120
|
+
"هیچ مورد در طی ماه گذشته",
|
|
121
|
+
"کمتر از یک مورد در هفته",
|
|
122
|
+
"یک یا دو بار در هفته",
|
|
123
|
+
"سه بار یا بیشتر در هفته"
|
|
124
|
+
]
|
|
125
|
+
},
|
|
126
|
+
"user_answered": "2"
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
"type": "text",
|
|
130
|
+
"text": "مشکل در نفس کشیدن",
|
|
131
|
+
"category": "برای سؤالات باقیمانده بهترین پاسخ را علامت بزنید. لطفاً به تمام سؤالات پاسخ دهید.\n\nدر طی ماه گذشته چند بار به دلایل زیر در خوابیدن مشکل داشتهاید (تعداد دفعات را مشخص بفرمایید):",
|
|
132
|
+
"answer": {
|
|
133
|
+
"type": "optional",
|
|
134
|
+
"options": [
|
|
135
|
+
"هیچ مورد در طی ماه گذشته",
|
|
136
|
+
"کمتر از یک مورد در هفته",
|
|
137
|
+
"یک یا دو بار در هفته",
|
|
138
|
+
"سه بار یا بیشتر در هفته"
|
|
139
|
+
]
|
|
140
|
+
},
|
|
141
|
+
"user_answered": "1"
|
|
142
|
+
},
|
|
143
|
+
{
|
|
144
|
+
"type": "text",
|
|
145
|
+
"text": "سرفه و خروپف با صدای بلند",
|
|
146
|
+
"category": "برای سؤالات باقیمانده بهترین پاسخ را علامت بزنید. لطفاً به تمام سؤالات پاسخ دهید.\n\nدر طی ماه گذشته چند بار به دلایل زیر در خوابیدن مشکل داشتهاید (تعداد دفعات را مشخص بفرمایید):",
|
|
147
|
+
"answer": {
|
|
148
|
+
"type": "optional",
|
|
149
|
+
"options": [
|
|
150
|
+
"هیچ مورد در طی ماه گذشته",
|
|
151
|
+
"کمتر از یک مورد در هفته",
|
|
152
|
+
"یک یا دو بار در هفته",
|
|
153
|
+
"سه بار یا بیشتر در هفته"
|
|
154
|
+
]
|
|
155
|
+
},
|
|
156
|
+
"user_answered": "1"
|
|
157
|
+
},
|
|
158
|
+
{
|
|
159
|
+
"type": "text",
|
|
160
|
+
"text": "احساس سرمای شدید",
|
|
161
|
+
"category": "برای سؤالات باقیمانده بهترین پاسخ را علامت بزنید. لطفاً به تمام سؤالات پاسخ دهید.\n\nدر طی ماه گذشته چند بار به دلایل زیر در خوابیدن مشکل داشتهاید (تعداد دفعات را مشخص بفرمایید):",
|
|
162
|
+
"answer": {
|
|
163
|
+
"type": "optional",
|
|
164
|
+
"options": [
|
|
165
|
+
"هیچ مورد در طی ماه گذشته",
|
|
166
|
+
"کمتر از یک مورد در هفته",
|
|
167
|
+
"یک یا دو بار در هفته",
|
|
168
|
+
"سه بار یا بیشتر در هفته"
|
|
169
|
+
]
|
|
170
|
+
},
|
|
171
|
+
"user_answered": "1"
|
|
172
|
+
},
|
|
173
|
+
{
|
|
174
|
+
"type": "text",
|
|
175
|
+
"text": "احساس گرمای شدید",
|
|
176
|
+
"category": "برای سؤالات باقیمانده بهترین پاسخ را علامت بزنید. لطفاً به تمام سؤالات پاسخ دهید.\n\nدر طی ماه گذشته چند بار به دلایل زیر در خوابیدن مشکل داشتهاید (تعداد دفعات را مشخص بفرمایید):",
|
|
177
|
+
"answer": {
|
|
178
|
+
"type": "optional",
|
|
179
|
+
"options": [
|
|
180
|
+
"هیچ مورد در طی ماه گذشته",
|
|
181
|
+
"کمتر از یک مورد در هفته",
|
|
182
|
+
"یک یا دو بار در هفته",
|
|
183
|
+
"سه بار یا بیشتر در هفته"
|
|
184
|
+
]
|
|
185
|
+
},
|
|
186
|
+
"user_answered": "1"
|
|
187
|
+
},
|
|
188
|
+
{
|
|
189
|
+
"type": "text",
|
|
190
|
+
"text": "خواب بد دیدن",
|
|
191
|
+
"category": "برای سؤالات باقیمانده بهترین پاسخ را علامت بزنید. لطفاً به تمام سؤالات پاسخ دهید.\n\nدر طی ماه گذشته چند بار به دلایل زیر در خوابیدن مشکل داشتهاید (تعداد دفعات را مشخص بفرمایید):",
|
|
192
|
+
"answer": {
|
|
193
|
+
"type": "optional",
|
|
194
|
+
"options": [
|
|
195
|
+
"هیچ مورد در طی ماه گذشته",
|
|
196
|
+
"کمتر از یک مورد در هفته",
|
|
197
|
+
"یک یا دو بار در هفته",
|
|
198
|
+
"سه بار یا بیشتر در هفته"
|
|
199
|
+
]
|
|
200
|
+
},
|
|
201
|
+
"user_answered": "2"
|
|
202
|
+
},
|
|
203
|
+
{
|
|
204
|
+
"type": "text",
|
|
205
|
+
"text": "درد داشتن",
|
|
206
|
+
"category": "برای سؤالات باقیمانده بهترین پاسخ را علامت بزنید. لطفاً به تمام سؤالات پاسخ دهید.\n\nدر طی ماه گذشته چند بار به دلایل زیر در خوابیدن مشکل داشتهاید (تعداد دفعات را مشخص بفرمایید):",
|
|
207
|
+
"answer": {
|
|
208
|
+
"type": "optional",
|
|
209
|
+
"options": [
|
|
210
|
+
"هیچ مورد در طی ماه گذشته",
|
|
211
|
+
"کمتر از یک مورد در هفته",
|
|
212
|
+
"یک یا دو بار در هفته",
|
|
213
|
+
"سه بار یا بیشتر در هفته"
|
|
214
|
+
]
|
|
215
|
+
},
|
|
216
|
+
"user_answered": "3"
|
|
217
|
+
},
|
|
218
|
+
{
|
|
219
|
+
"type": "text",
|
|
220
|
+
"text": "اگر موارد دیگری وجود داشته است، لطفاً توضیح دهید (تعداد دفعات آن را نیز مشخص بفرمایید):",
|
|
221
|
+
"category": "برای سؤالات باقیمانده بهترین پاسخ را علامت بزنید. لطفاً به تمام سؤالات پاسخ دهید.\n\nدر طی ماه گذشته چند بار به دلایل زیر در خوابیدن مشکل داشتهاید (تعداد دفعات را مشخص بفرمایید):",
|
|
222
|
+
"answer": {
|
|
223
|
+
"type": "optional",
|
|
224
|
+
"description": {
|
|
225
|
+
"text": "موارد دیگر را اینجا توضیح دهید"
|
|
226
|
+
},
|
|
227
|
+
"options": [
|
|
228
|
+
"هیچ مورد در طی ماه گذشته",
|
|
229
|
+
"کمتر از یک مورد در هفته",
|
|
230
|
+
"یک یا دو بار در هفته",
|
|
231
|
+
"سه بار یا بیشتر در هفته"
|
|
232
|
+
]
|
|
233
|
+
},
|
|
234
|
+
"user_answered": "2",
|
|
235
|
+
"user_description": "پای بیقرار"
|
|
236
|
+
},
|
|
237
|
+
{
|
|
238
|
+
"type": "text",
|
|
239
|
+
"text": "بهطور کلی کیفیت خواب خود را در طی ماه گذشته چگونه ارزیابی میکنید؟",
|
|
240
|
+
"answer": {
|
|
241
|
+
"type": "optional",
|
|
242
|
+
"options": [
|
|
243
|
+
"خیلی خوب",
|
|
244
|
+
"نسبتاً خوب",
|
|
245
|
+
"نسبتاً بد",
|
|
246
|
+
"خیلی بد"
|
|
247
|
+
]
|
|
248
|
+
},
|
|
249
|
+
"user_answered": "3"
|
|
250
|
+
},
|
|
251
|
+
{
|
|
252
|
+
"type": "text",
|
|
253
|
+
"text": "در طی ماه گذشته چند بار جهت خواب رفتن از دارو استفاده کردهاید؟ (چه با تجویز پزشک و چه بدون نسخه)",
|
|
254
|
+
"answer": {
|
|
255
|
+
"type": "optional",
|
|
256
|
+
"options": [
|
|
257
|
+
"هیچ مورد در طی ماه گذشته",
|
|
258
|
+
"کمتر از یک مورد در هفته",
|
|
259
|
+
"یک یا دو بار در هفته",
|
|
260
|
+
"سه بار یا بیشتر در هفته"
|
|
261
|
+
]
|
|
262
|
+
},
|
|
263
|
+
"user_answered": "1"
|
|
264
|
+
},
|
|
265
|
+
{
|
|
266
|
+
"type": "text",
|
|
267
|
+
"text": "در طی ماه گذشته چند بار جهت بیدار ماندن حین رانندگی، غذا خوردن یا شرکت در فعالیت اجتماعی دچار مشکل شدهاید؟",
|
|
268
|
+
"answer": {
|
|
269
|
+
"type": "optional",
|
|
270
|
+
"options": [
|
|
271
|
+
"هیچ مورد در طی ماه گذشته",
|
|
272
|
+
"کمتر از یک مورد در هفته",
|
|
273
|
+
"یک یا دو بار در هفته",
|
|
274
|
+
"سه بار یا بیشتر در هفته"
|
|
275
|
+
]
|
|
276
|
+
},
|
|
277
|
+
"user_answered": "2"
|
|
278
|
+
},
|
|
279
|
+
{
|
|
280
|
+
"type": "text",
|
|
281
|
+
"text": "در طی ماه گذشته برای اینکه اشتیاق کافی جهت انجام دادن کار را در خود حفظ کنید، چقدر مشکل داشتهاید؟",
|
|
282
|
+
"answer": {
|
|
283
|
+
"type": "optional",
|
|
284
|
+
"options": [
|
|
285
|
+
"هیچ مشکلی نداشتم",
|
|
286
|
+
"خیلی کم مشکل داشتم",
|
|
287
|
+
"تا حدی مشکل داشتم",
|
|
288
|
+
"مشکل زیادی داشتم"
|
|
289
|
+
]
|
|
290
|
+
},
|
|
291
|
+
"user_answered": "3"
|
|
292
|
+
}
|
|
293
|
+
],
|
|
294
|
+
"prerequisites": [
|
|
295
|
+
{
|
|
296
|
+
"type": "text",
|
|
297
|
+
"label": "gender",
|
|
298
|
+
"text": "جنسیت",
|
|
299
|
+
"answer": {
|
|
300
|
+
"type": "select",
|
|
301
|
+
"options": [
|
|
302
|
+
"زن",
|
|
303
|
+
"مرد"
|
|
304
|
+
]
|
|
305
|
+
},
|
|
306
|
+
"alias": "gender",
|
|
307
|
+
"force": true,
|
|
308
|
+
"user_answered": "1"
|
|
309
|
+
},
|
|
310
|
+
{
|
|
311
|
+
"type": "text",
|
|
312
|
+
"label": "age",
|
|
313
|
+
"text": "سن",
|
|
314
|
+
"answer": {
|
|
315
|
+
"type": "number"
|
|
316
|
+
},
|
|
317
|
+
"alias": "age",
|
|
318
|
+
"force": true,
|
|
319
|
+
"user_answered": "35"
|
|
320
|
+
},
|
|
321
|
+
{
|
|
322
|
+
"type": "text",
|
|
323
|
+
"label": "education",
|
|
324
|
+
"text": "تحصیلات",
|
|
325
|
+
"answer": {
|
|
326
|
+
"type": "select",
|
|
327
|
+
"options": [
|
|
328
|
+
"ابتدایی اول",
|
|
329
|
+
"ابتدایی دوم",
|
|
330
|
+
"متوسطه اول",
|
|
331
|
+
"متوسطه دوم",
|
|
332
|
+
"دیپلم",
|
|
333
|
+
"کارشناسی",
|
|
334
|
+
"کارشناسی ارشد",
|
|
335
|
+
"پزشکی عمومی",
|
|
336
|
+
"متخصص",
|
|
337
|
+
"دکتری تخصصی",
|
|
338
|
+
"حوزوی مقدمات",
|
|
339
|
+
"حوزوی سطح۱",
|
|
340
|
+
"حوزوی سطح۲",
|
|
341
|
+
"حوزوی سطح۳",
|
|
342
|
+
"حوزوی سطح۴"
|
|
343
|
+
]
|
|
344
|
+
},
|
|
345
|
+
"alias": "education",
|
|
346
|
+
"force": true,
|
|
347
|
+
"user_answered": "6"
|
|
348
|
+
}
|
|
349
|
+
],
|
|
350
|
+
"cornometer": 743,
|
|
351
|
+
"score": {
|
|
352
|
+
"status": "valid",
|
|
353
|
+
"subjective_quality": 2,
|
|
354
|
+
"latency": 2,
|
|
355
|
+
"duration": 2,
|
|
356
|
+
"efficiency": 2,
|
|
357
|
+
"disturbances": 1,
|
|
358
|
+
"medication": 0,
|
|
359
|
+
"daytime_dysfunction": 2,
|
|
360
|
+
"total": 11,
|
|
361
|
+
"screening": "positive"
|
|
362
|
+
},
|
|
363
|
+
"score_current_version": "1.0.0",
|
|
364
|
+
"score_last_version": "1.0.0"
|
|
365
|
+
}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
const { Profile } = require("../Profile");
|
|
2
|
+
|
|
3
|
+
// ---------------------------------------------------------------------------
|
|
4
|
+
// Chart geometry, measured from the Figma "Chart" layer (789 × 414). Only the
|
|
5
|
+
// values the controller has to compute with live here; the static geometry is
|
|
6
|
+
// transcribed in the template.
|
|
7
|
+
// ---------------------------------------------------------------------------
|
|
8
|
+
const ROW = { top: 54, pitch: 40 }; // first bar row, row-to-row pitch
|
|
9
|
+
const BAR = { x: 174, coefficient: 4, gap: 4 }; // 100 % = 400 px (designer note); label 4 px inside the tip
|
|
10
|
+
const BASELINE = 12.06; // 13 px text baseline, measured from the row top
|
|
11
|
+
|
|
12
|
+
// Total column: vertical bar filling bottom → up, 100 % = 350 px (designer note).
|
|
13
|
+
const TOTAL = { bottom: 396, coefficient: 3.5 };
|
|
14
|
+
|
|
15
|
+
class JSS93 extends Profile {
|
|
16
|
+
static pages = 1;
|
|
17
|
+
|
|
18
|
+
// JSS93 — پرسشنامه رضایت شغلی اسپکتور. Nine 4-item factors (raw 4–20) plus the
|
|
19
|
+
// total (raw 36–180). `percentage` is the share of the possible maximum, the
|
|
20
|
+
// definition the design uses (scoring/JSS93.py → round(raw / max, 3)); it drives
|
|
21
|
+
// both the bar length and the "٪ NN" readout so the two can never disagree.
|
|
22
|
+
labels = {
|
|
23
|
+
L1_1: { eng: "pay_raw", title: "رضایت از پرداختها", max: 20 },
|
|
24
|
+
L1_2: { eng: "pay_percentage" },
|
|
25
|
+
|
|
26
|
+
L2_1: { eng: "operating_procedures_raw", title: "فرآیندهای اجرایی کار (شرایط کار)", max: 20 },
|
|
27
|
+
L2_2: { eng: "operating_procedures_percentage" },
|
|
28
|
+
|
|
29
|
+
L3_1: { eng: "coworkers_raw", title: "همکاران", max: 20 },
|
|
30
|
+
L3_2: { eng: "coworkers_percentage" },
|
|
31
|
+
|
|
32
|
+
L4_1: { eng: "promotion_raw", title: "ارتقای شغلی", max: 20 },
|
|
33
|
+
L4_2: { eng: "promotion_percentage" },
|
|
34
|
+
|
|
35
|
+
L5_1: { eng: "supervision_raw", title: "نظارت", max: 20 },
|
|
36
|
+
L5_2: { eng: "supervision_percentage" },
|
|
37
|
+
|
|
38
|
+
L6_1: { eng: "fringe_benefits_raw", title: "مزایای جانبی شغل", max: 20 },
|
|
39
|
+
L6_2: { eng: "fringe_benefits_percentage" },
|
|
40
|
+
|
|
41
|
+
L7_1: { eng: "contingent_rewards_raw", title: "پاداشهای احتمالی", max: 20 },
|
|
42
|
+
L7_2: { eng: "contingent_rewards_percentage" },
|
|
43
|
+
|
|
44
|
+
L8_1: { eng: "nature_of_work_raw", title: "ماهیت شغل", max: 20 },
|
|
45
|
+
L8_2: { eng: "nature_of_work_percentage" },
|
|
46
|
+
|
|
47
|
+
L9_1: { eng: "communication_raw", title: "ارتباطات و اطلاعرسانی", max: 20 },
|
|
48
|
+
L9_2: { eng: "communication_percentage" },
|
|
49
|
+
|
|
50
|
+
L10_1: { eng: "total_raw", title: "نمره کل رضایت شغلی", max: 180 },
|
|
51
|
+
L10_2: { eng: "total_percentage" },
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
profileSpec = {
|
|
55
|
+
sample: {
|
|
56
|
+
name: "پرسشنامه رضایت شغلی اسپکتور",
|
|
57
|
+
multiProfile: false,
|
|
58
|
+
questions: false,
|
|
59
|
+
defaultFields: true,
|
|
60
|
+
fields: [],
|
|
61
|
+
},
|
|
62
|
+
profile: {
|
|
63
|
+
get dimensions() {
|
|
64
|
+
return {
|
|
65
|
+
width: 789 + 2 * this.padding.x, // Chart layer 789 wide → 903
|
|
66
|
+
height: 414 + 2 * this.padding.y, // Chart layer 414 tall → 714
|
|
67
|
+
};
|
|
68
|
+
},
|
|
69
|
+
// Padding is the Chart's inset inside the 943 × 754 design page *minus* the
|
|
70
|
+
// 20 px the layout already owns on every side, so the page resolves to
|
|
71
|
+
// 903 × 714 — the exact with-sidebar drawing area — and renders at scale 1
|
|
72
|
+
// instead of being shrunk to fit.
|
|
73
|
+
padding: {
|
|
74
|
+
x: 57, // (943 − 789) / 2 − 20
|
|
75
|
+
y: 150, // (754 − 414) / 2 − 20
|
|
76
|
+
},
|
|
77
|
+
},
|
|
78
|
+
labels: Object.values(this.labels),
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
constructor(dataset, options, config = {}) {
|
|
82
|
+
super();
|
|
83
|
+
this._init(dataset, options, config);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
_calcContext() {
|
|
87
|
+
const { dataset } = this;
|
|
88
|
+
const s = dataset.score; // [raw, percentage] × 9 factors, then the total
|
|
89
|
+
|
|
90
|
+
const items = [];
|
|
91
|
+
for (let i = 0; i < 9; i++) {
|
|
92
|
+
const raw = s[2 * i];
|
|
93
|
+
const top = ROW.top + i * ROW.pitch;
|
|
94
|
+
// The design rounds the percentage before drawing, so the tip of the bar
|
|
95
|
+
// always lands exactly on the number printed inside it.
|
|
96
|
+
const pct = Math.round((s[2 * i + 1].mark ?? 0) * 100);
|
|
97
|
+
const width = BAR.coefficient * pct;
|
|
98
|
+
|
|
99
|
+
items.push({
|
|
100
|
+
title: raw.label.title,
|
|
101
|
+
mark: raw.mark ?? 0,
|
|
102
|
+
pct,
|
|
103
|
+
width,
|
|
104
|
+
top,
|
|
105
|
+
// Designer note: the percentage never leaves the bar — this test cannot
|
|
106
|
+
// score below 20 %, so there is always room for the label inside it.
|
|
107
|
+
labelX: BAR.x + width - BAR.gap,
|
|
108
|
+
baseline: top + BASELINE,
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const totalRaw = s[18];
|
|
113
|
+
const totalPct = Math.round((s[19].mark ?? 0) * 100);
|
|
114
|
+
const height = TOTAL.coefficient * totalPct;
|
|
115
|
+
const tip = TOTAL.bottom - height;
|
|
116
|
+
|
|
117
|
+
const total = {
|
|
118
|
+
mark: totalRaw.mark ?? 0,
|
|
119
|
+
max: totalRaw.label.max,
|
|
120
|
+
pct: totalPct,
|
|
121
|
+
height,
|
|
122
|
+
tip,
|
|
123
|
+
// Designer note: the readout travels with the bar, centred on its tip.
|
|
124
|
+
pctBaseline: tip - 0.98,
|
|
125
|
+
fractionBaseline: tip + 13.06,
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
return [{ items, total }];
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
module.exports = JSS93;
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
const { Profile } = require("../Profile");
|
|
2
|
+
|
|
3
|
+
// ---------------------------------------------------------------------------
|
|
4
|
+
// PSQI93 — شاخص کیفیت خواب پیتزبورگ. No Figma source: the chart was designed
|
|
5
|
+
// directly from the approved result specification of the science record
|
|
6
|
+
// (catalog/assessments/psqi, «مشخصات نتیجه فردی»), whose rules this layout
|
|
7
|
+
// enforces rather than decorates:
|
|
8
|
+
// - seven components on one shared 0–3 axis, raw only — no per-component
|
|
9
|
+
// class, colour or label (no evidence for any);
|
|
10
|
+
// - the total 0–21, drawn neutral: the screening result lives ONLY in the
|
|
11
|
+
// approved interpretation text — no badge, no colour, no cut line;
|
|
12
|
+
// - all-or-nothing: when scoring/PSQI93.py returns status "invalid" nothing
|
|
13
|
+
// but the no-result message is drawn — never a partial or zero score.
|
|
14
|
+
// Chart 863 × 674, centred on the 943 × 754 design page.
|
|
15
|
+
// ---------------------------------------------------------------------------
|
|
16
|
+
const CHART = { width: 863, height: 674 };
|
|
17
|
+
|
|
18
|
+
// Component rows: bars grow left → right from the 0 guide; the total card sits
|
|
19
|
+
// to the right of the chart.
|
|
20
|
+
const ROW = { top: 84, pitch: 44, height: 18 };
|
|
21
|
+
const AXIS = { zero: 162, unit: 150, max: 3 }; // 0 at x=162, 3 at x=612
|
|
22
|
+
const BASELINE = 13.2; // 14 px text on an 18 px row
|
|
23
|
+
|
|
24
|
+
// Total card bar, also left → right: 0 at the card's left inset, 21 at its right.
|
|
25
|
+
const TOTAL = { left: 713, length: 130, max: 21, cutoff: 6 };
|
|
26
|
+
|
|
27
|
+
// Interpretation panel: one fixed line pitch; the conditional false-positive
|
|
28
|
+
// line collapses its space when the screen is negative.
|
|
29
|
+
const TEXT = { top: 494, pitch: 27 };
|
|
30
|
+
|
|
31
|
+
class PSQI93 extends Profile {
|
|
32
|
+
static pages = 1;
|
|
33
|
+
|
|
34
|
+
labels = {
|
|
35
|
+
L1: { eng: "subjective_quality", title: "کیفیت ذهنی خواب" },
|
|
36
|
+
L2: { eng: "latency", title: "تأخیر خواب" },
|
|
37
|
+
L3: { eng: "duration", title: "مدت خواب" },
|
|
38
|
+
L4: { eng: "efficiency", title: "کارایی معمول خواب" },
|
|
39
|
+
L5: { eng: "disturbances", title: "اختلالهای خواب" },
|
|
40
|
+
L6: { eng: "medication", title: "مصرف داروی خواب" },
|
|
41
|
+
L7: { eng: "daytime_dysfunction", title: "اختلال عملکرد روزانه" },
|
|
42
|
+
L8: { eng: "total", title: "نمره کل", max: 21 },
|
|
43
|
+
L9: { eng: "status" }, // valid | invalid
|
|
44
|
+
L10: { eng: "screening" }, // positive | negative — read, never drawn as a label
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
profileSpec = {
|
|
48
|
+
sample: {
|
|
49
|
+
name: "شاخص کیفیت خواب پیتزبورگ",
|
|
50
|
+
multiProfile: false,
|
|
51
|
+
questions: false,
|
|
52
|
+
defaultFields: true,
|
|
53
|
+
fields: [],
|
|
54
|
+
},
|
|
55
|
+
profile: {
|
|
56
|
+
get dimensions() {
|
|
57
|
+
return {
|
|
58
|
+
width: CHART.width + 2 * this.padding.x, // 863 → 903
|
|
59
|
+
height: CHART.height + 2 * this.padding.y, // 674 → 714
|
|
60
|
+
};
|
|
61
|
+
},
|
|
62
|
+
// Chart inset inside the 943 × 754 design page minus the 20 px the layout
|
|
63
|
+
// owns on every side, so the with-sidebar page renders at scale 1.
|
|
64
|
+
padding: {
|
|
65
|
+
x: (943 - CHART.width) / 2 - 20, // 20
|
|
66
|
+
y: (754 - CHART.height) / 2 - 20, // 20
|
|
67
|
+
},
|
|
68
|
+
},
|
|
69
|
+
labels: Object.values(this.labels),
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
constructor(dataset, options, config = {}) {
|
|
73
|
+
super();
|
|
74
|
+
this._init(dataset, options, config);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
_calcContext() {
|
|
78
|
+
const s = this.dataset.score;
|
|
79
|
+
const status = s[8].mark;
|
|
80
|
+
|
|
81
|
+
// Anything but an explicit "valid" is treated as no result: a missing
|
|
82
|
+
// status must not let seven `?? 0` zeros read as "no sleep problem".
|
|
83
|
+
if (status !== "valid") return [{ valid: false }];
|
|
84
|
+
|
|
85
|
+
const items = s.slice(0, 7).map((data, i) => {
|
|
86
|
+
const mark = data.mark ?? 0;
|
|
87
|
+
const top = ROW.top + i * ROW.pitch;
|
|
88
|
+
const width = mark * AXIS.unit;
|
|
89
|
+
return {
|
|
90
|
+
title: data.label.title,
|
|
91
|
+
mark,
|
|
92
|
+
top,
|
|
93
|
+
width,
|
|
94
|
+
x: AXIS.zero,
|
|
95
|
+
baseline: top + BASELINE,
|
|
96
|
+
};
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
const totalMark = s[7].mark ?? 0;
|
|
100
|
+
const positive = totalMark >= TOTAL.cutoff;
|
|
101
|
+
const totalWidth = (TOTAL.length * totalMark) / TOTAL.max;
|
|
102
|
+
|
|
103
|
+
const line = (n) => TEXT.top + n * TEXT.pitch;
|
|
104
|
+
const falsePositive = positive ? line(3) : null;
|
|
105
|
+
const next = positive ? 4 : 3;
|
|
106
|
+
|
|
107
|
+
return [
|
|
108
|
+
{
|
|
109
|
+
valid: true,
|
|
110
|
+
items,
|
|
111
|
+
ticks: [0, 1, 2, 3].map((v) => ({ v, x: AXIS.zero + v * AXIS.unit })),
|
|
112
|
+
total: {
|
|
113
|
+
mark: totalMark,
|
|
114
|
+
max: TOTAL.max,
|
|
115
|
+
width: totalWidth,
|
|
116
|
+
x: TOTAL.left,
|
|
117
|
+
},
|
|
118
|
+
screen: {
|
|
119
|
+
positive,
|
|
120
|
+
text: positive ? "نیازمند بررسی بیشتر" : "نشانهای از مشکل قابلتوجه دیده نشد",
|
|
121
|
+
},
|
|
122
|
+
lines: {
|
|
123
|
+
direction: line(0),
|
|
124
|
+
screen: line(1),
|
|
125
|
+
cutoff: line(2),
|
|
126
|
+
falsePositive,
|
|
127
|
+
limits1: line(next),
|
|
128
|
+
limits2: line(next + 1),
|
|
129
|
+
},
|
|
130
|
+
},
|
|
131
|
+
];
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
module.exports = PSQI93;
|