Extract outercourse role graph wording
This commit is contained in:
@@ -102,6 +102,9 @@ Already isolated:
|
|||||||
- hardcore configured-cast role graph generation lives in
|
- hardcore configured-cast role graph generation lives in
|
||||||
`hardcore_role_graphs.py`; `prompt_builder.py` selects item/axis metadata and
|
`hardcore_role_graphs.py`; `prompt_builder.py` selects item/axis metadata and
|
||||||
then asks that module for the source role graph.
|
then asks that module for the source role graph.
|
||||||
|
- outercourse-specific role graph wording has started moving into action-family
|
||||||
|
modules; `hardcore_role_outercourse.py` owns boobjob, testicle-sucking,
|
||||||
|
penis-licking, handjob, and footjob body geometry.
|
||||||
- camera-scene prose and coworking composition adaptation live in
|
- camera-scene prose and coworking composition adaptation live in
|
||||||
`scene_camera_adapters.py`; `prompt_builder.py` still owns camera config
|
`scene_camera_adapters.py`; `prompt_builder.py` still owns camera config
|
||||||
parsing and row mutation.
|
parsing and row mutation.
|
||||||
@@ -358,7 +361,7 @@ Medium-term:
|
|||||||
|
|
||||||
1. Split `__init__.py` node classes by family after behavior is covered by smoke
|
1. Split `__init__.py` node classes by family after behavior is covered by smoke
|
||||||
checks.
|
checks.
|
||||||
2. Split the internals of `hardcore_role_graphs.py` by action family once more
|
2. Continue splitting the internals of `hardcore_role_graphs.py` by action
|
||||||
generated edge cases are covered by smoke fixtures.
|
family once generated edge cases are covered by smoke fixtures.
|
||||||
3. Add more route-level smoke fixtures for generated edge cases that are not
|
3. Add more route-level smoke fixtures for generated edge cases that are not
|
||||||
covered by the current static Krea/SDXL/caption metadata fixtures.
|
covered by the current static Krea/SDXL/caption metadata fixtures.
|
||||||
|
|||||||
@@ -65,6 +65,7 @@ Core helper ownership:
|
|||||||
| Python module | What it owns |
|
| Python module | What it owns |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
| `hardcore_role_graphs.py` | Source role graph construction for hardcore configured-cast rows, including POV-aware interaction geometry. |
|
| `hardcore_role_graphs.py` | Source role graph construction for hardcore configured-cast rows, including POV-aware interaction geometry. |
|
||||||
|
| `hardcore_role_outercourse.py` | Outercourse role graph wording for boobjob, testicle-sucking, penis-licking, handjob, and footjob geometry. |
|
||||||
| `hardcore_action_metadata.py` | Source action-family and position-family metadata used by Krea2, SDXL, and caption routes. |
|
| `hardcore_action_metadata.py` | Source action-family and position-family metadata used by Krea2, SDXL, and caption routes. |
|
||||||
| `scene_camera_adapters.py` | Location-aware camera/scene prose such as coworking lounge camera layout. |
|
| `scene_camera_adapters.py` | Location-aware camera/scene prose such as coworking lounge camera layout. |
|
||||||
| `prompt_hygiene.py` | Generic prompt, caption, and negative-prompt cleanup. |
|
| `prompt_hygiene.py` | Generic prompt, caption, and negative-prompt cleanup. |
|
||||||
|
|||||||
+6
-71
@@ -4,6 +4,11 @@ import random
|
|||||||
import re
|
import re
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
|
try:
|
||||||
|
from .hardcore_role_outercourse import build_outercourse_role_graph
|
||||||
|
except ImportError: # Allows local smoke tests with `python -c`.
|
||||||
|
from hardcore_role_outercourse import build_outercourse_role_graph
|
||||||
|
|
||||||
|
|
||||||
def _lettered(prefix: str, count: int) -> list[str]:
|
def _lettered(prefix: str, count: int) -> list[str]:
|
||||||
letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||||
@@ -293,76 +298,6 @@ def build_hardcore_role_graph(
|
|||||||
return f"{woman} kneels forward with hips raised while {man} kneels behind her and thrusts his penis into her ass."
|
return f"{woman} kneels forward with hips raised while {man} kneels behind her and thrusts his penis into her ass."
|
||||||
return f"{woman} is on all fours with hips raised while {man} is positioned behind her and thrusts his penis into her ass."
|
return f"{woman} is on all fours with hips raised while {man} is positioned behind her and thrusts his penis into her ass."
|
||||||
|
|
||||||
def outercourse_position_graph(woman: str, man: str) -> str:
|
|
||||||
position_text = str((item_axis_values or {}).get("position") or "").lower()
|
|
||||||
text = " ".join(
|
|
||||||
str(part or "").lower()
|
|
||||||
for part in (
|
|
||||||
item_text,
|
|
||||||
*((item_axis_values or {}).values()),
|
|
||||||
)
|
|
||||||
)
|
|
||||||
man_is_pov = man in pov_set
|
|
||||||
if any(term in text for term in ("boobjob", "titjob", "breast-sex", "breast sex")):
|
|
||||||
if man_is_pov:
|
|
||||||
return (
|
|
||||||
f"{woman} kneels between the POV viewer's open thighs with her torso bent forward over his pelvis and shoulders low, "
|
|
||||||
"both hands lifting and pressing her breasts tightly around the POV viewer's penis shaft while the glans sits just below her lips."
|
|
||||||
)
|
|
||||||
return (
|
|
||||||
f"{woman} kneels between {man}'s open thighs with her torso bent forward over his pelvis and shoulders low while {man} sits with legs apart, "
|
|
||||||
f"{woman}'s hands lifting and pressing her breasts tightly around {man}'s penis shaft while the glans sits just below her lips."
|
|
||||||
)
|
|
||||||
if any(term in text for term in ("testicle", "balls-licking", "balls licking", "balls and mouth", "balls held")):
|
|
||||||
if man_is_pov:
|
|
||||||
return (
|
|
||||||
f"{woman} kneels very low between the POV viewer's open thighs with her torso bent forward and shoulders between his knees, "
|
|
||||||
"head tucked under the penis shaft at the base of the penis, mouth and tongue on the POV viewer's balls while his penis points upward above her face."
|
|
||||||
)
|
|
||||||
return (
|
|
||||||
f"{man} sits with legs apart while {woman} kneels very low between his open thighs with her torso bent forward and shoulders between his knees, "
|
|
||||||
f"head tucked under the penis shaft at the base of his penis, mouth and tongue on his balls while {man}'s penis points upward above her face."
|
|
||||||
)
|
|
||||||
if "penis-licking" in position_text or "penis licking" in text or "tongue along" in text or "tongue licking" in text:
|
|
||||||
if man_is_pov:
|
|
||||||
return (
|
|
||||||
f"{woman} bends forward between the POV viewer's open thighs, head low under the POV viewer's penis with her face directly under the penis, "
|
|
||||||
"tongue running along the underside from the penis shaft to the glans while one hand steadies the base of the penis."
|
|
||||||
)
|
|
||||||
return (
|
|
||||||
f"{woman} bends forward between {man}'s open thighs, head low under {man}'s penis with her face directly under the penis, "
|
|
||||||
f"tongue running along the underside from the penis shaft to the glans while one hand steadies the base of the penis."
|
|
||||||
)
|
|
||||||
if "footjob" in text or "soles" in text or "toes curled" in text or "feet stroking" in text:
|
|
||||||
if man_is_pov:
|
|
||||||
return (
|
|
||||||
f"{woman} faces the POV viewer with her hips back, torso visible behind her raised legs, and both knees bent open toward the camera, "
|
|
||||||
"both soles wrapped around the POV viewer's penis shaft in the lower foreground."
|
|
||||||
)
|
|
||||||
return (
|
|
||||||
f"{man} reclines with hips forward while {woman} faces him with her hips back and both knees bent open, "
|
|
||||||
f"wrapping both soles around {man}'s penis shaft while the contact stays centered."
|
|
||||||
)
|
|
||||||
if "handjob" in position_text or "handjob" in text or "hand job" in text or "hand wrapped" in text:
|
|
||||||
if man_is_pov:
|
|
||||||
return (
|
|
||||||
f"{woman} kneels between the POV viewer's open thighs with her torso leaning forward and face visible behind the penis shaft, "
|
|
||||||
"one hand wrapped around the POV viewer's penis shaft while the other hand steadies the base of the penis as she strokes toward the glans."
|
|
||||||
)
|
|
||||||
return (
|
|
||||||
f"{woman} kneels between {man}'s open thighs with her torso leaning forward and face visible behind the penis shaft, "
|
|
||||||
f"one hand wrapped around {man}'s penis shaft while the other hand steadies the base of the penis as she strokes toward the glans."
|
|
||||||
)
|
|
||||||
if man_is_pov:
|
|
||||||
return (
|
|
||||||
f"{woman} kneels close to the POV viewer's hips and keeps the POV viewer's penis centered in clear non-penetrative contact, "
|
|
||||||
"with her mouth, hands, breasts, or feet visibly working around the penis shaft."
|
|
||||||
)
|
|
||||||
return (
|
|
||||||
f"{woman} kneels close to {man}'s hips and keeps {man}'s penis centered in clear non-penetrative contact, "
|
|
||||||
"with her mouth, hands, breasts, or feet visibly working around the penis shaft."
|
|
||||||
)
|
|
||||||
|
|
||||||
def oral_position_graph(woman: str, man: str) -> str:
|
def oral_position_graph(woman: str, man: str) -> str:
|
||||||
position_text = str((item_axis_values or {}).get("position") or "").lower()
|
position_text = str((item_axis_values or {}).get("position") or "").lower()
|
||||||
text = " ".join(
|
text = " ".join(
|
||||||
@@ -543,7 +478,7 @@ def build_hardcore_role_graph(
|
|||||||
elif "foreplay" in slug:
|
elif "foreplay" in slug:
|
||||||
graph = foreplay_position_graph(woman, man)
|
graph = foreplay_position_graph(woman, man)
|
||||||
elif "outercourse" in slug:
|
elif "outercourse" in slug:
|
||||||
graph = outercourse_position_graph(woman, man)
|
graph = build_outercourse_role_graph(woman, man, item_text, item_axis_values, pov_labels)
|
||||||
elif "oral" in slug:
|
elif "oral" in slug:
|
||||||
graph = oral_position_graph(woman, man)
|
graph = oral_position_graph(woman, man)
|
||||||
elif "anal" in slug or "double" in slug:
|
elif "anal" in slug or "double" in slug:
|
||||||
|
|||||||
@@ -0,0 +1,84 @@
|
|||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
|
||||||
|
def _context_text(item_text: str, item_axis_values: dict[str, Any] | None) -> str:
|
||||||
|
return " ".join(
|
||||||
|
str(part or "").lower()
|
||||||
|
for part in (
|
||||||
|
item_text,
|
||||||
|
*((item_axis_values or {}).values()),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def build_outercourse_role_graph(
|
||||||
|
woman: str,
|
||||||
|
man: str,
|
||||||
|
item_text: str,
|
||||||
|
item_axis_values: dict[str, Any] | None = None,
|
||||||
|
pov_labels: list[str] | None = None,
|
||||||
|
) -> str:
|
||||||
|
position_text = str((item_axis_values or {}).get("position") or "").lower()
|
||||||
|
text = _context_text(item_text, item_axis_values)
|
||||||
|
man_is_pov = man in set(pov_labels or [])
|
||||||
|
if any(term in text for term in ("boobjob", "titjob", "breast-sex", "breast sex")):
|
||||||
|
if man_is_pov:
|
||||||
|
return (
|
||||||
|
f"{woman} kneels between the POV viewer's open thighs with her torso bent forward over his pelvis and shoulders low, "
|
||||||
|
"both hands lifting and pressing her breasts tightly around the POV viewer's penis shaft while the glans sits just below her lips."
|
||||||
|
)
|
||||||
|
return (
|
||||||
|
f"{woman} kneels between {man}'s open thighs with her torso bent forward over his pelvis and shoulders low while {man} sits with legs apart, "
|
||||||
|
f"{woman}'s hands lifting and pressing her breasts tightly around {man}'s penis shaft while the glans sits just below her lips."
|
||||||
|
)
|
||||||
|
if any(term in text for term in ("testicle", "balls-licking", "balls licking", "balls and mouth", "balls held")):
|
||||||
|
if man_is_pov:
|
||||||
|
return (
|
||||||
|
f"{woman} kneels very low between the POV viewer's open thighs with her torso bent forward and shoulders between his knees, "
|
||||||
|
"head tucked under the penis shaft at the base of the penis, mouth and tongue on the POV viewer's balls while his penis points upward above her face."
|
||||||
|
)
|
||||||
|
return (
|
||||||
|
f"{man} sits with legs apart while {woman} kneels very low between his open thighs with her torso bent forward and shoulders between his knees, "
|
||||||
|
f"head tucked under the penis shaft at the base of his penis, mouth and tongue on his balls while {man}'s penis points upward above her face."
|
||||||
|
)
|
||||||
|
if "penis-licking" in position_text or "penis licking" in text or "tongue along" in text or "tongue licking" in text:
|
||||||
|
if man_is_pov:
|
||||||
|
return (
|
||||||
|
f"{woman} bends forward between the POV viewer's open thighs, head low under the POV viewer's penis with her face directly under the penis, "
|
||||||
|
"tongue running along the underside from the penis shaft to the glans while one hand steadies the base of the penis."
|
||||||
|
)
|
||||||
|
return (
|
||||||
|
f"{woman} bends forward between {man}'s open thighs, head low under {man}'s penis with her face directly under the penis, "
|
||||||
|
f"tongue running along the underside from the penis shaft to the glans while one hand steadies the base of the penis."
|
||||||
|
)
|
||||||
|
if "footjob" in text or "soles" in text or "toes curled" in text or "feet stroking" in text:
|
||||||
|
if man_is_pov:
|
||||||
|
return (
|
||||||
|
f"{woman} faces the POV viewer with her hips back, torso visible behind her raised legs, and both knees bent open toward the camera, "
|
||||||
|
"both soles wrapped around the POV viewer's penis shaft in the lower foreground."
|
||||||
|
)
|
||||||
|
return (
|
||||||
|
f"{man} reclines with hips forward while {woman} faces him with her hips back and both knees bent open, "
|
||||||
|
f"wrapping both soles around {man}'s penis shaft while the contact stays centered."
|
||||||
|
)
|
||||||
|
if "handjob" in position_text or "handjob" in text or "hand job" in text or "hand wrapped" in text:
|
||||||
|
if man_is_pov:
|
||||||
|
return (
|
||||||
|
f"{woman} kneels between the POV viewer's open thighs with her torso leaning forward and face visible behind the penis shaft, "
|
||||||
|
"one hand wrapped around the POV viewer's penis shaft while the other hand steadies the base of the penis as she strokes toward the glans."
|
||||||
|
)
|
||||||
|
return (
|
||||||
|
f"{woman} kneels between {man}'s open thighs with her torso leaning forward and face visible behind the penis shaft, "
|
||||||
|
f"one hand wrapped around {man}'s penis shaft while the other hand steadies the base of the penis as she strokes toward the glans."
|
||||||
|
)
|
||||||
|
if man_is_pov:
|
||||||
|
return (
|
||||||
|
f"{woman} kneels close to the POV viewer's hips and keeps the POV viewer's penis centered in clear non-penetrative contact, "
|
||||||
|
"with her mouth, hands, breasts, or feet visibly working around the penis shaft."
|
||||||
|
)
|
||||||
|
return (
|
||||||
|
f"{woman} kneels close to {man}'s hips and keeps {man}'s penis centered in clear non-penetrative contact, "
|
||||||
|
"with her mouth, hands, breasts, or feet visibly working around the penis shaft."
|
||||||
|
)
|
||||||
Reference in New Issue
Block a user