nx_garment_fit_match_test.nx source
↩ module page · 120 lines · 5540 B
1// nx_garment_fit_match_test.nx -- smoke for garment-vs-body fit verdict.
2
3import "nx_syscalls.nx"
4import "nx_tier.nx"
5import "nx_garment_fit_match.nx"
6
7func _set_garment(g: *GarmentDimensions, bust: nx_int, waist: nx_int, hip: nx_int,
8 length: nx_int, shoulder: nx_int, cut: nx_int) -> nx_int {
9 g.bust_mm = bust
10 g.waist_mm = waist
11 g.hip_mm = hip
12 g.length_mm = length
13 g.shoulder_width_mm = shoulder
14 g.sleeve_length_mm = 0
15 g.inseam_mm = 0
16 g.cut = cut
17 g.extracted_fidelity_q10 = 900
18 return 0
19}
20
21func _set_body(b: *BodyDimensions, bust: nx_int, waist: nx_int, hip: nx_int,
22 height: nx_int, shoulder: nx_int, archetype: nx_int) -> nx_int {
23 b.bust_mm = bust
24 b.waist_mm = waist
25 b.hip_mm = hip
26 b.height_mm = height
27 b.shoulder_width_mm = shoulder
28 b.arm_length_mm = 0
29 b.inseam_mm = 0
30 b.archetype = archetype
31 return 0
32}
33
34func main() -> nx_int {
35 let g: *GarmentDimensions = (sys_mmap(10 * NX_SIZEOF_NX_INT)) as *GarmentDimensions
36 let b: *BodyDimensions = (sys_mmap(8 * NX_SIZEOF_NX_INT)) as *BodyDimensions
37 let r: *FitMatchReport = (sys_mmap(16 * NX_SIZEOF_NX_INT)) as *FitMatchReport
38
39 // === Test 1: PERFECT_TAILORED -- all axes within +-5mm ===
40 // Body: bust 870, waist 700, hip 940, height 1650 (US 4 / petite).
41 // Garment: bust 873, waist 702, hip 941, length 900, shoulder 380.
42 // All deltas <= 5mm. Cut: wrap on curvy body (good flattery).
43 _set_garment(g, 873, 702, 941, 900, 380, NX_FIT_CUT_WRAP)
44 _set_body(b, 870, 700, 940, 1650, 378, NX_FIT_ARCHETYPE_CURVY)
45 nx_garment_fit_match(g, b, r)
46 if r.verdict != NX_FIT_PERFECT_TAILORED { return 1 }
47 if r.recommended_action != NX_FIT_ACTION_SHIP { return 2 }
48 if r.max_critical_delta_mm > 5 { return 3 }
49 if r.fit_score_q10 < 950 { return 4 }
50
51 // === Test 2: GOOD_FIT -- deltas in (5, 25] mm ===
52 _set_garment(g, 880, 710, 950, 900, 380, NX_FIT_CUT_WRAP)
53 _set_body(b, 870, 700, 940, 1650, 378, NX_FIT_ARCHETYPE_CURVY)
54 nx_garment_fit_match(g, b, r)
55 if r.verdict != NX_FIT_GOOD_FIT { return 10 }
56 if r.recommended_action != NX_FIT_ACTION_SHIP { return 11 }
57
58 // === Test 3: TIGHT_OK -- garment smaller than body by 25-50mm ===
59 _set_garment(g, 830, 660, 900, 900, 380, NX_FIT_CUT_WRAP)
60 _set_body(b, 870, 700, 940, 1650, 378, NX_FIT_ARCHETYPE_CURVY)
61 nx_garment_fit_match(g, b, r)
62 if r.verdict != NX_FIT_TIGHT_OK { return 20 }
63 if r.recommended_action != NX_FIT_ACTION_TAILOR_TO_FIT { return 21 }
64 // Negative max delta on critical axes (bust -40, waist -40, hip -40)
65 if r.bust_delta_mm > 0 { return 22 }
66
67 // === Test 4: LOOSE_OK -- garment larger by 25-50mm ===
68 _set_garment(g, 910, 740, 980, 900, 380, NX_FIT_CUT_WRAP)
69 _set_body(b, 870, 700, 940, 1650, 378, NX_FIT_ARCHETYPE_CURVY)
70 nx_garment_fit_match(g, b, r)
71 if r.verdict != NX_FIT_LOOSE_OK { return 30 }
72
73 // === Test 5: SIZED_WRONG -- > 75mm off on a critical axis ===
74 _set_garment(g, 750, 600, 850, 900, 380, NX_FIT_CUT_WRAP)
75 _set_body(b, 870, 700, 940, 1650, 378, NX_FIT_ARCHETYPE_CURVY)
76 nx_garment_fit_match(g, b, r)
77 if r.verdict != NX_FIT_SIZED_WRONG { return 40 }
78 // Garment way smaller -> SIZE_UP recommendation
79 if r.recommended_action != NX_FIT_ACTION_SIZE_UP { return 41 }
80
81 // === Test 6: SIZED_WRONG the other way -> SIZE_DOWN ===
82 _set_garment(g, 1000, 850, 1080, 900, 380, NX_FIT_CUT_WRAP)
83 _set_body(b, 870, 700, 940, 1650, 378, NX_FIT_ARCHETYPE_CURVY)
84 nx_garment_fit_match(g, b, r)
85 if r.verdict != NX_FIT_SIZED_WRONG { return 50 }
86 if r.recommended_action != NX_FIT_ACTION_SIZE_DOWN { return 51 }
87
88 // === Test 7: UNFLATTERING -- physical fit OK but cut wrong for body ===
89 // BODYCON cut on a FULL archetype -> low flattery (< 512).
90 // Garment within tolerance physically.
91 _set_garment(g, 873, 702, 941, 900, 380, NX_FIT_CUT_BODYCON)
92 _set_body(b, 870, 700, 940, 1650, 378, NX_FIT_ARCHETYPE_FULL)
93 nx_garment_fit_match(g, b, r)
94 if r.verdict != NX_FIT_UNFLATTERING { return 60 }
95 if r.recommended_action != NX_FIT_ACTION_TRY_DIFFERENT_CUT { return 61 }
96
97 // === Test 8: length proportion math ===
98 // Garment length 900mm, body height 1650mm -> Q10 = 558 (~0.545).
99 _set_garment(g, 873, 702, 941, 900, 380, NX_FIT_CUT_WRAP)
100 _set_body(b, 870, 700, 940, 1650, 378, NX_FIT_ARCHETYPE_CURVY)
101 nx_garment_fit_match(g, b, r)
102 if r.length_proportion_q10 < 540 { return 70 }
103 if r.length_proportion_q10 > 580 { return 71 }
104
105 // === Test 9: worst_axis_index pinpoint ===
106 // Bust delta = +5, waist delta = +50 (LARGEST), hip delta = +10.
107 _set_garment(g, 875, 750, 950, 900, 380, NX_FIT_CUT_WRAP)
108 _set_body(b, 870, 700, 940, 1650, 378, NX_FIT_ARCHETYPE_CURVY)
109 nx_garment_fit_match(g, b, r)
110 if r.worst_axis_index != 1 { return 80 } // 1 = waist
111
112 // === Test 10: sealed-enum validity ===
113 if nx_garment_fit_verdict_is_valid(NX_FIT_PERFECT_TAILORED) != 1 { return 90 }
114 if nx_garment_fit_verdict_is_valid(NX_FIT_UNFLATTERING) != 1 { return 91 }
115 if nx_garment_fit_verdict_is_valid(99) != 0 { return 92 }
116 if nx_garment_fit_action_is_valid(NX_FIT_ACTION_SHIP) != 1 { return 93 }
117 if nx_garment_fit_action_is_valid(99) != 0 { return 94 }
118
119 return 0
120}