1+ import logging
12import re
23from collections import namedtuple
34
45from layout import Rectangle
56
7+
8+ def even (x ):
9+ return round (x / 2. )* 2
10+
11+
612def is_valid_seat (seat ):
713 return all (key in seat for key in ("row" , "seat" , "x1" , "x2" , "y1" , "y2" ))
814
@@ -20,10 +26,14 @@ def normalize_table_name(table):
2026def add_coordinates (seatmap , cursor ):
2127 halls = {}
2228 tables = {}
29+ # Currently we don't use the "hall" property of the seatmap but calculate
30+ # our own grouping based on the initial non-numeric characters in the table
31+ # name. That way we work around the human naming of halls.
2332 for seat in seatmap :
2433 if not is_valid_seat (seat ):
2534 continue
2635 table = normalize_table_name (seat ['row' ])
36+ logging .debug ("Normalized table name %s to %s" , seat ['row' ], table )
2737 hall = get_hall_from_table_name (table )
2838 halls .setdefault (hall , []).append (seat )
2939 tables .setdefault (hall , {}).setdefault (table , []).append (seat )
@@ -35,23 +45,46 @@ def add_coordinates(seatmap, cursor):
3545 x_min = float ("inf" )
3646 y_max = 0
3747 y_min = float ("inf" )
48+ scales = []
3849 for table in sorted (tables [hall ].keys (), key = lambda x : (len (x ), x )):
3950 # Ignore tables without switches
4051 if not switches .get (table , []):
52+ logging .debug ("Table %s has no switches, ignoring" , table )
4153 continue
42- c = table_location (table , tables )
54+ c , scale = table_location (table , tables )
55+ scales .append (scale )
4356 table_coordinates .append ((table , c ))
44- x_min = c .x1 if c .x1 < x_min else x_min
45- x_min = c .x2 if c .x2 < x_min else x_min
46- y_max = c .y1 if c .y1 > y_max else y_max
47- y_max = c .y2 if c .y2 > y_max else y_max
48- y_min = c .y1 if c .y1 < y_min else y_min
49- y_min = c .y2 if c .y2 < y_min else y_min
57+
58+ # Select a scale (median)
59+ scale = sorted (scales )[len (scales )/ 2 ] if scales else 1.0
60+ logging .debug ("Selected median scale %f" , scale )
61+
62+ # Calculate common offsets
63+ scaled_table_coordinates = []
64+ for table , c in table_coordinates :
65+ s = Rectangle (
66+ even (c .x1 * scale ),
67+ even (c .x2 * scale ),
68+ even (c .y1 * scale ),
69+ even (c .y2 * scale ),
70+ even (c .x_start * scale ),
71+ even (c .y_start * scale ),
72+ even (c .width * scale ),
73+ even (c .height * scale ),
74+ c .horizontal )
75+ x_min = s .x1 if s .x1 < x_min else x_min
76+ x_min = s .x2 if s .x2 < x_min else x_min
77+ y_max = s .y1 if s .y1 > y_max else y_max
78+ y_max = s .y2 if s .y2 > y_max else y_max
79+ y_min = s .y1 if s .y1 < y_min else y_min
80+ y_min = s .y2 if s .y2 < y_min else y_min
81+ scaled_table_coordinates .append ((table , s ))
5082
5183 x_offset = x_min
5284 y_offset = y_min
85+ logging .debug ("Hall %s has offset [%f, %f]" , hall , x_offset , y_offset )
5386
54- for table , t in table_coordinates :
87+ for table , t in scaled_table_coordinates :
5588 coordinates = c = Rectangle (
5689 t .x1 - x_offset , t .x2 - x_offset , t .y1 - y_offset ,
5790 t .y2 - y_offset , t .x_start -
@@ -81,14 +114,14 @@ def switch_locations(t, n):
81114 padding = 2
82115 if t .horizontal :
83116 for i in range (1 , 2 * n , 2 ):
84- x = t .x1 + (t .width / n ) / 2 * i
85- y = t .y1 - t .height / 2
86- locations .append ((x , y ))
117+ x = t .x_start + (t .width / n ) / 2 * i
118+ y = t .y_start - t .height / 2
119+ locations .append ((even ( x ), even ( y ) ))
87120 else :
88121 for i in range (1 , 2 * n , 2 ):
89- x = t .x1 - t .height / 2
90- y = t .y1 + (t .width / n ) / 2 * i - padding
91- locations .append ((x , y ))
122+ x = t .x_start - t .height / 2
123+ y = t .y_start + (t .width / n ) / 2 * i - padding
124+ locations .append ((even ( x ), even ( y ) ))
92125
93126 locations .reverse ()
94127 return locations
@@ -98,31 +131,34 @@ def table_location(table, tables):
98131 seats = sorted (
99132 tables [get_hall_from_table_name (table )][table ],
100133 key = lambda seat : int (seat ['seat' ]))
101- x1 = int (seats [- 1 ]["x1" ])
102- x2 = int (seats [0 ]["x2" ])
103- y1 = int (seats [- 1 ]["y1" ])
104- y2 = int (seats [0 ]["y2" ])
134+ logging .debug ("First and last seat on %s is %s and %s" ,
135+ table , seats [0 ]["seat" ], seats [- 1 ]["seat" ])
136+
137+ x1 = int (seats [0 ]["x1" ])
138+ x2 = int (seats [- 1 ]["x2" ])
139+ y1 = int (seats [0 ]["y1" ])
140+ y2 = int (seats [- 1 ]["y2" ])
141+
105142 x_len = max (x1 , x2 ) - min (x1 , x2 )
106143 y_len = max (y1 , y2 ) - min (y1 , y2 )
144+
107145 x_start = min (x1 , x2 )
108146 y_start = min (y1 , y2 )
109147 horizontal = 1 if x_len > y_len else 0
110148
111- if horizontal :
112- y1 += 5
113- y2 -= 5
114- y_len = max (y1 , y2 ) - min (y1 , y2 )
149+ # Calculate scaling. A normal table is 33x2 seats, use the classical
150+ # magial measurement of 157x2 and scale to that
151+ length = x_len if horizontal else y_len
152+ seats = len (seats )/ 2 # Assume 2xY seating
153+ scale = 1.0 / ((float (length ) * 33.0 / float (seats ))/ 157.0 )
154+ logging .debug ("Bounding box for table %s is [%d, %d - %d, %d], scale is %f" ,
155+ table , x1 , y1 , x2 , y2 , scale )
115156
116157 width = x_len if horizontal else y_len
117158 height = y_len if horizontal else x_len
118159
119- even = lambda x : round (x / 2. )* 2
120-
121- width = even (width )
122- height = even (height )
123-
124160 return Rectangle (x1 , x2 , y1 , y2 , x_start , y_start , width , height ,
125- horizontal )
161+ horizontal ), scale
126162
127163
128164def switches_by_table (cursor ):
@@ -133,4 +169,6 @@ def switches_by_table(cursor):
133169 table = table [0 ] + table [1 :]
134170 switches [table ] = switches .get (table , [])
135171 switches [table ].append (switch [0 ])
172+ for table in switches .keys ():
173+ logging .debug ("Table %s has %d switches" , table , len (switches [table ]))
136174 return switches
0 commit comments