@baravak/risloo-profile-cli 4.86.0 → 4.87.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@baravak/risloo-profile-cli",
3
- "version": "4.86.0",
3
+ "version": "4.87.0",
4
4
  "description": "**Risloo Profile CLI** is a library for creating profiles, reports and sheets for *psychological* samples.",
5
5
  "main": "bin/risloo.js",
6
6
  "publishConfig": {
@@ -1,25 +1,25 @@
1
1
  const { Profile } = require("../Profile");
2
2
 
3
3
  // ---------------------------------------------------------------------------
4
- // AIS93 — مقیاس بی‌خوابی آتن (AIS-8 فارسی). No Figma source: the chart is
5
- // designed from the approved individual-result specification of the science
6
- // package (AIS-FA8-C2), whose rules this layout enforces rather than decorates:
7
- // - one score only, the 0–24 total, drawn as its position on one line with
8
- // that range; no night/day subscore, no component, no comparison;
9
- // - classification is off: one neutral hue, no coloured zone, no threshold,
10
- // no label, no warning, no percentile or norm;
11
- // - the only interpretation is the two approved sentences, verbatim;
12
- // - the reference cut-off (6) is text only, with its source, sample and year,
13
- // because the profile is read by the authorised specialist and never handed
14
- // to the respondent; the score is never compared with it;
15
- // - all-or-nothing: unless scoring/AIS93.py returns status "valid", only the
16
- // no-result message is drawn — never a partial or zero score.
17
- // Chart 863 × 674, centred on the 943 × 754 design page.
4
+ // AIS93 — مقیاس بی‌خوابی آتن (AIS-8 فارسی). Chart drawn from the Figma
5
+ // half-ring gauge (Assessments v3.0.0, node 5405:146150): the total (0–24) as
6
+ // a 180° gauge filling clockwise from 0 on the left to 100 % on the right,
7
+ // percentage and "mark از max" in the centre, title above.
8
+ // The interpretation panel and the reference cut-off text were dropped on
9
+ // request to match that design.
10
+ // All-or-nothing: unless scoring/AIS93.py returns status "valid", only the
11
+ // no-result message is drawn — never a partial or zero score.
12
+ // The gauge piece sits at (346, 284) on the 943 × 754 design page, one pixel
13
+ // off-centre on each axis (insets 346 / 347 and 284 / 283), so the Chart is
14
+ // the page minus the measured left/top insets: 251 × 186. The piece is 250
15
+ // wide; its bottom labels paint down to y ≈ 186.
18
16
  // ---------------------------------------------------------------------------
19
- const CHART = { width: 863, height: 674 };
17
+ const CHART = { width: 251, height: 186 };
18
+ const INSET = { x: 346, y: 284 }; // measured on the design page
20
19
 
21
- // The total's own axis: 0 at x=LINE.left, 24 at x=LINE.right.
22
- const LINE = { left: 20, right: 640, y: 112 };
20
+ // Gauge centre on the Chart; R 125 / r 87.5, so the ring's top sits at y = 42.
21
+ const GAUGE = { x: 125, y: 167 };
22
+ const SWEEP = { start: Math.PI, end: 2 * Math.PI }; // left → top → right, clockwise
23
23
 
24
24
  class AIS93 extends Profile {
25
25
  static pages = 1;
@@ -40,15 +40,15 @@ class AIS93 extends Profile {
40
40
  profile: {
41
41
  get dimensions() {
42
42
  return {
43
- width: CHART.width + 2 * this.padding.x, // 863 → 903
44
- height: CHART.height + 2 * this.padding.y, // 674 → 714
43
+ width: CHART.width + 2 * this.padding.x, // 251 → 903
44
+ height: CHART.height + 2 * this.padding.y, // 186 → 714
45
45
  };
46
46
  },
47
- // Chart inset inside the 943 × 754 design page minus the 20 px the layout
48
- // owns on every side, so the with-sidebar page renders at scale 1.
47
+ // Measured Chart inset on the 943 × 754 design page minus the 20 px the
48
+ // layout owns on every side, so the with-sidebar page renders at scale 1.
49
49
  padding: {
50
- x: (943 - CHART.width) / 2 - 20, // 20
51
- y: (754 - CHART.height) / 2 - 20, // 20
50
+ x: INSET.x - 20, // 326
51
+ y: INSET.y - 20, // 264
52
52
  },
53
53
  },
54
54
  labels: Object.values(this.labels),
@@ -68,17 +68,19 @@ class AIS93 extends Profile {
68
68
 
69
69
  const mark = s[0].mark ?? 0;
70
70
  const max = s[0].label.max;
71
+ const p = Math.min(Math.max(mark / max, 0), 1);
71
72
 
72
73
  return [
73
74
  {
74
75
  valid: true,
75
76
  total: {
77
+ title: "بی‌خوابی آتن",
76
78
  mark,
77
79
  max,
78
- left: LINE.left,
79
- right: LINE.right,
80
- y: LINE.y,
81
- x: LINE.left + ((LINE.right - LINE.left) * mark) / max,
80
+ pct: Math.round(p * 100),
81
+ zeta: SWEEP.start + p * (SWEEP.end - SWEEP.start),
82
+ x: GAUGE.x,
83
+ y: GAUGE.y,
82
84
  },
83
85
  },
84
86
  ];
@@ -1,60 +1,48 @@
1
1
  {{#> layout}}
2
2
 
3
+ <defs>
4
+ {{#if valid}}
5
+ {{! Fill gradient from the Figma export, in gauge-centred user space (page 346,451 → 555.826,359.187 about centre 471,451) }}
6
+ <linearGradient id="aisGauge" x1="-125" y1="0" x2="84.826" y2="-91.813" gradientUnits="userSpaceOnUse">
7
+ <stop stop-color="#818CF8"/>
8
+ <stop offset="1" stop-color="#4338CA"/>
9
+ </linearGradient>
10
+ {{! Track shape: both ends rounded; clips the fill so a full gauge keeps the rounded right end }}
11
+ <clipPath id="aisGaugeTrack">
12
+ {{gauge 125 87.5 (object tl=6 tr=6 bl=6 br=6) (object start=(toRad 180) end=(toRad 0)) false}}
13
+ </clipPath>
14
+ {{/if}}
15
+ </defs>
16
+
3
17
  <g transform="translate({{spec.profile.padding.x}}, {{spec.profile.padding.y}})">
4
18
 
5
19
  {{#if valid}}
6
20
 
7
- {{! ===================== The total, on its own 0–24 line ===================== }}
8
- {{! One neutral hue; no zone, no threshold, no tick at the reference cut-off. }}
9
- <text x="843" y="24" text-anchor="start" font-size="16" font-weight="600" fill="#1E293B">نمرهٔ کل</text>
10
-
11
- <line x1="{{total.left}}" y1="{{total.y}}" x2="{{total.right}}" y2="{{total.y}}" stroke="#CBD5E1" stroke-width="4" stroke-linecap="round"/>
12
- <line x1="{{total.left}}" y1="{{math total.y '-' 7}}" x2="{{total.left}}" y2="{{math total.y '+' 7}}" stroke="#94A3B8" stroke-width="1.5"/>
13
- <line x1="{{total.right}}" y1="{{math total.y '-' 7}}" x2="{{total.right}}" y2="{{math total.y '+' 7}}" stroke="#94A3B8" stroke-width="1.5"/>
14
- <text x="{{total.left}}" y="{{math total.y '+' 24}}" text-anchor="middle" font-size="11" fill="#94A3B8">0</text>
15
- <text x="{{total.right}}" y="{{math total.y '+' 24}}" text-anchor="middle" font-size="11" fill="#94A3B8">{{total.max}}</text>
16
-
17
- <circle cx="{{total.x}}" cy="{{total.y}}" r="7" fill="#475569" stroke="white" stroke-width="2"/>
18
- <text x="{{total.x}}" y="{{math total.y '-' 14}}" text-anchor="middle" font-size="13" font-weight="700" fill="#1E293B">{{total.mark}}</text>
19
-
20
- {{! Total card (right of the line) }}
21
- <rect x="693.5" y="52.5" width="169" height="120" rx="8" fill="#F8FAFC" stroke="#E2E8F0"/>
22
- <text x="778" y="82" text-anchor="middle" font-size="14" font-weight="600" fill="#475569">نمرهٔ کل</text>
23
- <text x="778" y="134" text-anchor="middle" font-size="44" font-weight="700" fill="#1E293B">{{total.mark}}</text>
24
- <text x="778" y="158" text-anchor="middle" font-size="13" fill="#64748B">از {{total.max}}</text>
25
-
26
- {{! ===================== Interpretation, uncertainty, reference cut-off ===================== }}
27
- {{! Fixed text from the science package; the profile is read by the authorised specialist. }}
28
- <rect x="0.5" y="204.5" width="862" height="401" rx="8" fill="#F8FAFC" stroke="#E2E8F0"/>
29
-
30
- <text x="843" y="236" text-anchor="start" font-size="15" font-weight="600" fill="#1E293B">تفسیر</text>
31
- <text x="843" y="264" text-anchor="start" font-size="13.5" fill="#334155">نمرهٔ بالاتر، دشواری بیشتری در خواب را نشان می‌دهد، همان‌طور که پاسخ‌دهنده خودش گزارش کرده است.</text>
32
- <text x="843" y="288" text-anchor="start" font-size="13.5" fill="#334155">این نمره تشخیص نیست.</text>
33
-
34
- <text x="843" y="326" text-anchor="start" font-size="15" font-weight="600" fill="#1E293B">عدم قطعیت و محدودیت</text>
35
- <circle cx="840" cy="349.5" r="2" fill="#334155"/>
36
- <text x="831" y="354" text-anchor="start" font-size="13.5" fill="#334155">این نسخهٔ فارسی اعتبارسنجی نشده و برش بومی ندارد.</text>
37
- <circle cx="840" cy="373.5" r="2" fill="#334155"/>
38
- <text x="831" y="378" text-anchor="start" font-size="13.5" fill="#334155">این ابزار غربال است، نه تشخیص.</text>
39
- <circle cx="840" cy="397.5" r="2" fill="#334155"/>
40
- <text x="831" y="402" text-anchor="start" font-size="13.5" fill="#334155">آزمون تصمیم‌یار است، نه تصمیم‌گیر قطعی.</text>
41
-
42
- <text x="843" y="440" text-anchor="start" font-size="15" font-weight="600" fill="#1E293B">نقطهٔ برش مرجع</text>
43
- <text x="843" y="468" text-anchor="start" font-size="13" fill="#334155">نمرهٔ کل <tspan font-weight="700">6</tspan> — فقط اطلاعات مرجع برای متخصص؛ نمرهٔ این پاسخ‌نامه با آن طبقه‌بندی نمی‌شود.</text>
44
- <text x="843" y="496" text-anchor="start" font-size="13" fill="#334155">منبع: مطالعهٔ روایی تشخیصیِ نسخهٔ یونانی، در برابر تشخیص بی‌خوابی غیرارگانیک در <tspan class="eng-font" font-family="Dana">ICD-10</tspan>.</text>
45
- <text x="843" y="520" text-anchor="start" font-size="13" fill="#334155">جامعه: نمونهٔ بالینی/مختلط آتن، 299 نفر.</text>
46
- <text x="843" y="544" text-anchor="start" font-size="13" fill="#334155">سال: 2003.</text>
47
- <text x="843" y="572" text-anchor="start" font-size="13" font-weight="600" fill="#334155">این عدد به نسخهٔ فارسی و به فرم پنج‌گویه‌ای تعلق ندارد.</text>
21
+ {{! ===================== Half-ring gauge (Figma node 5405:146150) ===================== }}
22
+ <g transform="translate({{total.x}}, {{total.y}})">
23
+ {{gauge 125 87.5 (object tl=6 tr=6 bl=6 br=6) (object start=(toRad 180) end=(toRad 0)) false fill="#F1F5F9"}}
24
+ {{#if total.mark}}{{gauge 125 87.5 (object tl=6 tr=0 bl=6 br=0) (object start=(toRad 180) end=total.zeta) false clip-path="url(#aisGaugeTrack)" fill="url(#aisGauge)"}}{{/if}}
25
+ </g>
26
+
27
+ <text x="124.5" y="18" text-anchor="middle" font-size="18" font-weight="500" fill="#4338CA">{{total.title}}</text>
28
+
29
+ <text x="125" y="141" text-anchor="middle" font-size="28" font-weight="600" fill="#4F46E5" direction="ltr">٪ {{total.pct}}</text>
30
+ <text x="125" y="166" text-anchor="middle" font-size="18" font-weight="500" fill="#64748B">{{total.mark}} از {{total.max}}</text>
31
+
32
+ <text x="18.5" y="186" text-anchor="middle" font-size="14" font-weight="500" fill="#64748B">0</text>
33
+ <text x="232.5" y="186" text-anchor="middle" font-size="14" font-weight="500" fill="#64748B" direction="ltr">٪ 100</text>
48
34
 
49
35
  {{else}}
50
36
 
51
- {{! ===================== No result (all-or-nothing) ===================== }}
52
- <rect x="181.5" y="237.5" width="500" height="199" rx="12" fill="#F8FAFC" stroke="#E2E8F0"/>
53
- <circle cx="431.5" cy="288" r="17" fill="none" stroke="#64748B" stroke-width="2"/>
54
- <line x1="431.5" y1="279" x2="431.5" y2="291" stroke="#64748B" stroke-width="2.5" stroke-linecap="round"/>
55
- <circle cx="431.5" cy="297.5" r="1.6" fill="#64748B"/>
56
- <text x="431.5" y="344" text-anchor="middle" font-size="17" font-weight="600" fill="#1E293B">نمره تولید نشد</text>
57
- <text x="431.5" y="376" text-anchor="middle" font-size="13" fill="#64748B">پاسخ ناقص یا نامعتبر است؛ هیچ نمره‌ای، حتی نمرهٔ جزئی، گزارش نمی‌شود.</text>
37
+ {{! ===================== No result (all-or-nothing), centred on the Chart ===================== }}
38
+ <g transform="translate(-306.5, -243.5)">
39
+ <rect x="181.5" y="237.5" width="500" height="199" rx="12" fill="#F8FAFC" stroke="#E2E8F0"/>
40
+ <circle cx="431.5" cy="288" r="17" fill="none" stroke="#64748B" stroke-width="2"/>
41
+ <line x1="431.5" y1="279" x2="431.5" y2="291" stroke="#64748B" stroke-width="2.5" stroke-linecap="round"/>
42
+ <circle cx="431.5" cy="297.5" r="1.6" fill="#64748B"/>
43
+ <text x="431.5" y="344" text-anchor="middle" font-size="17" font-weight="600" fill="#1E293B">نمره تولید نشد</text>
44
+ <text x="431.5" y="376" text-anchor="middle" font-size="13" fill="#64748B">پاسخ ناقص یا نامعتبر است؛ هیچ نمره‌ای، حتی نمرهٔ جزئی، گزارش نمی‌شود.</text>
45
+ </g>
58
46
 
59
47
  {{/if}}
60
48