Clarify vaginal penetration geometry
This commit is contained in:
@@ -856,6 +856,40 @@ def _is_oral_text(*parts: Any) -> bool:
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _is_vaginal_penetration_text(*parts: Any) -> bool:
|
||||||
|
text = " ".join(_clean(part).lower() for part in parts if _clean(part))
|
||||||
|
if not text or _is_outercourse_text(text) or _is_oral_text(text):
|
||||||
|
return False
|
||||||
|
if any(term in text for term in ("anal", "double penetration", "double-penetration", "toy-assisted", "strap-on")):
|
||||||
|
return False
|
||||||
|
return any(
|
||||||
|
term in text
|
||||||
|
for term in (
|
||||||
|
"vaginal penetration",
|
||||||
|
"deep vaginal sex",
|
||||||
|
"explicit penetrative sex",
|
||||||
|
"penetrative sex",
|
||||||
|
"penis entering pussy",
|
||||||
|
"penis thrusts into her pussy",
|
||||||
|
"penis thrusts into the woman",
|
||||||
|
"pussy stretched around a penis",
|
||||||
|
"hardcore vaginal thrusting",
|
||||||
|
"full-body penetrative sex",
|
||||||
|
"close-contact vaginal sex",
|
||||||
|
"missionary position",
|
||||||
|
"cowgirl position",
|
||||||
|
"reverse cowgirl position",
|
||||||
|
"doggy style position",
|
||||||
|
"standing sex position",
|
||||||
|
"spooning sex position",
|
||||||
|
"edge-of-bed position",
|
||||||
|
"kneeling straddle position",
|
||||||
|
"lotus sex position",
|
||||||
|
"bent-over position",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def _is_toy_assisted_double_text(*parts: Any) -> bool:
|
def _is_toy_assisted_double_text(*parts: Any) -> bool:
|
||||||
text = " ".join(_clean(part).lower() for part in parts if _clean(part))
|
text = " ".join(_clean(part).lower() for part in parts if _clean(part))
|
||||||
if "toy" not in text:
|
if "toy" not in text:
|
||||||
@@ -1521,6 +1555,74 @@ def _dedupe_oral_detail(detail: str, role_graph: str, hard_item: str = "", axis_
|
|||||||
return _join_detail_clauses(clauses)
|
return _join_detail_clauses(clauses)
|
||||||
|
|
||||||
|
|
||||||
|
def _dedupe_penetration_detail(detail: str, role_graph: str, hard_item: str = "", axis_values: Any = None) -> str:
|
||||||
|
detail = _clean(detail)
|
||||||
|
if not detail:
|
||||||
|
return ""
|
||||||
|
role_lower = _clean(role_graph).lower()
|
||||||
|
detail = re.sub(
|
||||||
|
r"\b(?:front-facing|side-profile|rear-view|overhead|mirror-reflected|low-angle|close-up|wide full-body)\s+view of\s+"
|
||||||
|
r"(?:vaginal penetration with visible genital contact|deep vaginal sex|explicit penetrative sex|penetrative sex|"
|
||||||
|
r"penis entering pussy|pussy stretched around a penis|hardcore vaginal thrusting|full-body penetrative sex|"
|
||||||
|
r"close-contact vaginal sex)\b,?\s*",
|
||||||
|
"",
|
||||||
|
detail,
|
||||||
|
flags=re.IGNORECASE,
|
||||||
|
)
|
||||||
|
act_terms = (
|
||||||
|
"vaginal penetration with visible genital contact",
|
||||||
|
"deep vaginal sex",
|
||||||
|
"explicit penetrative sex",
|
||||||
|
"penetrative sex",
|
||||||
|
"penis entering pussy",
|
||||||
|
"pussy stretched around a penis",
|
||||||
|
"hardcore vaginal thrusting",
|
||||||
|
"full-body penetrative sex",
|
||||||
|
"close-contact vaginal sex",
|
||||||
|
"missionary position",
|
||||||
|
"cowgirl position",
|
||||||
|
"reverse cowgirl position",
|
||||||
|
"doggy style position",
|
||||||
|
"standing sex position",
|
||||||
|
"spooning sex position",
|
||||||
|
"edge-of-bed position",
|
||||||
|
"kneeling straddle position",
|
||||||
|
"lotus sex position",
|
||||||
|
"bent-over position",
|
||||||
|
)
|
||||||
|
clauses: list[str] = []
|
||||||
|
for clause in _detail_clauses(detail):
|
||||||
|
lower = clause.lower()
|
||||||
|
if any(term in lower for term in act_terms):
|
||||||
|
continue
|
||||||
|
if lower in (
|
||||||
|
"tongues visible while kissing",
|
||||||
|
"deep kissing",
|
||||||
|
"mouth close to the ear",
|
||||||
|
"neck kissing",
|
||||||
|
"explicit genital contact visible",
|
||||||
|
"genitals clearly visible",
|
||||||
|
"anatomically clear penetration",
|
||||||
|
"pussy and penis visible",
|
||||||
|
"wetness visible between the thighs",
|
||||||
|
):
|
||||||
|
continue
|
||||||
|
if lower in ("legs spread wide", "thighs open toward the viewer") and any(
|
||||||
|
term in role_lower for term in ("legs spread wide", "thighs open", "open thighs")
|
||||||
|
):
|
||||||
|
continue
|
||||||
|
if lower == "one body pinned under another" and "lies under" in role_lower:
|
||||||
|
continue
|
||||||
|
if lower in ("hips locked tightly together", "hips aligned") and "hips" in role_lower:
|
||||||
|
continue
|
||||||
|
if lower in ("hands gripping hips", "hands spreading the thighs") and any(
|
||||||
|
term in role_lower for term in ("hips", "thighs", "legs")
|
||||||
|
):
|
||||||
|
continue
|
||||||
|
clauses.append(clause)
|
||||||
|
return _join_detail_clauses(clauses)
|
||||||
|
|
||||||
|
|
||||||
def _detail_clauses(detail: str) -> list[str]:
|
def _detail_clauses(detail: str) -> list[str]:
|
||||||
return [part.strip(" ,;") for part in re.split(r",\s*(?:and\s+)?", _clean(detail)) if part.strip(" ,;")]
|
return [part.strip(" ,;") for part in re.split(r",\s*(?:and\s+)?", _clean(detail)) if part.strip(" ,;")]
|
||||||
|
|
||||||
@@ -1846,6 +1948,7 @@ def _hardcore_action_sentence(
|
|||||||
anchor = _hardcore_pose_anchor(role_graph, hard_item, composition, axis_values)
|
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_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_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)):
|
if _is_toy_assisted_double_text(role_graph, hard_item, composition, _axis_values_text(axis_values)):
|
||||||
role_graph = re.sub(
|
role_graph = re.sub(
|
||||||
r"\s+while a toy adds (?:the|a) second penetration point\b",
|
r"\s+while a toy adds (?:the|a) second penetration point\b",
|
||||||
@@ -1864,6 +1967,10 @@ def _hardcore_action_sentence(
|
|||||||
anchor = ""
|
anchor = ""
|
||||||
detail = _dedupe_oral_detail(detail, role_graph, hard_item, axis_values)
|
detail = _dedupe_oral_detail(detail, role_graph, hard_item, axis_values)
|
||||||
detail = _limit_detail_for_density(detail, detail_density, False)
|
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:
|
else:
|
||||||
detail = _dedupe_hardcore_detail(detail, anchor) if anchor else detail
|
detail = _dedupe_hardcore_detail(detail, anchor) if anchor else detail
|
||||||
if _is_toy_assisted_double_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)):
|
||||||
|
|||||||
+20
-11
@@ -5251,24 +5251,33 @@ def _role_graph(
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
if "missionary" in text:
|
if "missionary" in text:
|
||||||
return f"{woman} lies on her back with legs open while {man} is above her and {man}'s penis thrusts into her."
|
return (
|
||||||
|
f"{woman} lies on her back with legs open around {man}'s hips while {man} is above her between her thighs; "
|
||||||
|
f"{man}'s hips press close and {man}'s penis thrusts into her pussy."
|
||||||
|
)
|
||||||
if "reverse cowgirl" in text:
|
if "reverse cowgirl" in text:
|
||||||
return f"{woman} straddles {man}'s hips facing away while {man} lies under her and {man}'s penis thrusts into her."
|
return f"{woman} straddles {man}'s hips facing away while {man} lies under her and {man}'s penis thrusts into her pussy."
|
||||||
if "cowgirl" in text or "straddling" in text:
|
if "cowgirl" in text or "straddling" in text:
|
||||||
return f"{woman} straddles {man}'s hips facing him while {man} lies under her and {man}'s penis thrusts into her."
|
return f"{woman} straddles {man}'s hips facing him while {man} lies under her and {man}'s penis thrusts into her pussy."
|
||||||
if "doggy" in text or "rear-entry" in text or "bent-over" in text or "bent over" in text:
|
if "doggy" in text or "rear-entry" in text or "bent-over" in text or "bent over" in text:
|
||||||
return f"{woman} is on all fours with hips raised while {man} is positioned behind her and {man}'s penis thrusts into her."
|
return f"{woman} is on all fours with hips raised while {man} is positioned behind her and {man}'s penis thrusts into her pussy."
|
||||||
if "standing" in text:
|
if "standing" in text:
|
||||||
return f"{woman} stands braced with hips angled back while {man} stands behind her and {man}'s penis thrusts into her."
|
return f"{woman} stands braced with hips angled back while {man} stands behind her and {man}'s penis thrusts into her pussy."
|
||||||
if "spooning" in text or "side-lying" in text:
|
if "spooning" in text or "side-lying" in text:
|
||||||
return f"{woman} lies on her side with thighs parted while {man} presses behind her and {man}'s penis thrusts into her."
|
return f"{woman} lies on her side with thighs parted while {man} presses behind her and {man}'s penis thrusts into her pussy."
|
||||||
if "edge-of-bed" in text or "edge of bed" in text or "bed edge" in text:
|
if "edge-of-bed" in text or "edge of bed" in text or "bed edge" in text or "edge-supported" in text or "raised edge" in text:
|
||||||
return f"{woman} lies at the bed edge with hips near the edge while {man} kneels between her legs and {man}'s penis thrusts into her."
|
return (
|
||||||
|
f"{woman} lies back at a raised edge with hips at the edge and legs open while {man} kneels between her thighs; "
|
||||||
|
f"{man}'s hips press close and {man}'s penis thrusts into her pussy."
|
||||||
|
)
|
||||||
if "kneeling straddle" in text:
|
if "kneeling straddle" in text:
|
||||||
return f"{woman} kneels straddling {man}'s hips while {man} supports her waist and {man}'s penis thrusts into her."
|
return f"{woman} kneels straddling {man}'s hips while {man} supports her waist and {man}'s penis thrusts into her pussy."
|
||||||
if "lotus" in text:
|
if "lotus" in text:
|
||||||
return f"{woman} sits in {man}'s lap facing him with legs around his hips while {man}'s penis thrusts into her."
|
return f"{woman} sits in {man}'s lap facing him with legs around his hips while {man}'s penis thrusts into her pussy."
|
||||||
return f"{woman} lies on her back with thighs open while {man} kneels between her legs and {man}'s penis thrusts into her."
|
return (
|
||||||
|
f"{woman} lies on her back with legs spread wide and knees bent outward while {man} kneels between her open thighs facing her; "
|
||||||
|
f"{man}'s hips are pressed between her legs and {man}'s penis thrusts into her pussy."
|
||||||
|
)
|
||||||
|
|
||||||
def anal_position_graph(woman: str, man: str) -> str:
|
def anal_position_graph(woman: str, man: str) -> str:
|
||||||
text = " ".join(
|
text = " ".join(
|
||||||
|
|||||||
Reference in New Issue
Block a user