3 from math
import sin
, pi
6 from sqlalchemy
import Column
, ForeignKey
7 from sqlalchemy
.orm
import relation
8 from sqlalchemy
.types
import Integer
, Unicode
10 from spline
.model
.meta
import TableBase
12 class AnonymousUser(object):
13 """Fake user object, for when the user isn't actually logged in.
15 Tests as false and tries to respond to method calls the expected way.
18 def __nonzero__(self
):
23 def can(self
, action
):
24 # XXX if viewing is ever a permission, this should probably change.
28 class User(TableBase
):
29 __tablename__
= 'users'
30 id = Column(Integer
, primary_key
=True)
31 name
= Column(Unicode(length
=20), nullable
=False)
32 unique_identifier
= Column(Unicode(length
=32), nullable
=False)
34 def __init__(self
, *args
, **kwargs
):
35 # Generate a unique hash if one isn't provided (which it shouldn't be)
36 if 'unique_identifier' not in kwargs
:
37 ident
= u
''.join(random
.choice(u
'0123456789abcdef')
39 kwargs
['unique_identifier'] = ident
41 super(User
, self
).__init__(*args
, **kwargs
)
43 def can(self
, action
):
44 # XXX this is probably not desired.
48 def unique_colors(self
):
49 """Returns a list of (width, '#rrggbb') tuples that semi-uniquely
52 width_blob
, colors_blob
= self
.unique_identifier
[0:8], \
53 self
.unique_identifier
[8:32]
57 width_hex
= width_blob
[i
*2:i
*2+2]
58 widths
.append(int(width_hex
, 16))
59 total_width
= sum(widths
)
64 raw_hue
= int(colors_blob
[i
*6:i
*6+2], 16) / 256.0
66 # Make adjacent hues relatively close together, to avoid green
67 # + purple sorts of clashes.
68 # Minimum distance is 0.1; maximum is 0.35. Leaves half the
69 # spectrum available for any given color.
70 # Change 0.0–0.1 to -0.35–-0.1, 0.1–0.35
71 hue_offset
= raw_hue
* 0.5 - 0.25
77 h
= last_hue
+ raw_hue
82 l
= int(colors_blob
[i
*6+2:i
*6+4], 16) / 256.0
83 s
= int(colors_blob
[i
*6+4:i
*6+6], 16) / 256.0
85 # Secondary colors are extremely biased against when picking
86 # randomly from the hue spectrum.
87 # To alleviate this, try to bias hue towards secondary colors.
88 # This adjustment is based purely on experimentation; sin() works
89 # well because hue is periodic, * 6 means each period is 1/3 the
90 # hue spectrum, and the final / 24 is eyeballed
91 h
+= sin(h
* pi
* 6) / 24
93 # Cap lightness to 0.4 to 0.95, so it's not too close to white or
97 # Cap saturation to 0.5 to 1.0, so the color isn't too gray
100 r
, g
, b
= colorsys
.hls_to_rgb(h
, l
, s
)
101 color
= "#{0:02x}{1:02x}{2:02x}".format(
107 ret
.append((1.0 * widths
[i
] / total_width
, color
))
112 class OpenID(TableBase
):
113 __tablename__
= 'openid'
114 openid
= Column(Unicode(length
=255), primary_key
=True)
115 user_id
= Column(Integer
, ForeignKey('users.id'))
116 user
= relation(User
, lazy
=False, backref
='openids')