@baravak/risloo-profile-cli 4.46.1 → 4.46.3
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/.claude/settings.local.json +9 -0
- package/CLAUDE.md +188 -0
- package/a.json +4805 -0
- package/package.json +1 -1
- package/src/publish/json/profiles/BSCT93.json +495 -0
- package/src/publish/json/profiles/BSCT93_t1.json +512 -0
- package/src/publish/json/profiles/BSCT93_t2.json +512 -0
- package/src/samples/BSCT93.js +85 -0
- package/src/samples/FRHPT9A.js +1 -9
- package/views/profiles/samples/BSCT93.hbs +99 -0
- package/views/profiles/samples/FRHPT93_1.hbs +2 -0
- package/views/profiles/samples/FRHPT9A.hbs +12 -22
package/CLAUDE.md
ADDED
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
# CLAUDE.md
|
|
2
|
+
|
|
3
|
+
## Project Overview
|
|
4
|
+
|
|
5
|
+
**@baravak/risloo-profile-cli** is a Node.js CLI tool that converts psychological test result JSON data into SVG and PNG profile/report images. It supports 81+ psychological questionnaires with Persian/Farsi labeling.
|
|
6
|
+
|
|
7
|
+
Published as npm package: `@baravak/risloo-profile-cli` (v4.46.2, MIT)
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## Directory Structure
|
|
12
|
+
|
|
13
|
+
```
|
|
14
|
+
risloo-extractor-app/
|
|
15
|
+
├── bin/
|
|
16
|
+
│ └── risloo.js # CLI entry point
|
|
17
|
+
├── src/
|
|
18
|
+
│ ├── cli.js # Commander.js command definitions
|
|
19
|
+
│ ├── cli-commands/
|
|
20
|
+
│ │ ├── Executor.js # Base executor class
|
|
21
|
+
│ │ ├── ExtractExecutor.js # Profile/report/sheet extraction logic
|
|
22
|
+
│ │ ├── GiftExecutor.js # Gift card generation
|
|
23
|
+
│ │ └── utilities/ # BaseOps, Benchmarker, Response, Errors, Status codes
|
|
24
|
+
│ ├── Profile.js # Base Profile class (math utilities)
|
|
25
|
+
│ ├── Gift.js # Gift card class
|
|
26
|
+
│ ├── samples/ # JS controller files — one per profile (e.g. BSCT93.js)
|
|
27
|
+
│ ├── handlebars/
|
|
28
|
+
│ │ ├── init.js # Handlebars initialization
|
|
29
|
+
│ │ ├── helpers.js # Entry point for all helpers
|
|
30
|
+
│ │ ├── helpers/ # 45+ geometry helper modules
|
|
31
|
+
│ │ ├── importPartials.js # Partials loader
|
|
32
|
+
│ │ └── polygon.js # Polygon drawing logic
|
|
33
|
+
│ ├── helpers/ # Math helpers (angleABS, polarXY, gauge, polygonXY)
|
|
34
|
+
│ ├── qrcode/ # QR code generation & rendering
|
|
35
|
+
│ └── publish/
|
|
36
|
+
│ ├── json/profiles/ # Template JSON per sample (e.g. BSCT93.json)
|
|
37
|
+
│ ├── json/gift/ # Gift template data
|
|
38
|
+
│ ├── test.js # Auto-test all samples
|
|
39
|
+
│ └── bot.js # Post-publish automation
|
|
40
|
+
├── views/
|
|
41
|
+
│ ├── profiles/samples/ # Handlebars SVG templates (.hbs)
|
|
42
|
+
│ └── gift.hbs
|
|
43
|
+
└── package.json
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## Commands
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
# Test a single profile (generates SVG in ./temp)
|
|
52
|
+
./bin/risloo.js E <NAME> -d ./src/publish/json/profiles/<NAME>.json -a ./temp
|
|
53
|
+
|
|
54
|
+
# Watch mode
|
|
55
|
+
risloo extract <NAME> profile -i local -d ./src/publish/json/profiles/<NAME>.json -o local -a ./temp -w
|
|
56
|
+
|
|
57
|
+
# Generate gift card
|
|
58
|
+
risloo gift -i raw-json -d '{"code":"..."}' -o local -a ./output
|
|
59
|
+
|
|
60
|
+
# Test all samples
|
|
61
|
+
npm test # → node ./src/publish/test.js
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
## Profile Development Workflow (Figma → Code)
|
|
67
|
+
|
|
68
|
+
### Design Source
|
|
69
|
+
|
|
70
|
+
Each profile is designed in Figma. Per task, one or both of the following may be provided:
|
|
71
|
+
|
|
72
|
+
- **Figma design file** — connect via Figma MCP to read layer dimensions and structure. The relevant layer is named **Chart**.
|
|
73
|
+
- **Figma handoff file** — contains additional implementation notes and specs. May state that this profile is similar to an existing one (e.g. "similar to BSCT93 with these changes"). In that case: find the referenced profile's JS + HBS files, use them as the base, and apply only the described differences.
|
|
74
|
+
|
|
75
|
+
> **Important:** The Figma MCP reads text layers only — it does NOT read Figma comments. Designers often leave critical specs (thresholds, coefficients, pixel values) as Figma comments. Always ask the user to share designer comments before finalizing the plan.
|
|
76
|
+
|
|
77
|
+
### What the HBS Draws
|
|
78
|
+
|
|
79
|
+
The HBS file draws **only the Chart layer**. The library automatically injects the header (test name, dates, client info) and sidebar (logo, room info, prerequisites) via the `{{#> layout}}` wrapper. Never include these in the HBS.
|
|
80
|
+
|
|
81
|
+
### SVG Coordinate System
|
|
82
|
+
|
|
83
|
+
Since this is SVG, coordinate origin matters for correctness across **all** inputs:
|
|
84
|
+
|
|
85
|
+
- **x=0** = left edge, increases rightward
|
|
86
|
+
- **y=0** = top edge, increases downward
|
|
87
|
+
- Horizontal bars fill left → right: `{{bar (BAR_WIDTH * factor.p) height ...}}`
|
|
88
|
+
- Vertical total bar fills bottom → up via the transform trick: `translate(0, barHeight - barHeight * p)`
|
|
89
|
+
- All positions must remain stable for edge-case inputs: 0% score, 100% score, missing data
|
|
90
|
+
|
|
91
|
+
### Inside/Outside Bar Text
|
|
92
|
+
|
|
93
|
+
When rendering percentage text on a bar, check if the bar is wide enough to contain the text. The threshold is specified by the designer per profile (in Figma comments):
|
|
94
|
+
|
|
95
|
+
```hbs
|
|
96
|
+
{{#if (boolean factor.percentage '<=' THRESHOLD)}}
|
|
97
|
+
<text x="{{math (math BAR_WIDTH '*' factor.p) '+' 6}}" ...>{{factor.percentage}} ٪</text>
|
|
98
|
+
{{else}}
|
|
99
|
+
<text x="{{math (math BAR_WIDTH '*' factor.p) '-' 4}}" ...>{{factor.percentage}} ٪</text>
|
|
100
|
+
{{/if}}
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### File Structure per Profile
|
|
104
|
+
|
|
105
|
+
Each profile (نیمرخ) consists of three files:
|
|
106
|
+
|
|
107
|
+
| File | Path | Role |
|
|
108
|
+
|---|---|---|
|
|
109
|
+
| JSON template | `src/publish/json/profiles/<NAME>.json` | Test data / input template |
|
|
110
|
+
| JS controller | `src/samples/<NAME>.js` | Data processing, geometry config |
|
|
111
|
+
| HBS template | `views/profiles/samples/<NAME>.hbs` | SVG rendering |
|
|
112
|
+
|
|
113
|
+
If a profile has **multiple pages**, the HBS files are named with suffixes:
|
|
114
|
+
- `<NAME>_1.hbs`, `<NAME>_2.hbs`, `<NAME>_3.hbs`, ...
|
|
115
|
+
|
|
116
|
+
### Dimensions & Padding Convention
|
|
117
|
+
|
|
118
|
+
The chart drawing must fit within the **Main** layer in Figma.
|
|
119
|
+
|
|
120
|
+
- Read the **Main** layer dimensions from Figma
|
|
121
|
+
- `profile.padding` = 20 units per side
|
|
122
|
+
- The `x` and `y` values (drawing area) = Main dimensions minus one padding unit each:
|
|
123
|
+
- e.g. Main = 104×255 → `{ x: 84, y: 235 }`
|
|
124
|
+
|
|
125
|
+
The `dimensions` property in the JS controller adds padding back on both sides of the **Chart** layer dimensions:
|
|
126
|
+
|
|
127
|
+
```js
|
|
128
|
+
get dimensions() {
|
|
129
|
+
return {
|
|
130
|
+
width: 736 + 2 * this.padding.x, // Chart layer width from Figma
|
|
131
|
+
height: 254 + 2 * this.padding.y, // Chart layer height from Figma
|
|
132
|
+
};
|
|
133
|
+
},
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
### Data / Labels Convention
|
|
137
|
+
|
|
138
|
+
All data needed for rendering goes in the `labels` property of the JS controller.
|
|
139
|
+
|
|
140
|
+
The data structure is typically derived from a Python script that outputs a JSON file — flattened with `_` separators — which maps source fields to their `labels` keys.
|
|
141
|
+
|
|
142
|
+
```js
|
|
143
|
+
get labels() {
|
|
144
|
+
return {
|
|
145
|
+
// flat_key: value
|
|
146
|
+
score_total: ...,
|
|
147
|
+
subscale_anxiety: ...,
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
---
|
|
153
|
+
|
|
154
|
+
## Tech Stack
|
|
155
|
+
|
|
156
|
+
| Area | Technology |
|
|
157
|
+
|---|---|
|
|
158
|
+
| Language | JavaScript (Node.js, no build step) |
|
|
159
|
+
| CLI | Commander.js |
|
|
160
|
+
| Templating | Handlebars (SVG generation) |
|
|
161
|
+
| Image output | Sharp (SVG → PNG) |
|
|
162
|
+
| Dates | Moment.js + moment-jalaali (Persian calendar) |
|
|
163
|
+
| QR codes | qrcode |
|
|
164
|
+
| File watching | Chokidar |
|
|
165
|
+
| Package manager | Yarn |
|
|
166
|
+
| Design source | Figma (via MCP) |
|
|
167
|
+
|
|
168
|
+
---
|
|
169
|
+
|
|
170
|
+
## Naming Conventions
|
|
171
|
+
|
|
172
|
+
- `items` — array of data elements to draw
|
|
173
|
+
- `raw` — total/aggregate element
|
|
174
|
+
- `ticks` — graduation marks on profiles
|
|
175
|
+
- `s` suffix — denotes arrays (not `Arr`)
|
|
176
|
+
- Sample names: uppercase acronym + year (e.g. `BSCT93`, `BEQI93`, `16PF93`)
|
|
177
|
+
- Dataset score structure: `dataset.score = [{ label: { eng, ... }, mark }]`
|
|
178
|
+
|
|
179
|
+
---
|
|
180
|
+
|
|
181
|
+
## Publishing
|
|
182
|
+
|
|
183
|
+
```bash
|
|
184
|
+
npm version <patch|minor|major>
|
|
185
|
+
npm publish
|
|
186
|
+
# prepublishOnly: npm test
|
|
187
|
+
# postpublish: npm run bot
|
|
188
|
+
```
|