Extract Krea action family dispatch

This commit is contained in:
2026-06-26 16:26:28 +02:00
parent f6d6dfffb4
commit 0e49aed8ac
4 changed files with 254 additions and 145 deletions
+7 -134
View File
@@ -4,59 +4,17 @@ import re
from typing import Any
try:
from .krea_action_context import (
axis_values_text,
is_climax_text,
is_foreplay_text,
is_oral_text,
is_outercourse_text,
is_toy_assisted_double_text,
is_vaginal_penetration_text,
normalize_hardcore_detail_density,
)
from .krea_detail import limit_detail_for_density
from .krea_action_positions import (
arrangement_duplicates_role,
hardcore_pose_anchor,
hardcore_pose_arrangement,
)
from .krea_action_details import (
dedupe_anchor_detail,
dedupe_oral_detail,
dedupe_outercourse_detail,
dedupe_penetration_detail,
dedupe_toy_double_detail,
hardcore_item_detail,
sanitize_foreplay_detail,
)
from .krea_action_climax import climax_role_graph, dedupe_climax_detail
from .krea_action_dispatch import resolve_hardcore_action_parts
except ImportError: # Allows local smoke tests with `python -c`.
from krea_action_context import (
axis_values_text,
is_climax_text,
is_foreplay_text,
is_oral_text,
is_outercourse_text,
is_toy_assisted_double_text,
is_vaginal_penetration_text,
normalize_hardcore_detail_density,
)
from krea_detail import limit_detail_for_density
from krea_action_positions import (
arrangement_duplicates_role,
hardcore_pose_anchor,
hardcore_pose_arrangement,
)
from krea_action_details import (
dedupe_anchor_detail,
dedupe_oral_detail,
dedupe_outercourse_detail,
dedupe_penetration_detail,
dedupe_toy_double_detail,
hardcore_item_detail,
sanitize_foreplay_detail,
)
from krea_action_climax import climax_role_graph, dedupe_climax_detail
from krea_action_dispatch import resolve_hardcore_action_parts
def _clean(value: Any) -> str:
@@ -87,96 +45,11 @@ def hardcore_action_sentence(
axis_values: Any = None,
detail_density: str = "balanced",
) -> str:
detail_density = normalize_hardcore_detail_density(detail_density)
role_graph = _clean(role_graph).rstrip(".")
hard_item = _clean(hard_item).rstrip(".")
role_graph = re.sub(
r"\bthe man penetrates the woman while a toy adds a second point of contact\b",
"the man's penis thrusts into the woman while a toy is positioned at the second penetration point",
role_graph,
flags=re.IGNORECASE,
)
role_graph = re.sub(
r"\bthe man thrusts his penis into the woman while a toy adds a second penetration point\b",
"the man's penis thrusts into the woman while a toy is positioned at the second penetration point",
role_graph,
flags=re.IGNORECASE,
)
role_graph = re.sub(
r"\bthe man thrusts his penis into the woman\b",
"the man's penis thrusts into the woman",
role_graph,
flags=re.IGNORECASE,
)
role_graph = re.sub(
r"\bthe man penetrates the woman anally\b",
"the man's penis thrusts into the woman's ass",
role_graph,
flags=re.IGNORECASE,
)
role_graph = re.sub(
r"\bthe man thrusts his penis into the woman's ass\b",
"the man's penis thrusts into the woman's ass",
role_graph,
flags=re.IGNORECASE,
)
role_graph = re.sub(
r"\bthe man penetrates the woman\b",
"the man's penis thrusts into the woman",
role_graph,
flags=re.IGNORECASE,
)
role_graph = re.sub(
r"\bthe woman and the man are in mutual oral contact with mouth-to-genital contact visible\b",
"the woman has the man's penis in her mouth while the man uses his mouth on her pussy",
role_graph,
flags=re.IGNORECASE,
)
role_graph = re.sub(
r"\bthe woman gives oral to the man\b",
"the woman takes the man's penis in her mouth",
role_graph,
flags=re.IGNORECASE,
)
is_climax = is_climax_text(role_graph, hard_item, composition, axis_values_text(axis_values))
if is_climax:
role_graph = climax_role_graph(role_graph, hard_item, axis_values)
detail = hardcore_item_detail(hard_item)
anchor = hardcore_pose_anchor(role_graph, hard_item, composition, axis_values)
is_outercourse = is_outercourse_text(role_graph, hard_item, composition, axis_values_text(axis_values))
is_oral = is_oral_text(role_graph, hard_item, composition, axis_values_text(axis_values))
is_penetrative = is_vaginal_penetration_text(role_graph, hard_item, composition, axis_values_text(axis_values))
if is_toy_assisted_double_text(role_graph, hard_item, composition, axis_values_text(axis_values)):
role_graph = re.sub(
r"\s+while a toy adds (?:the|a) second penetration point\b",
" while a toy is positioned at the second penetration point",
role_graph,
flags=re.IGNORECASE,
)
if is_climax:
anchor = ""
detail = dedupe_climax_detail(detail, role_graph, detail_density)
elif is_foreplay_text(role_graph, hard_item, composition, axis_values_text(axis_values)):
anchor = ""
detail = sanitize_foreplay_detail(detail, role_graph, composition)
detail = limit_detail_for_density(detail, detail_density, False)
elif is_outercourse:
anchor = ""
detail = dedupe_outercourse_detail(detail, role_graph, hard_item, axis_values)
detail = limit_detail_for_density(detail, detail_density, False)
elif is_oral and role_graph:
anchor = ""
detail = dedupe_oral_detail(detail, role_graph, hard_item, axis_values)
detail = limit_detail_for_density(detail, detail_density, False)
elif is_penetrative and role_graph:
anchor = ""
detail = dedupe_penetration_detail(detail, role_graph, hard_item, axis_values)
detail = limit_detail_for_density(detail, detail_density, False)
else:
detail = dedupe_anchor_detail(detail, anchor) if anchor else detail
if is_toy_assisted_double_text(role_graph, hard_item, composition, axis_values_text(axis_values)):
detail = dedupe_toy_double_detail(detail)
detail = limit_detail_for_density(detail, detail_density, False)
parts = resolve_hardcore_action_parts(role_graph, hard_item, composition, axis_values, detail_density)
role_graph = parts.role_graph
hard_item = parts.hard_item
detail = parts.detail
anchor = parts.anchor
arrangement = hardcore_pose_arrangement(anchor, role_graph, hard_item, composition, axis_values)
anchor_phrase = _with_indefinite_article(anchor) if anchor else ""
if arrangement and anchor_phrase and not arrangement_duplicates_role(arrangement, role_graph):