@baravak/risloo-profile-cli 3.1.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/.github/workflows/push.yml +14 -0
- package/.prettierrc +16 -0
- package/.yarn/releases/yarn-1.22.19.cjs +147529 -0
- package/.yarnrc.yml +1 -0
- package/README.md +98 -0
- package/bin/risloo.js +9 -0
- package/package.json +44 -0
- package/src/Gift.js +29 -0
- package/src/Profile.js +405 -0
- package/src/cli-commands/Executor.js +118 -0
- package/src/cli-commands/ExtractExecutor.js +194 -0
- package/src/cli-commands/GiftExecutor.js +56 -0
- package/src/cli-commands/utilities/BaseOps.js +71 -0
- package/src/cli-commands/utilities/Benchmarker.js +88 -0
- package/src/cli-commands/utilities/CustomErrors.js +14 -0
- package/src/cli-commands/utilities/Response.js +59 -0
- package/src/cli-commands/utilities/STATUSES.js +16 -0
- package/src/cli-commands/utilities/Status.js +9 -0
- package/src/cli.js +125 -0
- package/src/handlebars/helpers/abs.js +8 -0
- package/src/handlebars/helpers/addCommas.js +8 -0
- package/src/handlebars/helpers/array.js +8 -0
- package/src/handlebars/helpers/assignGlobal.js +9 -0
- package/src/handlebars/helpers/boolean.js +19 -0
- package/src/handlebars/helpers/ceil.js +8 -0
- package/src/handlebars/helpers/concat.js +8 -0
- package/src/handlebars/helpers/cos.js +8 -0
- package/src/handlebars/helpers/displacePoint.js +11 -0
- package/src/handlebars/helpers/ellipsisChars.js +10 -0
- package/src/handlebars/helpers/ellipsisLines.js +11 -0
- package/src/handlebars/helpers/first.js +11 -0
- package/src/handlebars/helpers/floor.js +8 -0
- package/src/handlebars/helpers/forLoop.js +15 -0
- package/src/handlebars/helpers/getArrOfProp.js +8 -0
- package/src/handlebars/helpers/isArray.js +8 -0
- package/src/handlebars/helpers/join.js +10 -0
- package/src/handlebars/helpers/last.js +11 -0
- package/src/handlebars/helpers/lineWrap.js +28 -0
- package/src/handlebars/helpers/math.js +24 -0
- package/src/handlebars/helpers/modulo.js +8 -0
- package/src/handlebars/helpers/normalizeAngle.js +7 -0
- package/src/handlebars/helpers/object.js +8 -0
- package/src/handlebars/helpers/objectEntries.js +8 -0
- package/src/handlebars/helpers/polarToCartesian.js +14 -0
- package/src/handlebars/helpers/prepend.js +10 -0
- package/src/handlebars/helpers/profiles/bar.js +45 -0
- package/src/handlebars/helpers/profiles/calcGaugeSidePoints.js +34 -0
- package/src/handlebars/helpers/profiles/gauge.js +61 -0
- package/src/handlebars/helpers/profiles/polygon.js +40 -0
- package/src/handlebars/helpers/reverse.js +9 -0
- package/src/handlebars/helpers/roundToTwo.js +8 -0
- package/src/handlebars/helpers/setVar.js +8 -0
- package/src/handlebars/helpers/sin.js +8 -0
- package/src/handlebars/helpers/split.js +8 -0
- package/src/handlebars/helpers/tan.js +8 -0
- package/src/handlebars/helpers/ternary.js +9 -0
- package/src/handlebars/helpers/toDeg.js +8 -0
- package/src/handlebars/helpers/toRad.js +8 -0
- package/src/handlebars/helpers/withGroup.js +20 -0
- package/src/handlebars/helpers/wrapOnNewline.js +11 -0
- package/src/handlebars/helpers.js +86 -0
- package/src/handlebars/importPartials.js +40 -0
- package/src/handlebars/init.js +15 -0
- package/src/publish/bot.js +91 -0
- package/src/publish/json/gift/gift.json +16 -0
- package/src/publish/json/profiles/16PF93.json +201 -0
- package/src/publish/json/profiles/AEQ93.json +96 -0
- package/src/publish/json/profiles/AMS93.json +102 -0
- package/src/publish/json/profiles/AMS9A.json +102 -0
- package/src/publish/json/profiles/BAOMEIS93.json +99 -0
- package/src/publish/json/profiles/BEQI93.json +1589 -0
- package/src/publish/json/profiles/CAATS93.json +11355 -0
- package/src/publish/json/profiles/CADS93.json +351 -0
- package/src/publish/json/profiles/CARSP93.json +96 -0
- package/src/publish/json/profiles/CERQ93.json +106 -0
- package/src/publish/json/profiles/CRAAS93.json +98 -0
- package/src/publish/json/profiles/CSI93.json +143 -0
- package/src/publish/json/profiles/DSWLS93.json +93 -0
- package/src/publish/json/profiles/EMSS93.json +116 -0
- package/src/publish/json/profiles/FACES93.json +106 -0
- package/src/publish/json/profiles/FTEPT93.json +102 -0
- package/src/publish/json/profiles/GMIT93.json +98 -0
- package/src/publish/json/profiles/HPL93.json +102 -0
- package/src/publish/json/profiles/IBT93.json +106 -0
- package/src/publish/json/profiles/IUS93.json +93 -0
- package/src/publish/json/profiles/JCSI93.json +102 -0
- package/src/publish/json/profiles/JPFQ93.json +1 -0
- package/src/publish/json/profiles/KJGI93.json +100 -0
- package/src/publish/json/profiles/LMIQ93.json +109 -0
- package/src/publish/json/profiles/MMFAD93.json +103 -0
- package/src/publish/json/profiles/MMFAD9A.json +103 -0
- package/src/publish/json/profiles/MOCI93.json +100 -0
- package/src/publish/json/profiles/OBQ4493.json +96 -0
- package/src/publish/json/profiles/PIES93.json +104 -0
- package/src/publish/json/profiles/PIES9A.json +104 -0
- package/src/publish/json/profiles/PMCIEF93.json +1 -0
- package/src/publish/json/profiles/PSWQ93.json +97 -0
- package/src/publish/json/profiles/RIASEC93.json +2511 -0
- package/src/publish/json/profiles/SAFE93.json +110 -0
- package/src/publish/json/profiles/SASQ93.json +92 -0
- package/src/publish/json/profiles/SCASP93.json +611 -0
- package/src/publish/json/profiles/SDCAQ93.json +96 -0
- package/src/publish/json/profiles/STAIY93.json +98 -0
- package/src/publish/json/profiles/WAQ93.json +100 -0
- package/src/publish/json/profiles/YBOCS93.json +1322 -0
- package/src/publish/json/profiles/empty.json +139 -0
- package/src/publish/new-version.hbs +11 -0
- package/src/publish/test.js +109 -0
- package/src/qrcode/qrCodeGenerator.js +14 -0
- package/src/qrcode/qrRender.js +229 -0
- package/src/samples/16PF93.js +158 -0
- package/src/samples/AEQ93.js +121 -0
- package/src/samples/AMS93.js +139 -0
- package/src/samples/AMS9A.js +9 -0
- package/src/samples/BAOMEIS93.js +146 -0
- package/src/samples/BEQI93.js +255 -0
- package/src/samples/CAATS93.js +218 -0
- package/src/samples/CADS93.js +161 -0
- package/src/samples/CARSP93.js +134 -0
- package/src/samples/CERQ93.js +195 -0
- package/src/samples/CRAAS93.js +141 -0
- package/src/samples/CSI93.js +315 -0
- package/src/samples/DSWLS93.js +112 -0
- package/src/samples/EMSS93.js +178 -0
- package/src/samples/FACES93.js +225 -0
- package/src/samples/FTEPT93.js +167 -0
- package/src/samples/GMIT93.js +142 -0
- package/src/samples/HPL93.js +132 -0
- package/src/samples/IBT93.js +99 -0
- package/src/samples/IUS93.js +204 -0
- package/src/samples/JCSI93.js +174 -0
- package/src/samples/JPFQ93.js +74 -0
- package/src/samples/KJGI93.js +136 -0
- package/src/samples/LMIQ93.js +188 -0
- package/src/samples/MMFAD93.js +135 -0
- package/src/samples/MMFAD9A.js +31 -0
- package/src/samples/MOCI93.js +128 -0
- package/src/samples/OBQ4493.js +132 -0
- package/src/samples/PIES93.js +228 -0
- package/src/samples/PIES9A.js +32 -0
- package/src/samples/PMCIEF93.js +64 -0
- package/src/samples/PSWQ93.js +126 -0
- package/src/samples/RIASEC93.js +144 -0
- package/src/samples/SAFE93.js +64 -0
- package/src/samples/SASQ93.js +130 -0
- package/src/samples/SCASP93.js +207 -0
- package/src/samples/SDCAQ93.js +174 -0
- package/src/samples/STAIY93.js +159 -0
- package/src/samples/WAQ93.js +208 -0
- package/src/samples/YBOCS93.js +583 -0
- package/src/samples/empty.js +53 -0
- package/views/gift.hbs +160 -0
- package/views/profiles/fonts.css +18 -0
- package/views/profiles/layout.hbs +27 -0
- package/views/profiles/samples/16PF93.hbs +54 -0
- package/views/profiles/samples/AEQ93.hbs +31 -0
- package/views/profiles/samples/AMS93.hbs +97 -0
- package/views/profiles/samples/AMS9A.hbs +1 -0
- package/views/profiles/samples/BAOMEIS93.hbs +48 -0
- package/views/profiles/samples/BEQI93.hbs +118 -0
- package/views/profiles/samples/CAATS93.hbs +251 -0
- package/views/profiles/samples/CADS93.hbs +104 -0
- package/views/profiles/samples/CARSP93.hbs +26 -0
- package/views/profiles/samples/CERQ93.hbs +115 -0
- package/views/profiles/samples/CRAAS93.hbs +88 -0
- package/views/profiles/samples/CSI93_1.hbs +110 -0
- package/views/profiles/samples/CSI93_2.hbs +76 -0
- package/views/profiles/samples/DSWLS93.hbs +26 -0
- package/views/profiles/samples/EMSS93.hbs +101 -0
- package/views/profiles/samples/FACES93_1.hbs +107 -0
- package/views/profiles/samples/FACES93_2.hbs +51 -0
- package/views/profiles/samples/FTEPT93.hbs +67 -0
- package/views/profiles/samples/GMIT93.hbs +45 -0
- package/views/profiles/samples/HPL93.hbs +36 -0
- package/views/profiles/samples/IBT93.hbs +67 -0
- package/views/profiles/samples/IUS93.hbs +123 -0
- package/views/profiles/samples/JCSI93.hbs +65 -0
- package/views/profiles/samples/JPFQ93.hbs +44 -0
- package/views/profiles/samples/KJGI93.hbs +57 -0
- package/views/profiles/samples/LMIQ93.hbs +82 -0
- package/views/profiles/samples/MMFAD93.hbs +35 -0
- package/views/profiles/samples/MMFAD9A.hbs +1 -0
- package/views/profiles/samples/MOCI93.hbs +60 -0
- package/views/profiles/samples/OBQ4493.hbs +61 -0
- package/views/profiles/samples/PIES93.hbs +67 -0
- package/views/profiles/samples/PIES9A.hbs +1 -0
- package/views/profiles/samples/PMCIEF93.hbs +8 -0
- package/views/profiles/samples/PSWQ93.hbs +32 -0
- package/views/profiles/samples/RIASEC93.hbs +38 -0
- package/views/profiles/samples/SAFE93.hbs +118 -0
- package/views/profiles/samples/SASQ93.hbs +45 -0
- package/views/profiles/samples/SCASP93.hbs +94 -0
- package/views/profiles/samples/SDCAQ93.hbs +68 -0
- package/views/profiles/samples/STAIY93.hbs +67 -0
- package/views/profiles/samples/WAQ93.hbs +74 -0
- package/views/profiles/samples/YBOCS93_1.hbs +96 -0
- package/views/profiles/samples/YBOCS93_2.hbs +115 -0
- package/views/profiles/samples/YBOCS93_3.hbs +93 -0
- package/views/profiles/samples/empty.hbs +10 -0
- package/views/profiles/sidebar.hbs +193 -0
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
const { Profile, FS } = require("../Profile");
|
|
2
|
+
|
|
3
|
+
class DSWLS93 extends Profile {
|
|
4
|
+
// Number of pages
|
|
5
|
+
static pages = 1;
|
|
6
|
+
|
|
7
|
+
// Labels of the sample
|
|
8
|
+
labels = {
|
|
9
|
+
L1: { eng: "raw", fr: "نمره کل" },
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
profileSpec = {
|
|
13
|
+
/* "sample" determines some important info about the sample and profile */
|
|
14
|
+
/* Default prerequisites: 1. gender, 2. age, 3. education */
|
|
15
|
+
/* "prerequisites" is synonym to "fields" in our program */
|
|
16
|
+
sample: {
|
|
17
|
+
name: "پرسشنامه رضایت از زندگی داینر" /* Name of the sample */,
|
|
18
|
+
multiProfile: false /* Whether the sample has multiple profiles or not */,
|
|
19
|
+
questions: false /* Determines whether to get questions from inital dataset or not */,
|
|
20
|
+
defaultFields: true /* Determines whether to have default prerequisites in the profile or not */,
|
|
21
|
+
fields: ["marital_status"] /* In case you want to get some additional fields and show in the profile */,
|
|
22
|
+
},
|
|
23
|
+
/* "profile" determines the dimensions of the drawn profile (to be used in svg tag viewbox) */
|
|
24
|
+
/* calculating its dimensions carefully is of great importance */
|
|
25
|
+
profile: {
|
|
26
|
+
get dimensions() {
|
|
27
|
+
return {
|
|
28
|
+
width: 460 + 2 * this.padding.x,
|
|
29
|
+
height: 460 + 2 * this.padding.y,
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
padding: {
|
|
33
|
+
x: 0,
|
|
34
|
+
y: 127,
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
/* "raw" is the general term used for total data element in the profile */
|
|
38
|
+
raw: {
|
|
39
|
+
maxValue: 35 /* Maximum value of raw mark provided by the dataset */,
|
|
40
|
+
fill: "#16A34A" /* Color used in the raw element */,
|
|
41
|
+
circle: {
|
|
42
|
+
R: 230 /* Radius of the outer circle of the raw element */,
|
|
43
|
+
r: 160 /* Radius of the inner circle of the raw element */,
|
|
44
|
+
brs: {
|
|
45
|
+
tl: 20 /* Top left border radius */,
|
|
46
|
+
bl: 20 /* Bottom left border radius */,
|
|
47
|
+
tr: 20 /* Top right border radius */,
|
|
48
|
+
br: 20 /* Bottom right border radius */,
|
|
49
|
+
} /* Border radiuses at each end of the gauge of the raw element */,
|
|
50
|
+
angles: {
|
|
51
|
+
start: FS.toRadians(-90),
|
|
52
|
+
end: FS.toRadians(180),
|
|
53
|
+
} /* Angles of each end of the raw element */,
|
|
54
|
+
direction: false /* Clockwise direction for the raw gauge element */,
|
|
55
|
+
get totalAngle() {
|
|
56
|
+
return this.direction
|
|
57
|
+
? 2 * Math.PI - (this.angles.end - this.angles.start)
|
|
58
|
+
: this.angles.end - this.angles.start;
|
|
59
|
+
},
|
|
60
|
+
},
|
|
61
|
+
ticks: {
|
|
62
|
+
num: 2 /* Number of ticks */,
|
|
63
|
+
number: {
|
|
64
|
+
offset: 25 /* Offset from the line */,
|
|
65
|
+
},
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
/* "labels" part which has to be provided for each profile */
|
|
69
|
+
labels: Object.values(this.labels),
|
|
70
|
+
};
|
|
71
|
+
إ;
|
|
72
|
+
|
|
73
|
+
constructor(dataset, options, config = {}) {
|
|
74
|
+
super();
|
|
75
|
+
this._init(dataset, options, config);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
_calcContext() {
|
|
79
|
+
const {
|
|
80
|
+
spec: { parameters: spec },
|
|
81
|
+
dataset,
|
|
82
|
+
} = this;
|
|
83
|
+
|
|
84
|
+
const { raw: rawSpec } = spec;
|
|
85
|
+
|
|
86
|
+
const rawData = dataset.score[0];
|
|
87
|
+
|
|
88
|
+
// Calculate Ticks Numbers Array for Raw
|
|
89
|
+
const rawTicksNumbers = FS.createArithmeticSequence(
|
|
90
|
+
rawSpec.maxValue,
|
|
91
|
+
-rawSpec.maxValue / (rawSpec.ticks.num - 1),
|
|
92
|
+
rawSpec.ticks.num
|
|
93
|
+
).reverse();
|
|
94
|
+
|
|
95
|
+
// Gather Required Info for Raw
|
|
96
|
+
const raw = {
|
|
97
|
+
label: rawData.label,
|
|
98
|
+
mark: rawData.mark,
|
|
99
|
+
zeta: (rawData.mark / rawSpec.maxValue) * rawSpec.circle.totalAngle + rawSpec.circle.angles.start,
|
|
100
|
+
fill: rawSpec.fill,
|
|
101
|
+
opacity: FS.roundTo2(0.5 * (1 + rawData.mark / rawSpec.maxValue)),
|
|
102
|
+
ticks: rawTicksNumbers.map((tick) => ({
|
|
103
|
+
number: tick,
|
|
104
|
+
angle: (tick / rawSpec.maxValue) * rawSpec.circle.totalAngle + rawSpec.circle.angles.start,
|
|
105
|
+
})),
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
return [{ raw }];
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
module.exports = DSWLS93;
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
const { Profile, FS } = require("../Profile");
|
|
2
|
+
|
|
3
|
+
class EMSS93 extends Profile {
|
|
4
|
+
// Number of pages
|
|
5
|
+
static pages = 1;
|
|
6
|
+
|
|
7
|
+
// Labels of the sample
|
|
8
|
+
labels = {
|
|
9
|
+
L1: { eng: "raw", fr: "نمره کل" },
|
|
10
|
+
L2: { eng: "t_score", fr: "نمره t" },
|
|
11
|
+
L3: { eng: "t_score_summary", fr: "خلاصه نمره t" },
|
|
12
|
+
L4: { eng: "personality_issues", fr: "موضوعات شخصیتی" },
|
|
13
|
+
L5: { eng: "religious_orientation", fr: "جهتگیری مذهبی" },
|
|
14
|
+
L6: { eng: "family_and_friends", fr: "اقوام و دوستان" },
|
|
15
|
+
L7: { eng: "children_and_marriage", fr: "ازدواج و فرزندان" },
|
|
16
|
+
L8: { eng: "sexual_relationship", fr: "روابط جنسی" },
|
|
17
|
+
L9: { eng: "leisure_activities", fr: "فعالیتهای اوقات فراغت" },
|
|
18
|
+
L10: { eng: "financial_management", fr: "مدیریت مالی" },
|
|
19
|
+
L11: { eng: "Conflict_resolution", fr: "حل تعارض" },
|
|
20
|
+
L12: { eng: "marital_communication", fr: "ارتباط زناشویی" },
|
|
21
|
+
L13: { eng: "personality_issues_interpretation", fr: "تفسیر موضوعات شخصیتی" },
|
|
22
|
+
L14: { eng: "religious_orientation_interpretation", fr: "تفسیر جهتگیری مذهبی" },
|
|
23
|
+
L15: { eng: "family_and_friends_interpretation", fr: "تفسیر اقوام و دوستان" },
|
|
24
|
+
L16: { eng: "children_and_marriage_interpretation", fr: "تفسیر ازدواج و فرزندان" },
|
|
25
|
+
L17: { eng: "sexual_relationship_interpretation", fr: "تفسیر روابط جنسی" },
|
|
26
|
+
L18: { eng: "leisure_activities_interpretation", fr: "تفسیر فعالیتهای اوقات فراغت" },
|
|
27
|
+
L19: { eng: "financial_management_interpretation", fr: "تفسیر مدیریت مالی" },
|
|
28
|
+
L20: { eng: "Conflict_resolution_interpretation", fr: "تفسیر حل تعارض" },
|
|
29
|
+
L21: { eng: "marital_communication_interpretation", fr: "تفسیر ارتباط زناشویی" },
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
profileSpec = {
|
|
33
|
+
/* "sample" determines some important info about the sample and profile */
|
|
34
|
+
/* Default prerequisites: 1. gender, 2. age, 3. education */
|
|
35
|
+
/* "prerequisites" is synonym to "fields" in our program */
|
|
36
|
+
sample: {
|
|
37
|
+
name: "پرسشنامه رضایت زناشویی انریچ ۴۷ سؤالی" /* Name of the sample */,
|
|
38
|
+
multiProfile: false /* Whether the sample has multiple profiles or not */,
|
|
39
|
+
questions: false /* Determines whether to get questions from inital dataset or not */,
|
|
40
|
+
defaultFields: true /* Determines whether to have default prerequisites in the profile or not */,
|
|
41
|
+
fields: ["marital_status"] /* In case you want to get some additional fields and show in the profile */,
|
|
42
|
+
},
|
|
43
|
+
/* "profile" determines the dimensions of the drawn profile (to be used in svg tag viewbox) */
|
|
44
|
+
/* calculating its dimensions carefully is of great importance */
|
|
45
|
+
profile: {
|
|
46
|
+
get dimensions() {
|
|
47
|
+
return {
|
|
48
|
+
width: 770 + 2 * this.padding.x,
|
|
49
|
+
height: 662 + 2 * this.padding.y,
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
padding: {
|
|
53
|
+
x: 0,
|
|
54
|
+
y: 20,
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
raw: {
|
|
58
|
+
stops: [11, 29, 40, 60, 70, 72],
|
|
59
|
+
rect: {
|
|
60
|
+
width: 30,
|
|
61
|
+
brs: {
|
|
62
|
+
tl: 0 /* Top left border radius */,
|
|
63
|
+
bl: 0 /* Bottom left border radius */,
|
|
64
|
+
tr: 4 /* Top right border radius */,
|
|
65
|
+
br: 4 /* Bottom right border radius */,
|
|
66
|
+
},
|
|
67
|
+
opacity: {
|
|
68
|
+
chosen: 0.8,
|
|
69
|
+
default: 0.3,
|
|
70
|
+
},
|
|
71
|
+
},
|
|
72
|
+
heightCoeff: 7.5,
|
|
73
|
+
label: {
|
|
74
|
+
shape: {
|
|
75
|
+
width: 61,
|
|
76
|
+
height: 46,
|
|
77
|
+
},
|
|
78
|
+
},
|
|
79
|
+
},
|
|
80
|
+
circles: {
|
|
81
|
+
n: 9 /* Number of vertices of the polygons */,
|
|
82
|
+
get theta() {
|
|
83
|
+
return (2 * Math.PI) / this.n;
|
|
84
|
+
},
|
|
85
|
+
startAngle: FS.toRadians(-70) /* Start angle of the polygon */,
|
|
86
|
+
radiuses: [50, 90, 130, 170, 210, 250] /* Radiuses array of circles */,
|
|
87
|
+
get wholeRadius() {
|
|
88
|
+
let len = this.radiuses.length;
|
|
89
|
+
return this.radiuses[len - 1] - this.radiuses[0];
|
|
90
|
+
},
|
|
91
|
+
},
|
|
92
|
+
/* "items" is the general term used for independent data elements to be drawn in the profile */
|
|
93
|
+
items: {
|
|
94
|
+
maxValues: {
|
|
95
|
+
[this.labels.L4.eng]: 30,
|
|
96
|
+
[this.labels.L5.eng]: 25,
|
|
97
|
+
[this.labels.L6.eng]: 25,
|
|
98
|
+
[this.labels.L7.eng]: 25,
|
|
99
|
+
[this.labels.L8.eng]: 25,
|
|
100
|
+
[this.labels.L9.eng]: 25,
|
|
101
|
+
[this.labels.L10.eng]: 25,
|
|
102
|
+
[this.labels.L11.eng]: 25,
|
|
103
|
+
[this.labels.L12.eng]: 30,
|
|
104
|
+
} /* Maximum values of marks provided by the dataset */,
|
|
105
|
+
circle: {
|
|
106
|
+
r: 50,
|
|
107
|
+
brs: {
|
|
108
|
+
tl: 4 /* Top left border radius */,
|
|
109
|
+
bl: 0 /* Bottom left border radius */,
|
|
110
|
+
tr: 4 /* Top right border radius */,
|
|
111
|
+
br: 0 /* Bottom right border radius */,
|
|
112
|
+
} /* Border radiuses at each end of the gauge of the items element */,
|
|
113
|
+
direction: false /* Clockwise direction for the items gauge element */,
|
|
114
|
+
totalAngle: FS.toRadians(32),
|
|
115
|
+
opacity: 0.8,
|
|
116
|
+
},
|
|
117
|
+
labels: {
|
|
118
|
+
offset: 50 /* Offset of the label from the vertice of the polygon */,
|
|
119
|
+
},
|
|
120
|
+
interprets: [
|
|
121
|
+
{ fill: "#EF4444", eng: "severe_dissatisfaction", fr: "نارضایتی شدید" },
|
|
122
|
+
{ fill: "#FBBF24", eng: "dissatisfaction", fr: "عدم رضایت" },
|
|
123
|
+
{ fill: "#9CA3AF", eng: "moderate_satisfaction", fr: "رضایت نسبی و متوسط" },
|
|
124
|
+
{ fill: "#38BDF8", eng: "severe_satisfaction", fr: "رضایت زیاد" },
|
|
125
|
+
{ fill: "#22C55E", eng: "extreme_satisfaction", fr: "رضایت فوقالعاده" },
|
|
126
|
+
],
|
|
127
|
+
},
|
|
128
|
+
/* "labels" part which has to be provided for each profile */
|
|
129
|
+
labels: Object.values(this.labels),
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
constructor(dataset, options, config = {}) {
|
|
133
|
+
super();
|
|
134
|
+
this._init(dataset, options, config);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
_calcContext() {
|
|
138
|
+
const {
|
|
139
|
+
spec: { parameters: spec },
|
|
140
|
+
dataset,
|
|
141
|
+
} = this;
|
|
142
|
+
|
|
143
|
+
// Deconstructing the Spec of the Profile
|
|
144
|
+
let { circles: circlesSpec, items: itemsSpec } = spec;
|
|
145
|
+
|
|
146
|
+
const rawData = dataset.score.slice(0, 3);
|
|
147
|
+
const itemsData = dataset.score.slice(3, 12);
|
|
148
|
+
const interpretsData = dataset.score.slice(12);
|
|
149
|
+
|
|
150
|
+
const raw = {
|
|
151
|
+
label: rawData[0].label,
|
|
152
|
+
mark: rawData[0].mark,
|
|
153
|
+
tScore: rawData[1].mark,
|
|
154
|
+
tScoreIndex: itemsSpec.interprets.findIndex((interpretation) => interpretation.eng === rawData[2].mark) + 1,
|
|
155
|
+
get fill() {
|
|
156
|
+
return itemsSpec.interprets[this.tScoreIndex - 1].fill;
|
|
157
|
+
},
|
|
158
|
+
};
|
|
159
|
+
|
|
160
|
+
const items = itemsData.map((data, dataIndex) => ({
|
|
161
|
+
label: data.label,
|
|
162
|
+
mark: data.mark,
|
|
163
|
+
angle: circlesSpec.startAngle - dataIndex * circlesSpec.theta,
|
|
164
|
+
tScore:
|
|
165
|
+
itemsSpec.interprets.findIndex((interpretation) => interpretation.eng === interpretsData[dataIndex].mark) + 1,
|
|
166
|
+
get radius() {
|
|
167
|
+
return circlesSpec.radiuses.slice(1)[this.tScore - 1];
|
|
168
|
+
},
|
|
169
|
+
get fill() {
|
|
170
|
+
return itemsSpec.interprets[this.tScore - 1].fill;
|
|
171
|
+
},
|
|
172
|
+
}));
|
|
173
|
+
|
|
174
|
+
return [{ raw, items }];
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
module.exports = EMSS93;
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
const { Profile } = require("../Profile");
|
|
2
|
+
|
|
3
|
+
class FACES93 extends Profile {
|
|
4
|
+
// Number of pages
|
|
5
|
+
static pages = 2;
|
|
6
|
+
|
|
7
|
+
// Labels of the sample
|
|
8
|
+
labels = {
|
|
9
|
+
L1: {
|
|
10
|
+
eng: "a",
|
|
11
|
+
fr: "منسجم متعادل",
|
|
12
|
+
},
|
|
13
|
+
L2: {
|
|
14
|
+
eng: "c",
|
|
15
|
+
fr: "از هم گسسته",
|
|
16
|
+
},
|
|
17
|
+
L3: {
|
|
18
|
+
eng: "d",
|
|
19
|
+
fr: "در هم تنیده",
|
|
20
|
+
},
|
|
21
|
+
L4: {
|
|
22
|
+
eng: "e",
|
|
23
|
+
fr: "خشک",
|
|
24
|
+
},
|
|
25
|
+
L5: {
|
|
26
|
+
eng: "f",
|
|
27
|
+
fr: "آشفته",
|
|
28
|
+
},
|
|
29
|
+
L6: {
|
|
30
|
+
eng: "b",
|
|
31
|
+
fr: "انعطافپذیر متعادل",
|
|
32
|
+
},
|
|
33
|
+
L7: {
|
|
34
|
+
eng: "communication",
|
|
35
|
+
fr: "برقراری ارتباط در خانواده",
|
|
36
|
+
},
|
|
37
|
+
L8: {
|
|
38
|
+
eng: "satisfaction",
|
|
39
|
+
fr: "رضایت خانواده",
|
|
40
|
+
},
|
|
41
|
+
L9: {
|
|
42
|
+
eng: "cohesion",
|
|
43
|
+
fr: "انسجام",
|
|
44
|
+
},
|
|
45
|
+
L10: {
|
|
46
|
+
eng: "flexibility",
|
|
47
|
+
fr: "انعطافپذیری",
|
|
48
|
+
},
|
|
49
|
+
L11: {
|
|
50
|
+
eng: "interpretation",
|
|
51
|
+
fr: "تفسیر",
|
|
52
|
+
},
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
profileSpec = {
|
|
56
|
+
/* "sample" determines some important info about the sample and profile */
|
|
57
|
+
/* Default prerequisites: 1. gender, 2. age, 3. education */
|
|
58
|
+
/* "prerequisites" is synonym to "fields" in our program */
|
|
59
|
+
sample: {
|
|
60
|
+
name: "پرسشنامه FACES-III" /* Name of the sample */,
|
|
61
|
+
multiProfile: true /* Whether the sample has multiple profiles or not */,
|
|
62
|
+
questions: false /* Determines whether to get questions from inital dataset or not */,
|
|
63
|
+
defaultFields: true /* Determines whether to have default prerequisites in the profile or not */,
|
|
64
|
+
fields: [
|
|
65
|
+
"job",
|
|
66
|
+
"marriage_duration",
|
|
67
|
+
{ merge: ["sons", "daughters"], fr: "تعداد فرزندان (دختر / پسر)", valueFormat: "{1} دختر / {0} پسر" },
|
|
68
|
+
"religion",
|
|
69
|
+
] /* In case you want to get some additional fields and show in the profile */,
|
|
70
|
+
},
|
|
71
|
+
/* "profile" determines the dimensions of the drawn profile (to be used in svg tag viewbox) */
|
|
72
|
+
/* calculating its dimensions carefully is of great importance */
|
|
73
|
+
profile: {
|
|
74
|
+
get dimensions() {
|
|
75
|
+
return [
|
|
76
|
+
{
|
|
77
|
+
width: 825 + 2 * this.padding[0].x,
|
|
78
|
+
height: 605 + 2 * this.padding[0].y,
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
width: 802 + 2 * this.padding[1].x,
|
|
82
|
+
height: 537.5 + 2 * this.padding[1].y,
|
|
83
|
+
},
|
|
84
|
+
];
|
|
85
|
+
},
|
|
86
|
+
padding: [
|
|
87
|
+
{
|
|
88
|
+
x: 36.75,
|
|
89
|
+
y: 0,
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
x: 52,
|
|
93
|
+
y: 0,
|
|
94
|
+
},
|
|
95
|
+
],
|
|
96
|
+
},
|
|
97
|
+
page2: {
|
|
98
|
+
/* "items" is the general term used for independent data elements to be drawn in the profile */
|
|
99
|
+
items: {
|
|
100
|
+
top: {
|
|
101
|
+
baseline: {
|
|
102
|
+
width: 800 /* Width of the baseline below items */,
|
|
103
|
+
},
|
|
104
|
+
maxValue: 35 /* Maximum value of items marks provided by the dataset */,
|
|
105
|
+
topPos: 353.25 /* Top position of the baseline of items */,
|
|
106
|
+
offsetX: 75 /* Horizontal offset between two consecutive item */,
|
|
107
|
+
get distanceX() {
|
|
108
|
+
return this.offsetX + this.rect.body.width;
|
|
109
|
+
} /* Horizontal distance between two consecutive item */,
|
|
110
|
+
rect: {
|
|
111
|
+
base: {
|
|
112
|
+
width: 4 /* Width of the base rectangle of items */,
|
|
113
|
+
br: 2 /* Border radius of the base rectangle of items */,
|
|
114
|
+
color: "#E4E4E7" /* Fill of the base rectangle */,
|
|
115
|
+
},
|
|
116
|
+
body: {
|
|
117
|
+
width: 35 /* Width of the body rectangle of items */,
|
|
118
|
+
height: 8 /* Height of the body rectangle parts of items */,
|
|
119
|
+
offsetY: 1 /* Vertical offset between two parts of body rectangles */,
|
|
120
|
+
get distanceY() {
|
|
121
|
+
return this.height + this.offsetY;
|
|
122
|
+
} /* Vertical distance between two parts of body rectangles */,
|
|
123
|
+
br: 4 /* Border radius of the body rectangle of items */,
|
|
124
|
+
colors: [
|
|
125
|
+
"#A21CAF",
|
|
126
|
+
"#C026D3",
|
|
127
|
+
"#D946EF",
|
|
128
|
+
"#A855F7",
|
|
129
|
+
"#9333EA",
|
|
130
|
+
"#7E22CE",
|
|
131
|
+
] /* Colors used for theming items body parts */,
|
|
132
|
+
},
|
|
133
|
+
heightCoeff: 9.28 /* Used to convert mark to height for base rectangle of items */,
|
|
134
|
+
},
|
|
135
|
+
},
|
|
136
|
+
bottom: {
|
|
137
|
+
maxValue: 50 /* Maximum value of raw mark provided by the dataset */,
|
|
138
|
+
offsetY: 112.25 /* Vertical offset from items */,
|
|
139
|
+
rect: {
|
|
140
|
+
base: {
|
|
141
|
+
width: 600 /* Width of the base rectangle of the raw */,
|
|
142
|
+
height: 4 /* Height of the base rectangle of the raw */,
|
|
143
|
+
br: 2 /* Border radius of the base rectangle of the raw */,
|
|
144
|
+
},
|
|
145
|
+
body: {
|
|
146
|
+
height: 27 /* Height of the body rectangle of the raw */,
|
|
147
|
+
br: 8 /* Border radius of the body rectangle of the raw */,
|
|
148
|
+
},
|
|
149
|
+
},
|
|
150
|
+
widthCoeff: 12 /* Used for converting mark to the width */,
|
|
151
|
+
},
|
|
152
|
+
},
|
|
153
|
+
},
|
|
154
|
+
/* "labels" part which has to be provided for each profile */
|
|
155
|
+
labels: Object.values(this.labels),
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
constructor(dataset, options, config = {}) {
|
|
159
|
+
super();
|
|
160
|
+
this._init(dataset, options, config);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
_calcContext() {
|
|
164
|
+
const {
|
|
165
|
+
spec: { parameters: spec },
|
|
166
|
+
dataset,
|
|
167
|
+
} = this;
|
|
168
|
+
|
|
169
|
+
const { page2: page2Spec } = spec;
|
|
170
|
+
|
|
171
|
+
// Gather Required Info for Item (Page 1)
|
|
172
|
+
const page1Item = {
|
|
173
|
+
marks: {
|
|
174
|
+
cohesion: dataset.score[8].mark,
|
|
175
|
+
flexibility: dataset.score[9].mark,
|
|
176
|
+
},
|
|
177
|
+
coords: {
|
|
178
|
+
x: this._markToCoord(dataset.score[8].mark, 120),
|
|
179
|
+
y: this._markToCoord(dataset.score[9].mark, 80),
|
|
180
|
+
},
|
|
181
|
+
};
|
|
182
|
+
|
|
183
|
+
// Gather Required Info for Items (Page 2)
|
|
184
|
+
const page2Items = {
|
|
185
|
+
top: dataset.score.slice(0, 6).map((data, index) => ({
|
|
186
|
+
label: data.label,
|
|
187
|
+
mark: data.mark,
|
|
188
|
+
maxValue: page2Spec.items.top.maxValue,
|
|
189
|
+
height: {
|
|
190
|
+
base: page2Spec.items.top.maxValue * page2Spec.items.top.rect.heightCoeff + 5,
|
|
191
|
+
},
|
|
192
|
+
fill: page2Spec.items.top.rect.body.colors[index],
|
|
193
|
+
})),
|
|
194
|
+
bottom: dataset.score.slice(6, 8).map((data) => ({
|
|
195
|
+
label: data.label,
|
|
196
|
+
mark: data.mark,
|
|
197
|
+
width: data.mark * page2Spec.items.bottom.widthCoeff,
|
|
198
|
+
})),
|
|
199
|
+
};
|
|
200
|
+
|
|
201
|
+
return [
|
|
202
|
+
{ page: 1, item: page1Item },
|
|
203
|
+
{ page: 2, items: page2Items },
|
|
204
|
+
];
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
_markToCoord(mark, coeff) {
|
|
208
|
+
const stops = [0, 15, 35, 65, 85, 100];
|
|
209
|
+
const n = stops.length;
|
|
210
|
+
let index;
|
|
211
|
+
|
|
212
|
+
for (let i = 0; i < n; i++) {
|
|
213
|
+
if (mark >= stops[i] && mark <= stops[i + 1]) {
|
|
214
|
+
index = i;
|
|
215
|
+
break;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
const coord = index * coeff + ((mark - stops[index]) / (stops[index + 1] - stops[index])) * coeff;
|
|
220
|
+
|
|
221
|
+
return coord;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
module.exports = FACES93;
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
const { Profile } = require("../Profile");
|
|
2
|
+
|
|
3
|
+
class FTEPT93 extends Profile {
|
|
4
|
+
// Number of pages
|
|
5
|
+
static pages = 1;
|
|
6
|
+
|
|
7
|
+
// Labels of the sample
|
|
8
|
+
labels = {
|
|
9
|
+
L1: { eng: "raw", fr: "نمره کل" },
|
|
10
|
+
L2: { eng: "efficacy", fr: "خودکارآمدی" },
|
|
11
|
+
L3: { eng: "emotional_effects", fr: "تأثیرات\nهیجانی" },
|
|
12
|
+
L4: { eng: "planning", fr: "برنامهریزی" },
|
|
13
|
+
L5: { eng: "lack_of_consequence_control", fr: "فقدان\nکنترل پیامد" },
|
|
14
|
+
L6: { eng: "motivation", fr: "انگیزش" },
|
|
15
|
+
L7: { eng: "interpretation", fr: "تفسیر" },
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
profileSpec = {
|
|
19
|
+
/* "sample" determines some important info about the sample and profile */
|
|
20
|
+
/* Default prerequisites: 1. gender, 2. age, 3. education */
|
|
21
|
+
/* "prerequisites" is synonym to "fields" in our program */
|
|
22
|
+
sample: {
|
|
23
|
+
name: "پرسشنامه عملکرد تحصیلی فام و تیلر (درتاج)" /* Name of the sample */,
|
|
24
|
+
multiProfile: false /* Whether the sample has multiple profiles or not */,
|
|
25
|
+
questions: false /* Determines whether to get questions from inital dataset or not */,
|
|
26
|
+
defaultFields: true /* Determines whether to have default prerequisites in the profile or not */,
|
|
27
|
+
fields: [
|
|
28
|
+
"study_field",
|
|
29
|
+
"marital_status",
|
|
30
|
+
] /* In case you want to get some additional fields and show in the profile */,
|
|
31
|
+
},
|
|
32
|
+
/* "profile" determines the dimensions of the drawn profile (to be used in svg tag viewbox) */
|
|
33
|
+
/* calculating its dimensions carefully is of great importance */
|
|
34
|
+
profile: {
|
|
35
|
+
get dimensions() {
|
|
36
|
+
return {
|
|
37
|
+
width: 740 + 2 * this.padding.x,
|
|
38
|
+
height: 632 + 2 * this.padding.y,
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
padding: {
|
|
42
|
+
x: 0,
|
|
43
|
+
y: 40,
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
/* "raw" is the general term used for total data element in the profile */
|
|
47
|
+
raw: {
|
|
48
|
+
maxValue: 240 /* Maximum value of raw mark provided by the dataset */,
|
|
49
|
+
leftPos: 10 /* Left position of the raw rectangle */,
|
|
50
|
+
offsetY: 150 /* Vertical offset from items */,
|
|
51
|
+
rect: {
|
|
52
|
+
width: 720 /* Width of the raw rectangle */,
|
|
53
|
+
height: 20 /* Height of the raw rectangle */,
|
|
54
|
+
br: 5 /* Border radius of the raw rectangle */,
|
|
55
|
+
},
|
|
56
|
+
widthCoeff: 3 /* Used for converting mark to the width */,
|
|
57
|
+
stops: [48, 95, 143, 240] /* Stops array for the raw mark */,
|
|
58
|
+
interprets: [
|
|
59
|
+
{ fill: "#EF4444", eng: "weak", fr: "ضعیف" },
|
|
60
|
+
{ fill: "#FBBF24", eng: "mild", fr: "متوسط" },
|
|
61
|
+
{ fill: "#22C55E", eng: "very_good", fr: "بسیار خوب" },
|
|
62
|
+
] /* Interprets array for the raw mark */,
|
|
63
|
+
label: {
|
|
64
|
+
stops: {
|
|
65
|
+
line: {
|
|
66
|
+
length: 32,
|
|
67
|
+
},
|
|
68
|
+
number: {
|
|
69
|
+
offsetY: 15,
|
|
70
|
+
},
|
|
71
|
+
},
|
|
72
|
+
shape: {
|
|
73
|
+
width: 50,
|
|
74
|
+
height: 41.5,
|
|
75
|
+
offsetY: 35,
|
|
76
|
+
},
|
|
77
|
+
},
|
|
78
|
+
},
|
|
79
|
+
/* "items" is the general term used for independent data elements to be drawn in the profile */
|
|
80
|
+
items: {
|
|
81
|
+
baseline: {
|
|
82
|
+
width: 740 /* Width of the baseline below items */,
|
|
83
|
+
},
|
|
84
|
+
maxValues: {
|
|
85
|
+
[this.labels.L2.eng]: 40,
|
|
86
|
+
[this.labels.L3.eng]: 40,
|
|
87
|
+
[this.labels.L4.eng]: 70,
|
|
88
|
+
[this.labels.L5.eng]: 25,
|
|
89
|
+
[this.labels.L6.eng]: 65,
|
|
90
|
+
} /* Maximum values of items marks provided by the dataset */,
|
|
91
|
+
topPos: 425 /* Top position of the baseline of items */,
|
|
92
|
+
offsetX: 100 /* Horizontal offset between two consecutive item */,
|
|
93
|
+
get distanceX() {
|
|
94
|
+
return this.offsetX + this.rect.body.width;
|
|
95
|
+
} /* Horizontal distance between two consecutive item */,
|
|
96
|
+
rect: {
|
|
97
|
+
base: {
|
|
98
|
+
width: 10 /* Width of the base rectangle of items */,
|
|
99
|
+
br: 2 /* Border radius of the base rectangle of items */,
|
|
100
|
+
color: "#F4F4F5" /* Fill of the base rectangle */,
|
|
101
|
+
},
|
|
102
|
+
body: {
|
|
103
|
+
width: 35 /* Width of the body rectangle of items */,
|
|
104
|
+
br: 6 /* Border radius of the body rectangle of items */,
|
|
105
|
+
colors: [
|
|
106
|
+
"#C026D3",
|
|
107
|
+
"#EC4899",
|
|
108
|
+
"#3B82F6",
|
|
109
|
+
"#14B8A6",
|
|
110
|
+
"#65A30D",
|
|
111
|
+
] /* Colors used for theming items body parts */,
|
|
112
|
+
},
|
|
113
|
+
heightCoeff: 6 /* Used for converting mark to the height */,
|
|
114
|
+
},
|
|
115
|
+
},
|
|
116
|
+
/* "labels" part which has to be provided for each profile */
|
|
117
|
+
labels: Object.values(this.labels)
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
constructor(dataset, options, config = {}) {
|
|
121
|
+
super();
|
|
122
|
+
this._init(dataset, options, config);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
_calcContext() {
|
|
126
|
+
const {
|
|
127
|
+
spec: { parameters: spec },
|
|
128
|
+
dataset,
|
|
129
|
+
} = this;
|
|
130
|
+
|
|
131
|
+
const { raw: rawSpec, items: itemsSpec } = spec;
|
|
132
|
+
|
|
133
|
+
// Separate Raw Data from the Dataset
|
|
134
|
+
let rawData = dataset.score.shift();
|
|
135
|
+
|
|
136
|
+
// Separate Interpretation from the Dataset
|
|
137
|
+
let interpret = dataset.score.pop().mark;
|
|
138
|
+
|
|
139
|
+
// Gather Required Info for Raw
|
|
140
|
+
const raw = {
|
|
141
|
+
mark: rawData.mark,
|
|
142
|
+
label: rawData.label,
|
|
143
|
+
width: rawData.mark * rawSpec.widthCoeff,
|
|
144
|
+
interpret: rawSpec.interprets.find((interpretation) => interpretation.eng === interpret),
|
|
145
|
+
stops: rawSpec.stops.map((stop) => ({
|
|
146
|
+
mark: stop,
|
|
147
|
+
width: stop * rawSpec.widthCoeff,
|
|
148
|
+
})),
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
// Gather Required Info for Items
|
|
152
|
+
const items = dataset.score.map((data, index) => ({
|
|
153
|
+
label: data.label,
|
|
154
|
+
mark: data.mark,
|
|
155
|
+
maxValue: itemsSpec.maxValues[data.label.eng],
|
|
156
|
+
height: {
|
|
157
|
+
base: itemsSpec.maxValues[data.label.eng] * itemsSpec.rect.heightCoeff,
|
|
158
|
+
body: data.mark * itemsSpec.rect.heightCoeff,
|
|
159
|
+
},
|
|
160
|
+
fill: itemsSpec.rect.body.colors[index],
|
|
161
|
+
}));
|
|
162
|
+
|
|
163
|
+
return [{ raw, items }];
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
module.exports = FTEPT93;
|