nx_hair_style.nx source
↩ module page · 148 lines · 5924 B
1// nx_hair_style.nx -- Best Makeup-Hairstyling (hair half).
2//
3// Parallel structure to nx_makeup_style. Typed hair-style enum +
4// per-location-appropriateness scoring. Composes with makeup_style
5// into Best Makeup-Hairstyling joint composite.
6//
7// 8 sealed hair styles (intensity ladder):
8// PRACTICAL_UPDO bun / ponytail / messy bun
9// NATURAL_DOWN loose natural hair down
10// BEACH_WAVES tousled relaxed waves
11// BLOWOUT polished smooth blowout
12// SLEEK_STRAIGHT glossy ironed straight
13// STYLED_CURLS deliberate curl pattern
14// EDITORIAL_AVANT fashion-shoot statement style
15// WET_DAMP shower / pool / out-of-water look
16
17// nx_safety_envelope:
18// intended_use: AUTO_APPLIED -- primitive-specific tuning queued
19// sil_target: SIL1
20// evidence: [bulk_applied_2026-05-16, see-file-comment-for-detail]
21// verdict: NOT_YET_EVALUATED
22
23import "nx_syscalls.nx"
24const NX_MAGIC_1024: i64 = 1024
25
26const NX_HAIR_PRACTICAL_UPDO: i64 = 1
27const NX_HAIR_NATURAL_DOWN: i64 = 2
28const NX_HAIR_BEACH_WAVES: i64 = 3
29const NX_HAIR_BLOWOUT: i64 = 4
30const NX_HAIR_SLEEK_STRAIGHT: i64 = 5
31const NX_HAIR_STYLED_CURLS: i64 = 6
32const NX_HAIR_EDITORIAL_AVANT: i64 = 7
33const NX_HAIR_WET_DAMP: i64 = 8
34
35// LocationKind ids (mirror nx_makeup_style).
36const NX_HR_LOC_GYM: i64 = 1
37const NX_HR_LOC_BEDROOM: i64 = 2
38const NX_HR_LOC_KITCHEN: i64 = 3
39const NX_HR_LOC_BATHROOM: i64 = 4
40const NX_HR_LOC_OUTDOOR: i64 = 5
41const NX_HR_LOC_OFFICE: i64 = 6
42const NX_HR_LOC_RESTAURANT: i64 = 7
43const NX_HR_LOC_STUDIO: i64 = 8
44const NX_HR_LOC_BEACH: i64 = 9
45const NX_HR_LOC_POOL: i64 = 10
46
47const NX_HAIR_RES_DECLARED: i64 = 0
48const NX_HAIR_RES_MEASURED: i64 = 1
49const NX_HAIR_RES_APPROP_Q10: i64 = 2
50const NX_HAIR_RES_MATCH_Q10: i64 = 3
51const NX_HAIR_RES_VERDICT: i64 = 4
52const NX_HAIR_RES_FIELDS: i64 = 5
53
54const NX_HAIR_V_INAPPROPRIATE: i64 = 0
55const NX_HAIR_V_MISMATCHED: i64 = 1
56const NX_HAIR_V_ACCEPTABLE: i64 = 2
57const NX_HAIR_V_APPROPRIATE: i64 = 3
58
59func nx_hair_scene_score(location: i64, hair_kind: i64) -> i64 {
60 if location == NX_HR_LOC_GYM {
61 if hair_kind == NX_HAIR_PRACTICAL_UPDO { return NX_MAGIC_1024 }
62 if hair_kind == NX_HAIR_WET_DAMP { return 614 }
63 if hair_kind == NX_HAIR_NATURAL_DOWN { return 410 }
64 return 200
65 }
66 if location == NX_HR_LOC_BEDROOM {
67 if hair_kind == NX_HAIR_NATURAL_DOWN { return NX_MAGIC_1024 }
68 if hair_kind == NX_HAIR_BEACH_WAVES { return 870 }
69 if hair_kind == NX_HAIR_PRACTICAL_UPDO { return 768 }
70 if hair_kind == NX_HAIR_WET_DAMP { return 717 }
71 return 410
72 }
73 if location == NX_HR_LOC_RESTAURANT {
74 if hair_kind == NX_HAIR_BLOWOUT { return NX_MAGIC_1024 }
75 if hair_kind == NX_HAIR_SLEEK_STRAIGHT { return 920 }
76 if hair_kind == NX_HAIR_STYLED_CURLS { return 870 }
77 if hair_kind == NX_HAIR_NATURAL_DOWN { return 614 }
78 return 256
79 }
80 if location == NX_HR_LOC_OFFICE {
81 if hair_kind == NX_HAIR_BLOWOUT { return NX_MAGIC_1024 }
82 if hair_kind == NX_HAIR_SLEEK_STRAIGHT { return 920 }
83 if hair_kind == NX_HAIR_PRACTICAL_UPDO { return 870 }
84 return 410
85 }
86 if location == NX_HR_LOC_STUDIO {
87 if hair_kind == NX_HAIR_EDITORIAL_AVANT { return NX_MAGIC_1024 }
88 if hair_kind == NX_HAIR_STYLED_CURLS { return 920 }
89 if hair_kind == NX_HAIR_BLOWOUT { return 870 }
90 if hair_kind == NX_HAIR_BEACH_WAVES { return 768 }
91 return 614
92 }
93 if location == NX_HR_LOC_BEACH {
94 if hair_kind == NX_HAIR_BEACH_WAVES { return NX_MAGIC_1024 }
95 if hair_kind == NX_HAIR_WET_DAMP { return 920 }
96 if hair_kind == NX_HAIR_NATURAL_DOWN { return 870 }
97 if hair_kind == NX_HAIR_PRACTICAL_UPDO { return 614 }
98 return 200
99 }
100 if location == NX_HR_LOC_POOL {
101 if hair_kind == NX_HAIR_WET_DAMP { return NX_MAGIC_1024 }
102 if hair_kind == NX_HAIR_BEACH_WAVES { return 870 }
103 if hair_kind == NX_HAIR_PRACTICAL_UPDO { return 614 }
104 return 200
105 }
106 if location == NX_HR_LOC_BATHROOM {
107 if hair_kind == NX_HAIR_WET_DAMP { return NX_MAGIC_1024 }
108 if hair_kind == NX_HAIR_PRACTICAL_UPDO { return 768 }
109 if hair_kind == NX_HAIR_NATURAL_DOWN { return 614 }
110 return 410
111 }
112 if location == NX_HR_LOC_KITCHEN {
113 if hair_kind == NX_HAIR_PRACTICAL_UPDO { return NX_MAGIC_1024 }
114 if hair_kind == NX_HAIR_NATURAL_DOWN { return 768 }
115 return 410
116 }
117 if location == NX_HR_LOC_OUTDOOR {
118 if hair_kind == NX_HAIR_BEACH_WAVES { return 920 }
119 if hair_kind == NX_HAIR_NATURAL_DOWN { return 870 }
120 if hair_kind == NX_HAIR_BLOWOUT { return 614 }
121 return 410
122 }
123 return 512
124}
125
126func nx_hair_style_score(declared_kind: i64, measured_kind: i64,
127 location: i64, result: *i64) -> i64 {
128 var i: i64 = 0
129 while i < NX_HAIR_RES_FIELDS { result[i] = 0; i = i + 1 }
130 result[NX_HAIR_RES_DECLARED] = declared_kind
131 result[NX_HAIR_RES_MEASURED] = measured_kind
132
133 let approp: i64 = nx_hair_scene_score(location, measured_kind)
134 result[NX_HAIR_RES_APPROP_Q10] = approp
135
136 var diff: i64 = declared_kind - measured_kind
137 if diff < 0 { diff = -diff }
138 var match_score: i64 = NX_MAGIC_1024 - diff * 145 // ~14% per rank
139 if match_score < 0 { match_score = 0 }
140 result[NX_HAIR_RES_MATCH_Q10] = match_score
141
142 var verdict: i64 = NX_HAIR_V_INAPPROPRIATE
143 if approp >= 410 { verdict = NX_HAIR_V_MISMATCHED }
144 if approp >= 614 { verdict = NX_HAIR_V_ACCEPTABLE }
145 if approp >= 819 { if match_score >= 614 { verdict = NX_HAIR_V_APPROPRIATE } }
146 result[NX_HAIR_RES_VERDICT] = verdict
147 return 0
148}