Split manual hardcore action routing
This commit is contained in:
@@ -216,7 +216,7 @@
|
||||
"inherit_compositions": false,
|
||||
"weight": 0.85,
|
||||
"item_template_metadata": {
|
||||
"action_family": "foreplay",
|
||||
"action_family": "manual",
|
||||
"position_family": "manual"
|
||||
},
|
||||
"item_label": "Manual action",
|
||||
|
||||
@@ -27,6 +27,7 @@ except ImportError: # Allows local smoke tests with `python -c`.
|
||||
|
||||
ACTION_CLIMAX = "climax"
|
||||
ACTION_FOREPLAY = "foreplay"
|
||||
ACTION_MANUAL = "manual"
|
||||
ACTION_OUTERCOURSE = "outercourse"
|
||||
ACTION_ORAL = "oral"
|
||||
ACTION_PENETRATION = "penetration"
|
||||
@@ -36,6 +37,7 @@ ACTION_DEFAULT = "default"
|
||||
HARDCORE_ACTION_FAMILY_CHOICES = {
|
||||
ACTION_CLIMAX,
|
||||
ACTION_FOREPLAY,
|
||||
ACTION_MANUAL,
|
||||
ACTION_OUTERCOURSE,
|
||||
ACTION_ORAL,
|
||||
ACTION_PENETRATION,
|
||||
@@ -59,8 +61,8 @@ def normalize_hardcore_action_family(value: Any, default: str = "") -> str:
|
||||
"toy_assisted_double_penetration": ACTION_TOY_DOUBLE,
|
||||
"outer_course": ACTION_OUTERCOURSE,
|
||||
"outercourse_sex": ACTION_OUTERCOURSE,
|
||||
"manual": ACTION_FOREPLAY,
|
||||
"manual_stimulation": ACTION_FOREPLAY,
|
||||
"manual": ACTION_MANUAL,
|
||||
"manual_stimulation": ACTION_MANUAL,
|
||||
"interaction": ACTION_FOREPLAY,
|
||||
"body_worship": ACTION_FOREPLAY,
|
||||
"body_worship_touching": ACTION_FOREPLAY,
|
||||
@@ -132,7 +134,7 @@ def source_hardcore_action_family(
|
||||
"penetrative": ACTION_PENETRATION,
|
||||
"foreplay": ACTION_FOREPLAY,
|
||||
"interaction": ACTION_FOREPLAY,
|
||||
"manual": ACTION_FOREPLAY,
|
||||
"manual": ACTION_MANUAL,
|
||||
"oral": ACTION_ORAL,
|
||||
"outercourse": ACTION_OUTERCOURSE,
|
||||
"climax": ACTION_CLIMAX,
|
||||
|
||||
@@ -14,6 +14,7 @@ try:
|
||||
from .hardcore_action_metadata import (
|
||||
ACTION_CLIMAX,
|
||||
ACTION_FOREPLAY,
|
||||
ACTION_MANUAL,
|
||||
ACTION_ORAL,
|
||||
ACTION_OUTERCOURSE,
|
||||
ACTION_PENETRATION,
|
||||
@@ -43,6 +44,7 @@ except ImportError: # Allows local smoke tests with `python -c`.
|
||||
from hardcore_action_metadata import (
|
||||
ACTION_CLIMAX,
|
||||
ACTION_FOREPLAY,
|
||||
ACTION_MANUAL,
|
||||
ACTION_ORAL,
|
||||
ACTION_OUTERCOURSE,
|
||||
ACTION_PENETRATION,
|
||||
@@ -145,7 +147,7 @@ def action_detail_for_family(
|
||||
) -> tuple[str, str]:
|
||||
if family == ACTION_CLIMAX:
|
||||
return "", dedupe_climax_detail(detail, role_graph, detail_density)
|
||||
if family == ACTION_FOREPLAY:
|
||||
if family in (ACTION_FOREPLAY, ACTION_MANUAL):
|
||||
detail = sanitize_foreplay_detail(detail, role_graph, composition)
|
||||
return "", limit_detail_for_density(detail, detail_density, False)
|
||||
if family == ACTION_OUTERCOURSE:
|
||||
|
||||
@@ -48,6 +48,7 @@ SDXL_DEFAULT_NEGATIVE = (
|
||||
|
||||
SDXL_ACTION_FAMILY_TAGS = {
|
||||
"foreplay": ("foreplay", "body contact"),
|
||||
"manual": ("manual stimulation",),
|
||||
"outercourse": ("outercourse", "non-penetrative sex"),
|
||||
"oral": ("oral sex",),
|
||||
"penetration": ("penetrative sex", "penetration"),
|
||||
|
||||
@@ -25,6 +25,7 @@ INCOMPATIBLE_ROUTE_TAGS = {
|
||||
"action:penetration": ("oral sex", "outercourse", "anal sex", "manual stimulation"),
|
||||
"action:oral": ("penetrative sex", "penetration", "anal sex", "outercourse"),
|
||||
"action:outercourse": ("penetrative sex", "penetration", "oral sex", "anal sex", "manual stimulation"),
|
||||
"action:manual": ("penetrative sex", "penetration", "oral sex", "anal sex", "outercourse"),
|
||||
"position:penetrative": ("oral sex", "outercourse", "anal sex", "manual stimulation"),
|
||||
"position:oral": ("penetrative sex", "penetration", "anal sex", "outercourse"),
|
||||
"position:outercourse": ("penetrative sex", "penetration", "oral sex", "anal sex", "manual stimulation"),
|
||||
|
||||
@@ -259,7 +259,7 @@ HARDCORE_ROUTE_CASES = (
|
||||
"subcategory": "Manual stimulation",
|
||||
"focus": "manual_only",
|
||||
"family": "manual",
|
||||
"expected_route": {"position_family": "manual"},
|
||||
"expected_route": {"action_family": "manual", "position_family": "manual"},
|
||||
"expected_terms": {
|
||||
"krea": ("hand",),
|
||||
"sdxl": ("manual stimulation",),
|
||||
|
||||
+12
-8
@@ -4906,7 +4906,7 @@ def smoke_hardcore_position_config_policy() -> None:
|
||||
"Template action-family normalizer should accept spaced aliases",
|
||||
)
|
||||
_expect(
|
||||
category_template_metadata.template_action_family({"action_family": "manual stimulation"}) == "foreplay",
|
||||
category_template_metadata.template_action_family({"action_family": "manual stimulation"}) == "manual",
|
||||
"Template action-family normalizer should accept subcategory-style aliases",
|
||||
)
|
||||
_expect(
|
||||
@@ -5115,7 +5115,7 @@ def smoke_hardcore_position_config_policy() -> None:
|
||||
{
|
||||
"name": "Inherited metadata route",
|
||||
"item_template_metadata": {
|
||||
"action_family": "foreplay",
|
||||
"action_family": "manual",
|
||||
"position_family": "manual",
|
||||
"position_keys": ["kneeling"],
|
||||
"formatter_hint": {"caption": "inherited caption cue"},
|
||||
@@ -5132,7 +5132,7 @@ def smoke_hardcore_position_config_policy() -> None:
|
||||
)
|
||||
_expect(inherited_text == "hand stimulation in kneeling manual position", "Inherited template metadata changed item text")
|
||||
_expect(inherited_axis_values == {"act": "hand stimulation", "position": "kneeling manual position"}, "Inherited template metadata lost axis values")
|
||||
_expect(inherited_metadata.get("action_family") == "foreplay", "String template did not inherit action family")
|
||||
_expect(inherited_metadata.get("action_family") == "manual", "String template did not inherit action family")
|
||||
_expect(inherited_metadata.get("position_family") == "manual", "String template did not inherit position family")
|
||||
_expect(pb._template_position_keys(inherited_metadata) == ["kneeling"], "String template did not inherit position keys")
|
||||
_expect(
|
||||
@@ -5145,7 +5145,7 @@ def smoke_hardcore_position_config_policy() -> None:
|
||||
{
|
||||
"name": "Override metadata route",
|
||||
"item_template_metadata": {
|
||||
"action_family": "foreplay",
|
||||
"action_family": "manual",
|
||||
"position_family": "manual",
|
||||
"formatter_hint": {"all": "inherited shared cue"},
|
||||
},
|
||||
@@ -5343,7 +5343,7 @@ def smoke_row_route_metadata_policy() -> None:
|
||||
item_axis_values={"position": "kneeling manual position"},
|
||||
)
|
||||
_expect(fallback["position_family"] == "manual", "Route policy lost source position-family fallback")
|
||||
_expect(fallback["action_family"] == "foreplay", "Route policy lost source action-family fallback")
|
||||
_expect(fallback["action_family"] == "manual", "Route policy lost source action-family fallback")
|
||||
_expect("kneeling" in fallback["position_keys"], "Route policy lost inferred position key")
|
||||
|
||||
empty = row_route_metadata.resolve_action_position_route(
|
||||
@@ -5519,7 +5519,7 @@ def smoke_hardcore_category_routes() -> None:
|
||||
cases = [
|
||||
("hardcore_penetration", "Penetrative sex", "penetration_only", "penetrative", {"penetration", "default"}, "penetrative sex", "penetrative action"),
|
||||
("hardcore_oral", "Oral sex", "oral_only", "oral", {"oral"}, "oral sex", "oral action"),
|
||||
("hardcore_manual", "Manual stimulation", "manual_only", "manual", {"foreplay", "outercourse"}, "manual stimulation", "manual action"),
|
||||
("hardcore_manual", "Manual stimulation", "manual_only", "manual", {"manual"}, "manual stimulation", "manual action"),
|
||||
("hardcore_outercourse", "Outercourse and genital teasing", "outercourse_only", "outercourse", {"outercourse"}, "outercourse", "non-penetrative action"),
|
||||
("hardcore_foreplay", "Foreplay and teasing", "foreplay_only", "foreplay", {"foreplay"}, "foreplay", "foreplay action"),
|
||||
("hardcore_aftercare", "Aftercare and cleanup", "interaction_only", "interaction", {"foreplay"}, "interaction", "interaction beat"),
|
||||
@@ -6938,7 +6938,11 @@ def smoke_interaction_role_graph_routes() -> None:
|
||||
hardcore_position_config=_position_filter(focus, family, [position_key]),
|
||||
)
|
||||
_expect_custom_row(row, name)
|
||||
_expect(row.get("action_family") == "foreplay", f"{name} action_family should stay formatter foreplay")
|
||||
expected_action_family = "manual" if family == "manual" else "foreplay"
|
||||
_expect(
|
||||
row.get("action_family") == expected_action_family,
|
||||
f"{name} action_family mismatch: {row.get('action_family')} != {expected_action_family}",
|
||||
)
|
||||
_expect(row.get("position_family") == family, f"{name} position_family mismatch: {row.get('position_family')}")
|
||||
_expect(position_key in (row.get("position_keys") or []), f"{name} lost position key {position_key!r}")
|
||||
role_graph = _expect_text(f"{name}.source_role_graph", row.get("source_role_graph"), 40).lower()
|
||||
@@ -7131,7 +7135,7 @@ def smoke_formatter_metadata_fixtures() -> None:
|
||||
"Woman A reclines with thighs open while Man A's hand is between her legs, "
|
||||
"fingers visibly stimulating her pussy."
|
||||
),
|
||||
action_family="foreplay",
|
||||
action_family="manual",
|
||||
position_family="manual",
|
||||
position_key="fingering",
|
||||
position_keys=["fingering", "open_thighs"],
|
||||
|
||||
Reference in New Issue
Block a user