Skip to content
quarry Artifact [438f8cad88]
Login

Artifact [438f8cad88]

Artifact 438f8cad889d5e69d7fce22b2d3330f5fa9df21b24712d3564028ae06aced98b:


// Package idn is quarry's identity mark: one hue and one small grid per
// person, derived from the name alone.
//
// It lives on its own because THREE packages need the same answer and a
// person must look the same in all of them. web draws the mark beside a
// byline, api hands it to the markup resolver so an @mention carries it,
// and both hash the name to the same hue. When userHue was written twice —
// once in web, once in api — nothing checked that the two agreed; they did,
// by luck, and a one-character edit in either would have given the same
// person two colours on the same page.
package idn

import (
	"fmt"
	"hash/fnv"
	"strings"
	"sync"
)

// Hue is the person's colour, 0-359. One hue per person keeps the mark
// recognisable at a glance: the colour IS the identity as much as the
// pattern is.
func Hue(name string) int {
	h := fnv.New64a()
	h.Write([]byte(name))
	return int(h.Sum64() % 360)
}

var memo sync.Map // name -> string

// Mark is the person's identicon as an inline SVG: a 5x3 half-grid
// mirrored into a 5x5 face, in two lightness steps of their hue, on a wash
// of the same hue.
//
// Memoised because a busy page draws the same handful of people dozens of
// times, and the answer never changes.
func Mark(name string) string {
	if v, ok := memo.Load(name); ok {
		return v.(string)
	}
	h := fnv.New64a()
	h.Write([]byte(name))
	v := h.Sum64()
	hue := v % 360
	cells := v >> 9   // 15 bits: which of the 5x3 half-grid cells are on
	shades := v >> 24 // 15 more: which on-cells take the deeper shade
	if cells&0x7FFF == 0 {
		cells = 0x1084 // a degenerate hash still gets a face: centre column
	}
	var b strings.Builder
	fmt.Fprintf(&b, `<svg class="idn" viewBox="-0.6 -0.6 6.2 6.2" aria-hidden="true">`)
	fmt.Fprintf(&b, `<rect x="-0.6" y="-0.6" width="6.2" height="6.2" rx="1" fill="hsl(%d, 45%%, 50%%)" fill-opacity="0.14"/>`, hue)
	deep := fmt.Sprintf("hsl(%d, 62%%, 40%%)", hue)
	lit := fmt.Sprintf("hsl(%d, 60%%, 56%%)", hue)
	cell := func(x, y int, fill string) {
		fmt.Fprintf(&b, `<rect x="%d" y="%d" width="1" height="1" rx="0.22" fill="%s"/>`, x, y, fill)
	}
	for row := 0; row < 5; row++ {
		for col := 0; col < 3; col++ {
			i := uint(row*3 + col)
			if cells>>i&1 == 1 {
				fill := lit
				if shades>>i&1 == 1 {
					fill = deep
				}
				cell(col, row, fill)
				if col < 2 {
					cell(4-col, row, fill)
				}
			}
		}
	}
	b.WriteString(`</svg>`)
	out := b.String()
	memo.Store(name, out)
	return out
}