updated
This commit is contained in:
parent
a598ac025f
commit
2d5ef7741a
@ -27,7 +27,6 @@
|
||||
"bodyParts": [
|
||||
"anus",
|
||||
"ass",
|
||||
"back",
|
||||
"breasts",
|
||||
"penis",
|
||||
"tongue",
|
||||
|
||||
@ -79,10 +79,18 @@ def main():
|
||||
|
||||
x1, y1, x2, y2 = [float(v) for v in b.xyxy[0].tolist()]
|
||||
|
||||
x = clamp01(x1 / img_w)
|
||||
y = clamp01(y1 / img_h)
|
||||
w = clamp01((x2 - x1) / img_w)
|
||||
h = clamp01((y2 - y1) / img_h)
|
||||
x1 = max(0.0, min(float(img_w), x1))
|
||||
y1 = max(0.0, min(float(img_h), y1))
|
||||
x2 = max(0.0, min(float(img_w), x2))
|
||||
y2 = max(0.0, min(float(img_h), y2))
|
||||
|
||||
if x2 <= x1 or y2 <= y1:
|
||||
continue
|
||||
|
||||
x = x1 / img_w
|
||||
y = y1 / img_h
|
||||
w = (x2 - x1) / img_w
|
||||
h = (y2 - y1) / img_h
|
||||
|
||||
if w <= 0 or h <= 0:
|
||||
continue
|
||||
|
||||
@ -187,8 +187,11 @@ func trainingNextHandler(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
refreshPrediction := r.URL.Query().Get("refresh") == "1" ||
|
||||
strings.EqualFold(r.URL.Query().Get("refresh"), "true")
|
||||
|
||||
if !forceNew {
|
||||
if sample, ok, err := trainingLatestOpenSample(root); err != nil {
|
||||
if sample, ok, err := trainingLatestOpenSample(root, refreshPrediction); err != nil {
|
||||
trainingWriteError(w, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
} else if ok {
|
||||
@ -206,7 +209,7 @@ func trainingNextHandler(w http.ResponseWriter, r *http.Request) {
|
||||
trainingWriteJSON(w, http.StatusOK, sample)
|
||||
}
|
||||
|
||||
func trainingLatestOpenSample(root string) (*TrainingSample, bool, error) {
|
||||
func trainingLatestOpenSample(root string, refreshPrediction bool) (*TrainingSample, bool, error) {
|
||||
answered, err := trainingAnsweredSampleIDs(root)
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
@ -272,10 +275,10 @@ func trainingLatestOpenSample(root string) (*TrainingSample, bool, error) {
|
||||
continue
|
||||
}
|
||||
|
||||
// Wichtig: Prediction aktualisieren, damit alte "model_missing"-Samples
|
||||
// nach einem Training nicht stale bleiben.
|
||||
if refreshPrediction {
|
||||
sample.Prediction = trainingPredictFrame(framePath)
|
||||
_ = trainingWriteSample(root, sample)
|
||||
}
|
||||
|
||||
return sample, true, nil
|
||||
}
|
||||
@ -1372,6 +1375,10 @@ func trainingPredictionFromDetector(det TrainingDetectorPrediction) TrainingPred
|
||||
visibleBoxes := []TrainingBox{}
|
||||
|
||||
for _, box := range rawBoxes {
|
||||
if box.Score > 0 && box.Score < 0.25 {
|
||||
continue
|
||||
}
|
||||
|
||||
label := strings.TrimSpace(box.Label)
|
||||
if label == "" {
|
||||
continue
|
||||
@ -1428,7 +1435,7 @@ func trainingPredictDetector(root string, framePath string) TrainingDetectorPred
|
||||
}
|
||||
}
|
||||
|
||||
confValues := []string{"0.30", "0.10", "0.03", "0.01"}
|
||||
confValues := []string{"0.40", "0.30", "0.20"}
|
||||
|
||||
best := TrainingDetectorPrediction{
|
||||
Available: true,
|
||||
|
||||
@ -0,0 +1,70 @@
|
||||
.training-beaker-icon > svg {
|
||||
animation: training-beaker-pulse 1.6s ease-in-out infinite;
|
||||
}
|
||||
|
||||
.training-beaker-bubble {
|
||||
position: absolute;
|
||||
bottom: 34%;
|
||||
width: 0.22em;
|
||||
height: 0.22em;
|
||||
border-radius: 9999px;
|
||||
background: rgb(255 255 255 / 0.95);
|
||||
box-shadow:
|
||||
0 0 0 1px rgb(0 0 0 / 0.16),
|
||||
0 0 8px currentColor;
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
animation: training-beaker-bubble-rise 1.45s ease-in-out infinite;
|
||||
}
|
||||
|
||||
.training-beaker-bubble-1 {
|
||||
left: 40%;
|
||||
animation-delay: 0s;
|
||||
}
|
||||
|
||||
.training-beaker-bubble-2 {
|
||||
left: 52%;
|
||||
width: 0.18em;
|
||||
height: 0.18em;
|
||||
animation-delay: 0.35s;
|
||||
}
|
||||
|
||||
.training-beaker-bubble-3 {
|
||||
left: 47%;
|
||||
width: 0.14em;
|
||||
height: 0.14em;
|
||||
animation-delay: 0.7s;
|
||||
}
|
||||
|
||||
@keyframes training-beaker-bubble-rise {
|
||||
0% {
|
||||
transform: translate(-50%, 0) scale(0.45);
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
18% {
|
||||
opacity: 0.95;
|
||||
}
|
||||
|
||||
72% {
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: translate(-50%, -0.72em) scale(1);
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes training-beaker-pulse {
|
||||
0%,
|
||||
100% {
|
||||
transform: scale(1);
|
||||
filter: drop-shadow(0 0 0 rgb(16 185 129 / 0));
|
||||
}
|
||||
|
||||
50% {
|
||||
transform: scale(1.04);
|
||||
filter: drop-shadow(0 0 6px rgb(16 185 129 / 0.55));
|
||||
}
|
||||
}
|
||||
@ -621,8 +621,29 @@ function upsertJobById(list: RecordJob[], incoming: RecordJob): RecordJob[] {
|
||||
})
|
||||
}
|
||||
|
||||
function TrainingBeakerIcon(props: React.ComponentProps<typeof BeakerIcon>) {
|
||||
const { className } = props
|
||||
|
||||
return (
|
||||
<span
|
||||
className={[
|
||||
'training-beaker-icon relative inline-block overflow-visible',
|
||||
className ?? '',
|
||||
].join(' ')}
|
||||
aria-hidden="true"
|
||||
>
|
||||
<BeakerIcon className="block h-full w-full" />
|
||||
|
||||
<span className="training-beaker-bubble training-beaker-bubble-1" />
|
||||
<span className="training-beaker-bubble training-beaker-bubble-2" />
|
||||
<span className="training-beaker-bubble training-beaker-bubble-3" />
|
||||
</span>
|
||||
)
|
||||
}
|
||||
|
||||
export default function App() {
|
||||
|
||||
const [trainingTabRunning, setTrainingTabRunning] = useState(false)
|
||||
const [splitProgressByFile, setSplitProgressByFile] = useState<Record<string, BackgroundSplitProgress>>({})
|
||||
const splitProgressClearTimersRef = useRef<Record<string, number>>({})
|
||||
|
||||
@ -1065,6 +1086,51 @@ export default function App() {
|
||||
}
|
||||
}, [includeKeep])
|
||||
|
||||
useEffect(() => {
|
||||
if (!authed) {
|
||||
setTrainingTabRunning(false)
|
||||
return
|
||||
}
|
||||
|
||||
let cancelled = false
|
||||
|
||||
const loadTrainingStatus = async () => {
|
||||
try {
|
||||
const res = await fetch('/api/training/status', { cache: 'no-store' as any })
|
||||
const data = await res.json().catch(() => null)
|
||||
|
||||
if (cancelled || !res.ok || !data) return
|
||||
|
||||
setTrainingTabRunning(Boolean(data?.training?.running))
|
||||
} catch {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
|
||||
void loadTrainingStatus()
|
||||
|
||||
const timer = window.setInterval(
|
||||
() => {
|
||||
void loadTrainingStatus()
|
||||
},
|
||||
trainingTabRunning ? 1500 : 5000
|
||||
)
|
||||
|
||||
const onVisibilityChange = () => {
|
||||
if (!document.hidden) {
|
||||
void loadTrainingStatus()
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener('visibilitychange', onVisibilityChange)
|
||||
|
||||
return () => {
|
||||
cancelled = true
|
||||
window.clearInterval(timer)
|
||||
document.removeEventListener('visibilitychange', onVisibilityChange)
|
||||
}
|
||||
}, [authed, trainingTabRunning])
|
||||
|
||||
const loadPendingAutoStarts = useCallback(async (opts?: { force?: boolean }) => {
|
||||
const force = Boolean(opts?.force)
|
||||
const now = Date.now()
|
||||
@ -2582,7 +2648,7 @@ export default function App() {
|
||||
{
|
||||
id: 'training',
|
||||
label: 'Training',
|
||||
icon: BeakerIcon,
|
||||
icon: trainingTabRunning ? TrainingBeakerIcon : BeakerIcon,
|
||||
},
|
||||
{
|
||||
id: 'settings',
|
||||
|
||||
@ -10,6 +10,10 @@ export type IconProps = SVGProps<SVGSVGElement> & {
|
||||
|
||||
type IconComponent = (props: IconProps) => JSX.Element
|
||||
|
||||
function iconClassName(className: string | undefined, extra: string) {
|
||||
return [className, extra].filter(Boolean).join(' ')
|
||||
}
|
||||
|
||||
function IconBase({
|
||||
title,
|
||||
children,
|
||||
@ -95,6 +99,234 @@ export function FemaleGenitaliaIcon(props: IconProps) {
|
||||
)
|
||||
}
|
||||
|
||||
export function FingeringIcon(props: IconProps) {
|
||||
return (
|
||||
<IconBase {...props}>
|
||||
{/* stilisierte Vulva weiter rechts */}
|
||||
<path d="M18.2 3.6C16.7 4.8 15.5 7.2 15.5 10.7C15.5 15.8 16.8 19.7 18.2 21C19.6 19.7 20.9 15.8 20.9 10.7C20.9 7.2 19.7 4.8 18.2 3.6Z" />
|
||||
<path d="M18.2 6.9C17.4 8.4 16.9 10.4 16.9 12.8C16.9 15.5 17.4 17.7 18.2 19.1C19 17.7 19.5 15.5 19.5 12.8C19.5 10.4 19 8.4 18.2 6.9Z" />
|
||||
<path d="M18.2 9.8V17.2" />
|
||||
|
||||
{/* Zeige- und Mittelfinger seitlich von links */}
|
||||
<path d="M4.2 11.2H15.5" />
|
||||
<path d="M4.7 13.6H15.5" />
|
||||
<path d="M15.5 11.2C16.3 11.2 16.8 11.8 16.8 12.4C16.8 13 16.3 13.6 15.5 13.6" />
|
||||
|
||||
{/* Handfläche / Handkante - bewusst weiter weg von der Vulva */}
|
||||
<path d="M4.7 13.6C3.4 13.6 2.5 14.5 2.5 15.8V16.6C2.5 18.8 4.3 20.5 6.5 20.5H9.7C11.4 20.5 12.8 19.5 13.3 17.9" />
|
||||
|
||||
{/* angedeutete eingeklappte Finger / Knöchel */}
|
||||
<path d="M5.7 15.4C6.3 14.9 7.2 14.9 7.8 15.4" />
|
||||
<path d="M7.9 15.5C8.5 15 9.4 15 10 15.5" />
|
||||
<path d="M10.1 15.6C10.6 15.2 11.4 15.2 11.9 15.6" />
|
||||
|
||||
{/* Daumen */}
|
||||
<path d="M4.8 16.2L3.3 15.1C2.7 14.7 2.6 13.9 3 13.4C3.4 12.8 4.2 12.7 4.8 13.1L5.7 13.8" />
|
||||
|
||||
{/* kleine Bewegungslinien */}
|
||||
<path d="M21.5 10.6L22.7 9.9" />
|
||||
<path d="M21.7 13.2H22.9" />
|
||||
<path d="M21.5 15.8L22.7 16.5" />
|
||||
</IconBase>
|
||||
)
|
||||
}
|
||||
|
||||
export function BlowjobIcon(props: IconProps) {
|
||||
return (
|
||||
<IconBase
|
||||
{...props}
|
||||
className={iconClassName(props.className, 'origin-center scale-[1.35]')}
|
||||
viewBox="30 20 230 390"
|
||||
>
|
||||
<g
|
||||
transform="translate(0,432) scale(0.1,-0.1)"
|
||||
fill="currentColor"
|
||||
stroke="none"
|
||||
>
|
||||
<path d="M703 3936 c-174 -57 -260 -250 -185 -419 28 -62 103 -132 169 -157 245 -92 484 149 392 394 -25 68 -92 140 -157 168 -58 26 -162 33 -219 14z" />
|
||||
<path d="M812 3271 c-60 -21 -114 -68 -143 -124 -11 -20 -94 -163 -184 -317 -112 -190 -165 -289 -165 -309 0 -23 31 -66 148 -205 81 -96 174 -209 207 -250 61 -77 87 -96 130 -96 15 0 42 -18 73 -47 l49 -48 -13 -355 c-9 -254 -22 -438 -44 -648 l-32 -293 24 -47 c42 -84 142 -112 222 -62 60 37 70 72 115 410 52 400 59 460 50 466 -4 2 -69 85 -143 184 -127 168 -136 183 -136 224 0 35 6 50 29 75 28 30 47 36 101 31 34 -3 58 -23 125 -103 32 -37 59 -66 62 -64 2 3 11 63 18 134 l15 128 -35 205 c-19 113 -51 302 -70 420 -67 404 -95 542 -120 586 -30 51 -83 92 -143 110 -58 18 -76 17 -140 -5z m-87 -770 c14 -85 23 -156 21 -158 -7 -7 -136 181 -136 197 0 18 83 137 87 124 1 -5 14 -78 28 -163z" />
|
||||
<path d="M1580 2564 c-157 -60 -228 -142 -238 -274 -7 -111 39 -224 115 -278 16 -11 58 -30 93 -42 170 -57 341 27 391 192 48 156 -14 308 -153 379 -43 22 -173 36 -208 23z" />
|
||||
<path d="M2055 2186 c-38 -16 -84 -82 -92 -130 -7 -46 20 -119 54 -146 15 -11 49 -27 77 -35 93 -27 151 -68 180 -127 15 -29 26 -70 26 -92 1 -41 1 -41 15 -15 25 46 48 187 43 268 -11 195 -166 337 -303 277z" />
|
||||
<path d="M1603 1854 c-17 -9 -83 -69 -145 -135 -76 -80 -120 -119 -134 -119 -15 0 -46 30 -104 101 -45 55 -93 105 -106 111 -49 23 -113 -24 -100 -75 3 -12 31 -56 62 -97 217 -284 203 -269 251 -270 23 0 47 13 92 51 l61 51 0 -73 c0 -62 4 -77 26 -106 28 -37 72 -63 106 -63 13 0 42 9 66 20 l43 19 45 -62 c69 -94 124 -191 130 -228 4 -33 1 -36 -162 -168 -91 -73 -174 -147 -185 -165 -38 -62 -16 -158 44 -191 30 -16 64 -16 472 -8 484 9 489 10 515 72 9 23 9 38 0 66 -21 62 -58 72 -308 80 l-214 7 124 65 c67 36 134 75 146 87 52 46 77 133 60 209 -9 43 -25 65 -127 176 -64 69 -137 153 -162 186 -48 64 -136 209 -187 311 -61 121 -119 164 -219 164 -32 0 -72 -7 -90 -16z" />
|
||||
</g>
|
||||
</IconBase>
|
||||
)
|
||||
}
|
||||
|
||||
export function HandjobIcon(props: IconProps) {
|
||||
return (
|
||||
<IconBase {...props}>
|
||||
{/* Penis vertikal */}
|
||||
<path d="M12 3.6C13.6 3.6 14.9 4.9 14.9 6.5V18.2" />
|
||||
<path d="M12 3.6C10.4 3.6 9.1 4.9 9.1 6.5V18.2" />
|
||||
<path d="M9.1 7H14.9" />
|
||||
|
||||
{/* Hoden */}
|
||||
<circle cx="9.6" cy="19.1" r="1.6" />
|
||||
<circle cx="14.4" cy="19.1" r="1.6" />
|
||||
|
||||
{/* Hand umfasst den Schaft */}
|
||||
<path d="M6.1 11.4C6.1 10.6 6.7 10 7.5 10H15.8C17.1 10 18.1 11 18.1 12.3V14.6C18.1 16.3 16.8 17.6 15.1 17.6H8.6C7.2 17.6 6.1 16.5 6.1 15.1V11.4Z" />
|
||||
|
||||
{/* Finger über dem Schaft */}
|
||||
<path d="M7.4 10.1V7.9C7.4 7.2 7.9 6.7 8.6 6.7C9.3 6.7 9.8 7.2 9.8 7.9V10" />
|
||||
<path d="M9.8 10V7.2C9.8 6.5 10.3 6 11 6C11.7 6 12.2 6.5 12.2 7.2V10" />
|
||||
<path d="M12.2 10V7.7C12.2 7 12.7 6.5 13.4 6.5C14.1 6.5 14.6 7 14.6 7.7V10" />
|
||||
<path d="M14.6 10V8.8C14.6 8.1 15.1 7.6 15.8 7.6C16.5 7.6 17 8.1 17 8.8V11.1" />
|
||||
|
||||
{/* Daumen */}
|
||||
<path d="M6.3 14.2L4.5 13.1C3.9 12.7 3.7 11.9 4.1 11.3C4.5 10.7 5.3 10.5 5.9 10.9L7.3 11.7" />
|
||||
|
||||
{/* Griff-/Bewegungslinien */}
|
||||
<path d="M18.9 10.2L20.2 9.4" />
|
||||
<path d="M19.3 13H20.8" />
|
||||
<path d="M18.9 15.8L20.2 16.6" />
|
||||
</IconBase>
|
||||
)
|
||||
}
|
||||
|
||||
export function SixtyNineIcon(props: IconProps) {
|
||||
return (
|
||||
<IconBase
|
||||
{...props}
|
||||
className={iconClassName(props.className, 'origin-center scale-[1.65]')}
|
||||
viewBox="45 45 410 165"
|
||||
>
|
||||
<g transform="translate(0,262) scale(0.1,-0.1)" fill="currentColor" stroke="none">
|
||||
<path d="M2794 2030 c-72 -15 -162 -68 -239 -142 -41 -39 -75 -74 -75 -79 0 -4 19 1 43 11 85 39 155 21 264 -68 71 -58 104 -68 164 -52 81 22 130 100 116 185 -8 50 -33 81 -91 114 -57 33 -121 44 -182 31z" />
|
||||
<path d="M3213 1780 c-85 -17 -177 -89 -219 -170 -26 -52 -30 -165 -9 -231 24 -72 110 -159 179 -182 63 -21 149 -22 210 -1 64 22 147 100 177 166 71 161 -20 356 -192 409 -65 20 -81 21 -146 9z" />
|
||||
<path d="M1672 1714 c-29 -14 -65 -42 -80 -61 -15 -19 -103 -188 -197 -376 l-170 -342 -205 -7 c-365 -14 -433 -21 -474 -49 -40 -27 -70 -89 -60 -123 11 -37 46 -66 98 -81 72 -22 732 -21 824 0 120 28 123 31 280 273 126 194 147 222 181 235 63 26 179 45 313 52 122 7 127 7 140 -14 12 -19 21 -21 130 -21 l118 0 0 -32 c-1 -18 -11 -120 -24 -227 -18 -148 -21 -201 -13 -219 23 -49 43 -52 370 -52 361 0 388 3 428 42 56 57 27 149 -52 162 -19 3 -133 11 -254 17 -121 6 -220 12 -221 13 0 0 26 114 59 251 69 292 73 341 34 407 -32 55 -71 85 -133 104 -36 11 -87 11 -272 3 -263 -12 -297 -10 -523 36 -201 42 -230 43 -297 9z" />
|
||||
<path d="M3632 1304 l-264 -175 -234 1 -233 1 -6 -23 c-27 -117 -35 -161 -32 -164 2 -3 94 -9 203 -15 109 -6 216 -15 237 -20 91 -23 132 -110 88 -185 -12 -20 -19 -39 -16 -42 8 -8 123 26 181 55 80 39 204 142 280 232 37 45 73 81 80 81 6 0 87 -64 179 -142 225 -193 241 -203 326 -203 61 0 72 3 95 27 40 40 45 118 12 190 -21 44 -56 82 -204 218 -267 246 -381 340 -412 340 -10 0 -136 -79 -280 -176z" />
|
||||
<path d="M1335 1431 c-117 -56 -179 -153 -178 -276 0 -67 20 -136 43 -150 5 -3 61 97 125 225 129 258 129 258 10 201z" />
|
||||
<path d="M1902 1125 c-159 -81 -188 -288 -57 -403 66 -59 84 -62 349 -62 132 0 257 3 277 6 l37 6 -16 28 c-15 25 -14 43 7 229 13 111 20 205 17 209 -4 4 -132 8 -284 10 l-277 3 -53 -26z" />
|
||||
</g>
|
||||
</IconBase>
|
||||
)
|
||||
}
|
||||
|
||||
export function CowgirlIcon(props: IconProps) {
|
||||
return (
|
||||
<IconBase
|
||||
{...props}
|
||||
className={iconClassName(props.className, 'origin-center scale-[1.35]')}
|
||||
viewBox="45 15 350 270"
|
||||
>
|
||||
<g transform="translate(0,300) scale(0.1,-0.1)" fill="currentColor" stroke="none">
|
||||
<path d="M2253 2766 c-91 -30 -148 -80 -190 -171 -70 -151 -4 -326 151 -399 112 -53 245 -29 341 63 151 143 101 407 -93 493 -58 26 -154 32 -209 14z" />
|
||||
<path d="M2672 2283 c-42 -20 -69 -55 -82 -104 -17 -62 2 -111 71 -185 33 -36 67 -80 75 -99 18 -45 18 -116 -1 -162 -20 -48 -19 -50 11 -22 42 39 114 139 147 204 39 77 48 182 23 250 -43 111 -152 164 -244 118z" />
|
||||
<path d="M2255 2076 c-48 -22 -89 -73 -156 -196 -147 -269 -157 -302 -107 -378 30 -45 83 -67 145 -60 32 4 34 2 48 -46 43 -144 61 -386 34 -439 -8 -14 -99 -117 -202 -228 -104 -112 -195 -219 -203 -237 -22 -54 -18 -150 9 -202 40 -82 36 -81 482 -78 l390 3 55 30 c37 20 65 45 87 78 35 53 308 280 331 275 7 -2 91 -70 188 -153 97 -82 195 -160 217 -173 55 -30 143 -31 180 -2 32 26 51 81 44 131 -11 86 -40 120 -295 362 -291 273 -306 287 -336 287 -15 0 -139 -84 -322 -218 -398 -289 -416 -302 -442 -302 -12 0 -22 4 -22 8 0 4 69 59 153 122 153 113 194 155 215 219 21 61 13 103 -58 305 -79 223 -93 291 -110 521 -7 88 -19 184 -27 213 -17 63 -70 127 -128 153 -47 22 -127 24 -170 5z" />
|
||||
<path d="M664 766 c-218 -71 -285 -346 -124 -506 148 -149 397 -105 490 85 35 70 35 189 2 257 -30 60 -87 117 -147 147 -58 29 -161 37 -221 17z" />
|
||||
<path d="M1265 676 c-56 -25 -107 -78 -130 -133 -35 -83 -6 -202 66 -270 62 -59 82 -62 345 -63 132 0 246 -1 255 0 13 0 11 10 -13 56 -23 47 -28 70 -28 128 0 90 26 150 101 230 30 32 56 62 57 67 2 5 -127 9 -300 9 -296 0 -304 -1 -353 -24z" />
|
||||
</g>
|
||||
</IconBase>
|
||||
)
|
||||
}
|
||||
|
||||
export function CunnilingusIcon(props: IconProps) {
|
||||
return (
|
||||
<IconBase
|
||||
{...props}
|
||||
className={iconClassName(props.className, 'origin-center scale-[1.8]')}
|
||||
viewBox="15 40 455 125"
|
||||
>
|
||||
<g transform="translate(0,204) scale(0.1,-0.1)" fill="currentColor" stroke="none">
|
||||
<path d="M3140 1498 c-23 -16 -68 -76 -133 -181 -94 -150 -100 -157 -131 -157 -22 0 -40 -8 -55 -24 -23 -25 -24 -44 -6 -103 6 -18 -7 -36 -76 -106 -46 -46 -117 -110 -157 -141 -41 -32 -87 -79 -104 -105 -27 -42 -29 -52 -26 -121 4 -89 26 -128 91 -162 57 -29 153 -29 342 1 163 25 232 25 419 -5 122 -19 159 -11 217 47 100 100 105 222 13 297 -92 75 -239 176 -272 187 -24 9 -46 10 -69 3 -31 -8 -38 -6 -79 27 -24 20 -44 43 -44 52 0 8 43 94 96 191 110 201 124 250 82 289 -37 34 -68 37 -108 11z m-125 -678 l29 -30 -47 0 -48 0 16 30 c9 17 17 30 18 30 2 0 16 -13 32 -30z" />
|
||||
<path d="M2422 1199 c-96 -48 -154 -157 -138 -262 9 -59 58 -131 110 -162 75 -43 83 -42 166 26 113 91 200 181 200 204 0 64 -83 171 -156 201 -50 21 -132 18 -182 -7z" />
|
||||
<path d="M1975 974 c-55 -14 -212 -52 -350 -84 -291 -68 -292 -68 -342 -114 -34 -30 -56 -38 -173 -66 -351 -83 -332 -80 -592 -80 -259 0 -275 -3 -317 -56 -26 -33 -28 -95 -4 -135 33 -55 55 -59 344 -59 374 0 698 23 864 61 72 16 137 32 145 34 11 4 19 -5 25 -27 6 -19 21 -38 35 -45 31 -16 640 -18 721 -3 97 19 129 83 68 134 -30 26 -31 26 -212 26 -100 0 -188 4 -195 9 -9 5 19 16 80 30 51 12 107 30 124 40 143 87 115 307 -44 351 -50 14 -62 12 -177 -16z" />
|
||||
<path d="M3816 856 c-94 -35 -148 -106 -154 -202 -10 -146 87 -254 228 -254 155 0 264 142 225 292 -33 128 -180 208 -299 164z" />
|
||||
<path d="M4229 645 c-36 -20 -59 -58 -59 -99 0 -56 16 -84 67 -116 98 -62 223 -31 348 85 33 31 51 53 40 50 -61 -21 -81 -24 -116 -16 -38 9 -79 33 -137 83 -37 32 -98 37 -143 13z" />
|
||||
</g>
|
||||
</IconBase>
|
||||
)
|
||||
}
|
||||
|
||||
export function DoggyIcon(props: IconProps) {
|
||||
return (
|
||||
<IconBase {...props} viewBox="25 20 285 275">
|
||||
<g transform="translate(0,322) scale(0.1,-0.1)" fill="currentColor" stroke="none">
|
||||
<path d="M1251 2965 c-129 -36 -221 -159 -221 -296 0 -119 91 -248 201 -284 113 -38 251 -5 326 78 58 65 78 120 77 212 -1 95 -17 137 -77 202 -79 86 -194 119 -306 88z" />
|
||||
<path d="M1074 2314 c-65 -23 -120 -76 -143 -139 -22 -58 -153 -470 -233 -730 -56 -181 -56 -206 -8 -292 25 -45 35 -84 65 -279 19 -125 35 -237 35 -250 l0 -24 -182 0 c-207 0 -238 -8 -295 -73 -57 -65 -53 -154 9 -214 62 -60 77 -63 431 -70 178 -3 335 -3 350 1 48 12 57 48 57 218 0 84 -9 262 -19 396 l-19 242 24 83 c81 267 127 413 133 420 4 4 15 -16 24 -45 14 -43 43 -83 157 -213 267 -304 302 -331 375 -301 70 30 83 89 34 156 -38 52 -28 63 51 55 188 -18 183 -18 219 7 58 39 76 72 76 137 -1 95 -51 147 -153 157 -85 9 -150 -15 -213 -78 -27 -27 -59 -68 -70 -91 l-21 -41 -22 30 c-11 16 -31 40 -44 53 -13 13 -49 57 -79 98 -53 73 -55 77 -115 301 -33 125 -67 254 -76 287 -44 170 -191 254 -348 199z" />
|
||||
<path d="M2485 1737 c-103 -34 -171 -97 -205 -187 -75 -202 71 -415 283 -413 267 3 401 313 222 511 -71 79 -207 119 -300 89z" />
|
||||
<path d="M1383 1280 c-58 -12 -95 -33 -133 -76 -67 -77 -76 -153 -36 -294 20 -71 76 -377 76 -418 0 -6 -10 -12 -22 -12 -65 -1 -68 -5 -68 -99 0 -54 -5 -96 -14 -113 -12 -23 -12 -27 1 -32 8 -3 94 -6 192 -6 242 0 221 -27 221 286 0 229 1 245 18 241 9 -3 86 -16 171 -29 l153 -23 25 -50 c72 -144 179 -184 272 -101 l24 21 -6 -35 c-18 -107 -29 -230 -23 -253 11 -45 48 -49 384 -40 l304 8 29 33 c32 36 37 67 14 99 -22 32 -64 39 -280 53 -104 7 -193 14 -196 16 -3 1 12 97 32 211 21 114 38 222 39 239 0 45 -49 135 -89 161 -51 34 -93 37 -238 18 -91 -12 -158 -16 -213 -11 l-80 6 -43 -45 c-41 -43 -46 -45 -98 -45 -66 1 -108 24 -169 95 -104 120 -185 205 -194 204 -6 -1 -30 -5 -53 -9z" />
|
||||
</g>
|
||||
</IconBase>
|
||||
)
|
||||
}
|
||||
|
||||
export function MissionaryIcon(props: IconProps) {
|
||||
return (
|
||||
<IconBase
|
||||
{...props}
|
||||
className={iconClassName(props.className, 'origin-center scale-[1.55]')}
|
||||
viewBox="25 35 415 195"
|
||||
>
|
||||
<g transform="translate(0,266) scale(0.1,-0.1)" fill="currentColor" stroke="none">
|
||||
<path d="M2750 2166 c-72 -19 -117 -45 -156 -88 -78 -86 -103 -208 -65 -309 64 -170 253 -252 411 -178 72 34 117 79 153 157 26 57 29 71 25 135 -9 141 -90 240 -228 281 -63 19 -79 19 -140 2z" />
|
||||
<path d="M2194 1771 c-30 -14 -385 -243 -413 -267 -10 -8 173 -420 186 -417 5 1 92 47 192 102 101 56 187 99 191 96 4 -2 13 -18 20 -34 10 -26 9 -36 -9 -74 -12 -24 -21 -61 -21 -84 l0 -40 -167 -7 c-93 -4 -183 -8 -201 -9 l-34 -2 -104 235 c-57 129 -104 239 -104 245 0 5 23 25 51 43 28 19 47 37 43 42 -5 4 -54 33 -110 64 -117 65 -166 72 -225 33 -47 -31 -82 -101 -75 -152 3 -22 26 -218 51 -435 25 -217 53 -419 61 -447 36 -128 178 -182 366 -138 177 41 378 65 622 75 219 10 256 9 288 -4 88 -37 163 27 146 124 -1 8 4 35 11 60 10 36 11 56 1 98 -15 67 -50 108 -149 175 -42 28 -79 55 -83 61 -7 10 -60 143 -173 434 -28 75 -60 138 -79 160 -66 75 -192 104 -282 63z" />
|
||||
<path d="M1360 1199 c-16 -23 -35 -61 -41 -83 -6 -23 -14 -48 -18 -55 -7 -14 -165 -131 -270 -202 l-44 -29 -317 0 c-312 0 -318 0 -350 -23 -75 -50 -95 -143 -48 -215 47 -70 53 -71 455 -78 l358 -7 196 95 196 95 -28 249 c-16 137 -30 258 -31 268 -5 34 -26 28 -58 -15z" />
|
||||
<path d="M3222 1154 c-136 -42 -233 -205 -203 -343 41 -191 223 -297 407 -234 67 23 154 110 177 177 67 197 -61 399 -261 411 -44 3 -85 -1 -120 -11z" />
|
||||
<path d="M3785 911 c-48 -12 -82 -39 -105 -85 -40 -84 -17 -152 72 -213 122 -81 280 -41 450 116 38 35 67 65 66 67 -2 1 -30 -6 -62 -17 -90 -31 -154 -12 -248 70 -45 40 -104 72 -130 70 -7 -1 -27 -4 -43 -8z" />
|
||||
</g>
|
||||
</IconBase>
|
||||
)
|
||||
}
|
||||
|
||||
export function ReverseCowgirlIcon(props: IconProps) {
|
||||
return (
|
||||
<IconBase
|
||||
{...props}
|
||||
className={iconClassName(props.className, 'origin-center scale-[1.35]')}
|
||||
viewBox="45 15 350 270"
|
||||
>
|
||||
<g transform="translate(0,300) scale(0.1,-0.1)" fill="currentColor" stroke="none">
|
||||
<path d="M2422 2770 c-64 -14 -142 -60 -175 -105 -54 -74 -69 -122 -65 -205 7 -126 69 -214 186 -268 46 -21 65 -24 126 -20 120 8 212 71 261 179 24 55 27 71 23 138 -4 60 -11 88 -34 131 -60 110 -200 175 -322 150z" />
|
||||
<path d="M2026 2290 c-69 -21 -136 -130 -136 -221 0 -49 32 -147 67 -202 30 -49 124 -169 128 -165 2 2 -3 27 -11 57 -23 89 9 174 100 259 49 47 62 84 53 154 -6 46 -45 93 -94 114 -36 16 -64 16 -107 4z" />
|
||||
<path d="M2415 2079 c-45 -13 -110 -72 -133 -121 -15 -32 -23 -83 -32 -193 -21 -272 -34 -341 -106 -549 -91 -265 -90 -261 -70 -330 14 -46 29 -70 69 -110 29 -28 68 -59 87 -69 33 -16 14 -17 -443 -17 -523 0 -511 1 -581 -60 -105 -93 -106 -251 -1 -353 71 -69 49 -68 927 -65 782 3 787 3 815 24 52 39 68 80 67 174 l0 86 65 52 c36 28 75 52 86 51 11 0 94 -63 185 -141 91 -77 185 -153 209 -169 116 -75 236 -29 234 91 -1 90 -34 131 -318 402 -143 136 -271 251 -284 254 -38 11 -65 -4 -249 -140 -200 -147 -167 -145 -283 -14 -62 70 -68 81 -75 134 -8 69 9 222 39 342 l22 87 50 0 c71 0 112 20 136 66 30 61 25 107 -24 201 -155 295 -179 331 -241 359 -44 20 -101 23 -151 8z" />
|
||||
<path d="M635 746 c-69 -32 -112 -70 -140 -127 -37 -73 -48 -132 -35 -196 32 -150 146 -246 295 -247 59 0 79 4 130 31 111 58 165 146 165 269 0 123 -65 221 -181 274 -64 29 -168 27 -234 -4z" />
|
||||
</g>
|
||||
</IconBase>
|
||||
)
|
||||
}
|
||||
|
||||
export function StandingSexIcon(props: IconProps) {
|
||||
return (
|
||||
<IconBase {...props} viewBox="20 20 195 375">
|
||||
<g transform="translate(0,420) scale(0.1,-0.1)" fill="currentColor" stroke="none">
|
||||
<path d="M1280 3832 c-54 -22 -119 -62 -142 -88 -35 -40 -71 -135 -71 -190 0 -143 70 -239 213 -295 192 -74 404 76 404 286 0 116 -66 222 -171 275 -64 32 -169 38 -233 12z" />
|
||||
<path d="M510 3776 c-135 -29 -233 -154 -233 -298 0 -225 235 -369 438 -269 210 104 227 392 32 525 -34 23 -73 39 -111 45 -33 6 -62 11 -65 10 -3 0 -31 -6 -61 -13z" />
|
||||
<path d="M1763 3400 c-70 -31 -107 -115 -85 -188 7 -22 38 -64 76 -104 36 -37 72 -83 81 -104 18 -43 20 -108 4 -153 -6 -18 -9 -34 -7 -36 8 -8 110 129 138 185 81 160 74 276 -22 367 -59 56 -113 66 -185 33z" />
|
||||
<path d="M1345 3166 c-27 -12 -145 -133 -256 -261 -54 -63 -99 -134 -99 -155 0 -9 14 -45 31 -79 33 -66 67 -91 124 -91 24 0 25 -2 25 -67 l0 -68 108 -77 c59 -42 150 -99 202 -127 52 -29 103 -62 112 -74 61 -80 -4 -227 -101 -227 -40 0 -123 30 -233 86 -37 19 -72 34 -78 34 -5 0 -10 -22 -10 -48 0 -45 -3 -51 -42 -83 -135 -107 -466 -403 -476 -424 -17 -37 -15 -85 6 -122 17 -31 324 -386 390 -450 41 -40 84 -43 133 -10 51 34 53 100 5 148 -13 13 -74 84 -135 157 -110 133 -124 160 -98 192 13 17 111 80 198 127 158 86 434 261 464 295 48 52 70 131 56 200 -50 249 -61 485 -36 723 19 183 19 221 -6 275 -41 90 -113 140 -201 140 -29 -1 -66 -7 -83 -14z" />
|
||||
<path d="M592 3101 c-65 -22 -126 -79 -148 -138 -24 -61 -16 -139 56 -573 33 -201 66 -405 74 -454 17 -101 46 -154 109 -195 32 -21 37 -29 37 -64 0 -21 4 -37 9 -35 5 2 83 68 173 147 89 80 166 147 170 150 4 3 -2 60 -12 126 -10 66 -16 122 -15 124 6 6 195 -90 195 -98 0 -11 154 -81 210 -96 52 -14 81 -6 104 27 19 27 21 98 4 120 -7 9 -58 42 -113 73 -55 32 -137 84 -183 116 -45 33 -86 59 -90 59 -22 1 -81 74 -143 178 -70 115 -71 119 -94 249 -13 72 -33 149 -44 171 -28 54 -82 98 -143 117 -66 19 -91 19 -156 -4z" />
|
||||
<path d="M1370 1623 c-91 -57 -173 -107 -182 -110 -16 -5 -18 -23 -18 -192 0 -175 1 -187 20 -199 30 -18 70 -106 70 -151 0 -30 -7 -49 -29 -73 l-28 -33 30 -215 c36 -264 41 -286 73 -307 33 -21 103 -21 136 1 54 36 58 97 29 460 l-19 229 49 336 c53 363 53 361 42 360 -5 0 -82 -48 -173 -106z" />
|
||||
<path d="M1033 1419 c-29 -17 -53 -36 -53 -42 0 -7 25 -39 55 -72 l54 -60 1 103 c0 56 -1 102 -2 102 -2 0 -27 -14 -55 -31z" />
|
||||
<path d="M744 1108 c7 -93 5 -105 -53 -367 -34 -149 -61 -288 -61 -309 0 -80 75 -152 158 -152 42 0 104 32 126 64 9 15 44 137 77 273 60 242 61 247 42 263 -11 8 -75 78 -142 155 -68 77 -130 147 -138 155 -14 13 -15 4 -9 -82z" />
|
||||
</g>
|
||||
</IconBase>
|
||||
)
|
||||
}
|
||||
|
||||
export function StandingDoggySexIcon(props: IconProps) {
|
||||
return (
|
||||
<IconBase
|
||||
{...props}
|
||||
className={iconClassName(props.className, 'origin-center scale-[1.25]')}
|
||||
viewBox="0 0 212 402"
|
||||
>
|
||||
<g
|
||||
transform="translate(0,402) scale(0.1,-0.1)"
|
||||
fill="currentColor"
|
||||
stroke="none"
|
||||
>
|
||||
<path d="M325 3703 c-70 -25 -107 -55 -148 -115 -47 -73 -60 -119 -54 -193 12 -158 133 -275 294 -283 60 -4 80 0 127 21 194 89 246 330 106 490 -73 83 -217 118 -325 80z" />
|
||||
<path d="M1503 3640 c-64 -26 -137 -95 -166 -158 -16 -36 -22 -66 -22 -127 0 -94 24 -154 88 -218 60 -60 117 -82 212 -82 98 0 155 23 219 90 143 146 99 391 -86 486 -62 32 -176 36 -245 9z" />
|
||||
<path d="M1070 3281 c-73 -26 -134 -92 -156 -169 -20 -69 -15 -214 12 -317 l18 -69 11 54 c21 102 64 147 180 185 44 15 92 36 106 46 59 42 78 148 37 209 -51 75 -116 94 -208 61z" />
|
||||
<path d="M450 3045 c-87 -27 -162 -113 -175 -202 -8 -46 146 -989 171 -1052 9 -23 38 -61 66 -86 l50 -45 16 -353 16 -353 -28 -129 c-15 -72 -43 -199 -63 -283 -23 -103 -33 -165 -29 -188 8 -39 47 -89 87 -109 63 -33 174 -3 204 55 9 17 48 158 87 313 l70 282 14 415 14 415 -30 194 c-17 106 -28 196 -25 199 3 4 16 0 28 -8 36 -23 309 -156 359 -175 59 -22 93 -14 118 28 43 69 19 114 -92 172 -91 48 -281 173 -330 217 -20 18 -68 88 -106 155 -67 118 -70 126 -90 247 -12 69 -30 143 -41 164 -29 56 -92 108 -152 126 -63 19 -80 19 -139 1z" />
|
||||
<path d="M1431 2974 c-51 -19 -117 -81 -137 -129 -8 -19 -30 -117 -49 -217 -19 -101 -46 -223 -60 -271 -14 -48 -25 -89 -25 -91 0 -8 125 -83 198 -120 49 -25 76 -45 87 -65 17 -34 20 -88 6 -124 -14 -36 -61 -76 -96 -83 -35 -6 -145 30 -246 82 -36 19 -70 34 -76 34 -6 0 -20 -26 -33 -59 -17 -46 -20 -69 -15 -107 8 -58 35 -121 62 -150 12 -12 35 -75 57 -160 21 -76 55 -202 76 -279 21 -77 48 -177 59 -222 l21 -82 -45 -283 c-44 -280 -45 -309 -20 -371 16 -39 110 -61 156 -37 27 15 47 59 64 142 8 40 39 181 69 313 l55 240 -14 109 c-29 218 -75 609 -75 637 0 15 5 40 11 56 11 26 13 21 39 -80 31 -126 53 -157 111 -157 29 0 43 7 63 31 15 17 26 43 26 59 0 16 -21 168 -46 338 -38 264 -43 317 -34 352 l11 41 54 -6 c79 -10 137 19 161 81 16 42 16 48 0 107 -22 78 -138 348 -171 399 -47 71 -157 103 -244 72z" />
|
||||
</g>
|
||||
</IconBase>
|
||||
)
|
||||
}
|
||||
|
||||
export function MaleGenitaliaIcon(props: IconProps) {
|
||||
return (
|
||||
<IconBase {...props}>
|
||||
@ -431,29 +663,6 @@ export function TongueIcon(props: IconProps) {
|
||||
)
|
||||
}
|
||||
|
||||
export function BackIcon(props: IconProps) {
|
||||
return (
|
||||
<IconBase {...props}>
|
||||
{/* äußere Rücken-/Schulterkontur links */}
|
||||
<path d="M7.2 4C7.2 5.8 6.5 6.9 5.3 7.7C3.9 8.7 3.2 10.1 3.2 12V20" />
|
||||
|
||||
{/* äußere Rücken-/Schulterkontur rechts */}
|
||||
<path d="M16.8 4C16.8 5.8 17.5 6.9 18.7 7.7C20.1 8.7 20.8 10.1 20.8 12V20" />
|
||||
|
||||
{/* obere innere Schulterlinien */}
|
||||
<path d="M10 6.2C10 7.4 9.5 8.3 8.7 9" />
|
||||
<path d="M14 6.2C14 7.4 14.5 8.3 15.3 9" />
|
||||
|
||||
{/* innere Rückenlinien */}
|
||||
<path d="M9 10.3C9.6 12.3 9.9 14.5 9.9 16.9V20" />
|
||||
<path d="M15 10.3C14.4 12.3 14.1 14.5 14.1 16.9V20" />
|
||||
|
||||
{/* Wirbelsäulenlinie */}
|
||||
<path d="M12 9.4V20" />
|
||||
</IconBase>
|
||||
)
|
||||
}
|
||||
|
||||
export function BathIcon(props: IconProps) {
|
||||
return (
|
||||
<IconBase {...props}>
|
||||
@ -618,6 +827,87 @@ type SegmentLabelMeta = {
|
||||
}
|
||||
|
||||
const SEGMENT_LABEL_META: SegmentLabelMeta[] = [
|
||||
// Sex positions
|
||||
{
|
||||
match: ['69', 'sixty_nine', 'sixty-nine', 'sixtynine'],
|
||||
text: '69',
|
||||
icon: SixtyNineIcon,
|
||||
},
|
||||
{
|
||||
match: ['missionary'],
|
||||
text: 'Missionary',
|
||||
icon: MissionaryIcon,
|
||||
},
|
||||
{
|
||||
match: ['reverse_cowgirl', 'reverse-cowgirl', 'reverse cowgirl'],
|
||||
text: 'Reverse Cowgirl',
|
||||
icon: ReverseCowgirlIcon,
|
||||
},
|
||||
{
|
||||
match: ['cowgirl', 'riding', 'ride'],
|
||||
text: 'Cowgirl',
|
||||
icon: CowgirlIcon,
|
||||
},
|
||||
{
|
||||
match: ['blowjob', 'fellatio'],
|
||||
text: 'Blowjob',
|
||||
icon: BlowjobIcon,
|
||||
},
|
||||
{
|
||||
match: ['cunnilingus'],
|
||||
text: 'Cunnilingus',
|
||||
icon: CunnilingusIcon,
|
||||
},
|
||||
{
|
||||
match: ['facesitting', 'face_sitting', 'face-sitting', 'face sitting'],
|
||||
text: 'Facesitting',
|
||||
icon: FemalePersonIcon,
|
||||
},
|
||||
{
|
||||
match: ['oral'],
|
||||
text: 'Oral',
|
||||
icon: MouthIcon,
|
||||
},
|
||||
{
|
||||
match: ['anal'],
|
||||
text: 'Anal',
|
||||
icon: AnusIcon,
|
||||
},
|
||||
{
|
||||
match: ['handjob', 'hand_job', 'hand-job', 'manual'],
|
||||
text: 'Handjob',
|
||||
icon: HandjobIcon,
|
||||
},
|
||||
{
|
||||
match: ['fingering', 'fingered'],
|
||||
text: 'Fingering',
|
||||
icon: FingeringIcon,
|
||||
},
|
||||
{
|
||||
match: ['solo', 'masturbation'],
|
||||
text: 'Solo',
|
||||
icon: HandIcon,
|
||||
},
|
||||
{
|
||||
match: ['standing_doggy', 'standing-doggy', 'standing doggy'],
|
||||
text: 'Standing Doggy',
|
||||
icon: StandingDoggySexIcon,
|
||||
},
|
||||
{
|
||||
match: ['standing', 'standing_sex', 'standing-sex', 'standing sex'],
|
||||
text: 'Stehend',
|
||||
icon: StandingSexIcon,
|
||||
},
|
||||
{
|
||||
match: ['doggy', 'doggystyle', 'doggy_style'],
|
||||
text: 'Doggy',
|
||||
icon: DoggyIcon,
|
||||
},
|
||||
{
|
||||
match: ['unknown'],
|
||||
text: 'Unbekannt',
|
||||
icon: UnknownContentIcon,
|
||||
},
|
||||
// People
|
||||
{
|
||||
match: ['person_female', 'female_person'],
|
||||
@ -646,11 +936,6 @@ const SEGMENT_LABEL_META: SegmentLabelMeta[] = [
|
||||
text: 'Hintern',
|
||||
icon: ButtocksIcon,
|
||||
},
|
||||
{
|
||||
match: ['back'],
|
||||
text: 'Rücken',
|
||||
icon: BackIcon,
|
||||
},
|
||||
{
|
||||
match: ['breasts', 'female_breast_exposed', 'breast_exposed', 'breasts_exposed', 'female_breast'],
|
||||
text: 'Brüste',
|
||||
@ -911,10 +1196,6 @@ function findSegmentLabelMeta(label?: string): SegmentLabelMeta | null {
|
||||
}
|
||||
}
|
||||
|
||||
if (normalized.includes('back')) {
|
||||
return { match: [], text: 'Rücken', icon: BackIcon }
|
||||
}
|
||||
|
||||
if (normalized.includes('ass') || normalized.includes('butt') || normalized.includes('bottom')) {
|
||||
return { match: [], text: 'Hintern', icon: ButtocksIcon }
|
||||
}
|
||||
@ -1074,7 +1355,17 @@ function findSegmentLabelMeta(label?: string): SegmentLabelMeta | null {
|
||||
return { match: [], text: 'Schuhe', icon: ShoesIcon }
|
||||
}
|
||||
|
||||
if (normalized.includes('face')) {
|
||||
if (
|
||||
normalized === 'face' ||
|
||||
normalized === 'face_female' ||
|
||||
normalized === 'face_male' ||
|
||||
normalized === 'female_face' ||
|
||||
normalized === 'male_face' ||
|
||||
normalized.includes('face_exposed') ||
|
||||
normalized.includes('face_covered') ||
|
||||
normalized.endsWith('_face') ||
|
||||
normalized.startsWith('face_')
|
||||
) {
|
||||
return { match: [], text: 'Gesicht', icon: FaceIcon }
|
||||
}
|
||||
|
||||
@ -1152,6 +1443,14 @@ function prettifyUnknownLabel(label?: string): string {
|
||||
.replace(/\bfeet\b/g, 'Füße')
|
||||
.replace(/\bfoot\b/g, 'Fuß')
|
||||
.replace(/\bface\b/g, 'Gesicht')
|
||||
.replace(/\bfacesitting\b/g, 'Facesitting')
|
||||
.replace(/\bface sitting\b/g, 'Facesitting')
|
||||
.replace(/\bfingering\b/g, 'Fingering')
|
||||
.replace(/\bfingered\b/g, 'Fingering')
|
||||
.replace(/\bblowjob\b/g, 'Blowjob')
|
||||
.replace(/\bfellatio\b/g, 'Blowjob')
|
||||
.replace(/\bhandjob\b/g, 'Handjob')
|
||||
.replace(/\bhand job\b/g, 'Handjob')
|
||||
.replace(/\bcovered\b/g, 'bedeckt')
|
||||
.replace(/\bexposed\b/g, 'erkannt')
|
||||
.replace(/\s+/g, ' ')
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user