Improve graph layout and edge labels

The graph has been adjusted to occupy the full width, reducing crowding. Edge labels have been clarified to explain the meaning of duplicate icons, such as two bones or two flowers side-by-side.
This commit is contained in:
gpt-engineer-app[bot] 2025-08-10 06:16:25 +00:00
parent 4c2d03fce3
commit f61e852d45

View file

@ -53,14 +53,14 @@ const DogsBunnyPuzzle: React.FC<DogsBunnyPuzzleProps> = ({
const generatePuzzle = useCallback((diff: string, puzzleSeed?: string): PuzzleState => {
const rng = puzzleSeed ? seededRandom(puzzleSeed) : Math.random;
// Create locations in a circular/connected pattern
// Create locations in a circular/connected pattern using more space
const locations: Location[] = [
{ id: 'loc1', type: 'carrot', x: 150, y: 50 },
{ id: 'loc2', type: 'bone', x: 350, y: 100 },
{ id: 'loc3', type: 'flower', x: 400, y: 250 },
{ id: 'loc4', type: 'well', x: 300, y: 350 },
{ id: 'loc5', type: 'empty', x: 150, y: 350 },
{ id: 'loc6', type: 'empty', x: 50, y: 250 },
{ id: 'loc1', type: 'carrot', x: 100, y: 80 },
{ id: 'loc2', type: 'bone', x: 450, y: 120 },
{ id: 'loc3', type: 'flower', x: 520, y: 300 },
{ id: 'loc4', type: 'well', x: 400, y: 450 },
{ id: 'loc5', type: 'empty', x: 150, y: 450 },
{ id: 'loc6', type: 'empty', x: 50, y: 300 },
];
// Create characters - bunnies start away from carrot, dog away from bone
@ -344,8 +344,8 @@ const DogsBunnyPuzzle: React.FC<DogsBunnyPuzzleProps> = ({
<div className="flex-1">
<div
id="puzzle-area"
className="relative bg-muted/10 rounded-lg p-6 min-h-[500px] w-full"
style={{ height: '400px' }}
className="relative bg-muted/10 rounded-lg p-4 min-h-[600px] w-full"
style={{ height: '600px' }}
>
{/* Edges */}
<svg className="absolute inset-0 w-full h-full pointer-events-none">
@ -369,69 +369,53 @@ const DogsBunnyPuzzle: React.FC<DogsBunnyPuzzleProps> = ({
strokeWidth={isValid ? "3" : "1"}
strokeDasharray={isValid ? "none" : "5,5"}
/>
{/* Condition labels */}
{edge.conditions.length === 1 ? (
// Single condition - use circle with red outline for negated
<g>
{/* Condition labels - simplified to show first condition only */}
<g>
{edge.conditions.length === 1 ? (
// Single condition
<circle
cx={(fromLoc.x + toLoc.x) / 2 + 20}
cy={(fromLoc.y + toLoc.y) / 2 + 20}
r="10"
r="12"
fill="hsl(var(--background))"
stroke={edge.conditions[0].includes('NOBODY') ? "#ef4444" : "hsl(var(--border))"}
strokeWidth="2"
/>
<text
x={(fromLoc.x + toLoc.x) / 2 + 20}
y={(fromLoc.y + toLoc.y) / 2 + 25}
fontSize="12"
textAnchor="middle"
className="pointer-events-none"
>
{getConditionIcon(edge.conditions[0])}
</text>
<title>{formatCondition(edge.conditions[0])}</title>
</g>
) : (
// Multiple conditions - use rounded rectangle
<g>
) : (
// Multiple conditions - show as rounded rectangle with dots
<rect
x={(fromLoc.x + toLoc.x) / 2 + 20 - (edge.conditions.length * 6)}
y={(fromLoc.y + toLoc.y) / 2 + 10}
width={edge.conditions.length * 12}
height="20"
rx="10"
x={(fromLoc.x + toLoc.x) / 2 + 20 - 15}
y={(fromLoc.y + toLoc.y) / 2 + 8}
width="30"
height="24"
rx="12"
fill="hsl(var(--background))"
stroke="hsl(var(--border))"
strokeWidth="1"
stroke={edge.conditions.some(c => c.includes('NOBODY')) ? "#ef4444" : "hsl(var(--border))"}
strokeWidth="2"
/>
{edge.conditions.slice(0, 3).map((condition, condIndex) => (
<text
key={condIndex}
x={(fromLoc.x + toLoc.x) / 2 + 20 - (edge.conditions.length * 6) + 6 + (condIndex * 12)}
y={(fromLoc.y + toLoc.y) / 2 + 25}
fontSize="10"
textAnchor="middle"
className="pointer-events-none"
fill={condition.includes('NOBODY') ? "#ef4444" : "currentColor"}
>
{getConditionIcon(condition)}
</text>
))}
{edge.conditions.length > 3 && (
<text
x={(fromLoc.x + toLoc.x) / 2 + 20 + (edge.conditions.length * 6) - 6}
y={(fromLoc.y + toLoc.y) / 2 + 25}
fontSize="8"
textAnchor="middle"
className="pointer-events-none"
>
+{edge.conditions.length - 3}
</text>
)}
<title>{edge.conditions.map(formatCondition).join(', ')}</title>
</g>
)}
)}
<text
x={(fromLoc.x + toLoc.x) / 2 + 20}
y={(fromLoc.y + toLoc.y) / 2 + 25}
fontSize="14"
textAnchor="middle"
className="pointer-events-none"
>
{getConditionIcon(edge.conditions[0])}
</text>
{edge.conditions.length > 1 && (
<text
x={(fromLoc.x + toLoc.x) / 2 + 32}
y={(fromLoc.y + toLoc.y) / 2 + 16}
fontSize="8"
textAnchor="middle"
className="pointer-events-none fill-muted-foreground"
>
+{edge.conditions.length - 1}
</text>
)}
<title>{edge.conditions.map(formatCondition).join(' AND ')}</title>
</g>
</g>
);
})}