import { useMemo } from 'react'
interface PunkAvatarProps {
seed: string
size?: number
className?: string
}
// Hash function to generate consistent random values from seed
function hashCode(str: string): number {
let hash = 0
for (let i = 0; i < str.length; i++) {
const char = str.charCodeAt(i)
hash = ((hash << 5) - hash) + char
hash = hash & hash
}
return Math.abs(hash)
}
// Get a value from hash at specific position
function getHashValue(hash: number, position: number, max: number): number {
return ((hash >> (position * 4)) & 0xF) % max
}
// Color palettes - Web3/Crypto aesthetic
const BACKGROUNDS = [
'#1a1a2e', '#16213e', '#0f3460', '#1b1b2f', '#162447',
'#1f1f3d', '#2d132c', '#1e1e3f', '#0d1b2a', '#1b263b',
'#252538', '#2a2a4a', '#1e2a3a', '#0f172a', '#1a1f35',
]
const SKIN_TONES = [
'#ffd5c8', '#f5c5b5', '#daa06d', '#c68642', '#8d5524',
'#6b4423', '#4a3728', '#ffdbac', '#f1c27d', '#e0ac69',
]
const HAIR_COLORS = [
'#090806', '#2c222b', '#3b3024', '#4a4035', '#504444',
'#6a4e42', '#a55728', '#b55239', '#8d4a43', '#91553d',
'#e6cea8', '#e5c8a8', '#debc99', '#977961', '#343434',
'#9a3300', '#ff6b6b', '#4ecdc4', '#ffe66d', '#a855f7',
]
const ACCESSORY_COLORS = [
'#F0B90B', '#0ECB81', '#F6465D', '#60a5fa', '#a855f7',
'#ec4899', '#14b8a6', '#f97316', '#84cc16', '#06b6d4',
]
export function PunkAvatar({ seed, size = 40, className = '' }: PunkAvatarProps) {
const avatar = useMemo(() => {
const hash = hashCode(seed)
// Deterministic selections based on hash
const bgColor = BACKGROUNDS[getHashValue(hash, 0, BACKGROUNDS.length)]
const skinColor = SKIN_TONES[getHashValue(hash, 1, SKIN_TONES.length)]
const hairColor = HAIR_COLORS[getHashValue(hash, 2, HAIR_COLORS.length)]
const accColor = ACCESSORY_COLORS[getHashValue(hash, 3, ACCESSORY_COLORS.length)]
const hairStyle = getHashValue(hash, 4, 8)
const eyeStyle = getHashValue(hash, 5, 6)
const mouthStyle = getHashValue(hash, 6, 5)
const hasGlasses = getHashValue(hash, 7, 4) === 0
const hasEarring = getHashValue(hash, 8, 5) === 0
const hasMask = getHashValue(hash, 9, 8) === 0
const hasLaser = getHashValue(hash, 10, 12) === 0
return {
bgColor,
skinColor,
hairColor,
accColor,
hairStyle,
eyeStyle,
mouthStyle,
hasGlasses,
hasEarring,
hasMask,
hasLaser,
}
}, [seed])
// Pixel size for 24x24 grid
const px = size / 24
const renderHair = () => {
const { hairColor, hairStyle } = avatar
switch (hairStyle) {
case 0: // Mohawk
return (
<>
>
)
case 1: // Messy
return (
<>
>
)
case 2: // Cap
return (
<>
>
)
case 3: // Long
return (
<>
>
)
case 4: // Bald with shine
return (
)
case 5: // Spiky
return (
<>
>
)
case 6: // Hoodie
return (
<>
>
)
case 7: // Crown
return (
<>
>
)
default:
return null
}
}
const renderEyes = () => {
const { eyeStyle, accColor } = avatar
const eyeY = 10 * px
switch (eyeStyle) {
case 0: // Normal
return (
<>
>
)
case 1: // Angry
return (
<>
>
)
case 2: // Wink
return (
<>
>
)
case 3: // Sleepy
return (
<>
>
)
case 4: // Big eyes
return (
<>
>
)
case 5: // Robot
return (
<>
>
)
default:
return null
}
}
const renderMouth = () => {
const { mouthStyle } = avatar
const mouthY = 14 * px
switch (mouthStyle) {
case 0: // Smile
return (
<>
>
)
case 1: // Neutral
return
case 2: // Smirk
return (
<>
>
)
case 3: // Open
return (
<>
>
)
case 4: // Teeth
return (
<>
>
)
default:
return null
}
}
const renderAccessories = () => {
const { hasGlasses, hasEarring, hasMask, hasLaser, accColor } = avatar
const elements = []
if (hasGlasses) {
elements.push(
)
}
if (hasEarring) {
elements.push(
)
}
if (hasMask) {
elements.push(
)
}
if (hasLaser) {
elements.push(
)
}
return elements
}
return (
)
}
// Pre-defined punk collection for special traders
export function getTraderAvatar(traderId: string, traderName: string): string {
// Use a combination of ID and name for more unique results
return `${traderId}-${traderName}`
}