fix badly implemented loop, loop less, cache common results; this makes requests by new people >10x faster when there are a lot of existing people
このコミットが含まれているのは:
コミット
072d816aac
|
@ -1,12 +1,25 @@
|
|||
import hashlib
|
||||
from website.constants import BACKGROUND_COLOUR
|
||||
from functools import lru_cache
|
||||
|
||||
# functions for calculating constrast between two colours
|
||||
# https://www2.cs.sfu.ca/CourseCentral/820/li/material/RGB-YUV.pdf
|
||||
# https://www.accessibility-developer-guide.com/knowledge/colours-and-contrast/how-to-calculate/
|
||||
|
||||
def _contrast_numerator(c1):
|
||||
l1 = (0.299 * c1[0] + 0.587 * c1[1] + 0.114 * c1[2]) / 256
|
||||
return l1 + 0.05
|
||||
|
||||
# this is being cached because it is always called with the colours of existing
|
||||
# users, and we don't need to do the same float division thousands of times
|
||||
# just for gen_colour to return a single colour
|
||||
@lru_cache(maxsize=256)
|
||||
def _contrast_denominator(c2):
|
||||
l2 = (0.299 * c2[0] + 0.587 * c2[1] + 0.114 * c2[2]) / 256
|
||||
return 1 / (l2 + 0.05)
|
||||
|
||||
def _contrast(c1, c2):
|
||||
# https://www2.cs.sfu.ca/CourseCentral/820/li/material/RGB-YUV.pdf
|
||||
l1 = (0.299 * c1[0] + 0.587 * c1[1] + 0.114 * c1[2]) / 256
|
||||
l2 = (0.299 * c2[0] + 0.587 * c2[1] + 0.114 * c2[2]) / 256
|
||||
# https://www.accessibility-developer-guide.com/knowledge/colours-and-contrast/how-to-calculate/
|
||||
return (l1 + 0.05) / (l2 + 0.05)
|
||||
return _contrast_numerator(c1) * _contrast_denominator(c2)
|
||||
|
||||
def _distance_sq(c1, c2):
|
||||
return sum((i / 256 - j / 256) ** 2 for i, j in zip(c1, c2))
|
||||
|
@ -15,12 +28,13 @@ def _gen_colour(seed, background=BACKGROUND_COLOUR):
|
|||
'''
|
||||
Returns a colour with sufficient contrast to the background colour
|
||||
'''
|
||||
while True:
|
||||
for _ in range(16): # this loop exits on the first iteration 99.99% of the time (literally)
|
||||
seed = hashlib.sha256(seed).digest()
|
||||
for i in range(0, len(seed) - len(seed) % 3, 3):
|
||||
colour = seed[i:i+3]
|
||||
if 1.5 < _contrast(colour, background) < 3:
|
||||
return colour
|
||||
break
|
||||
return colour, seed
|
||||
|
||||
def gen_colour(seed, background=BACKGROUND_COLOUR, *avoid):
|
||||
'''
|
||||
|
@ -29,22 +43,20 @@ def gen_colour(seed, background=BACKGROUND_COLOUR, *avoid):
|
|||
This function hasn't been analysed for efficiency or anything
|
||||
'''
|
||||
best_colour, best_score = None, None
|
||||
for _ in range(16384):
|
||||
colour = _gen_colour(seed, background)
|
||||
score = float('inf') if len(avoid) == 0 else sum(_contrast(colour, c) for c in avoid) / len(avoid)
|
||||
if colour in avoid:
|
||||
for _ in range(1024):
|
||||
colour, seed = _gen_colour(seed, background)
|
||||
if len(avoid) == 0:
|
||||
score = float('inf')
|
||||
elif colour in avoid:
|
||||
score = float('-inf')
|
||||
else:
|
||||
score = sum(_contrast(colour, c) for c in avoid) / len(avoid)
|
||||
if 2.5 < score:
|
||||
return colour
|
||||
if best_score == None or score > best_score:
|
||||
best_colour = colour
|
||||
best_colour, best_score = colour, score
|
||||
return best_colour
|
||||
|
||||
# old-style tag generation: similar colours make similar tags
|
||||
#def tag(colour):
|
||||
# tag = ((colour[2] & 0xf0) >> 4) | (colour[1] & 0xf0) | ((colour[0] & 0xf0) << 4)
|
||||
# return f'#{tag:03x}'
|
||||
|
||||
def tag(token, length=3):
|
||||
'''
|
||||
Generates a deterministic pseudorandom tag from a given token
|
||||
|
|
読み込み中…
新しいイシューから参照