Skip to content

Commit eb4572a

Browse files
committed
compatibility for new dh seatmap
1 parent 14c89df commit eb4572a

4 files changed

Lines changed: 142 additions & 45 deletions

File tree

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,4 @@
11
*.pyc
22
*.db
3+
.*.swp
4+
.*.swo

convert-dh-seatmap.py

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import json
2+
3+
seatmap = json.load(open('seatmap.json', 'r'))
4+
5+
# Structure is:
6+
# floors: {
7+
# $floor_id: {
8+
# name: "Hall D"
9+
# We call them halls instead though
10+
hall_id_map = {k: v['name'] for k,v in seatmap['floors'].items()}
11+
# Structure is:
12+
# rows: {
13+
# $floor_id: {
14+
# $row_id: {
15+
# name: "B20"
16+
# Row IDs are unique, so we ignore which floor they belong to
17+
row_id_map = {k: v['name'] for x in seatmap['rows'].values() for k, v in x.items()}
18+
# Structure is:
19+
# seat_types: {
20+
# $seat_type_id: {
21+
# width: X
22+
# height: Y
23+
seat_type_map = seatmap['seat_types']
24+
25+
# Structure is:
26+
# seats: {
27+
# $floor_id: {
28+
# $seat_id: {
29+
# name: "20"
30+
# row_id: $row_id
31+
# floor_id: $floor_id
32+
# seat_type_id: $seat_type_id
33+
34+
# Since floor_id is redundant we use the one inside the seat object.
35+
seats = (v for x in seatmap['seats'].values() for v in x.values())
36+
37+
output = []
38+
for seat in seats:
39+
row = row_id_map[seat['row_id']]
40+
hall = hall_id_map[seat['floor_id']]
41+
seat_type = seat_type_map[seat['seat_type_id']]
42+
seat_idx = seat['name']
43+
x1 = seat['x']
44+
y1 = seat['y']
45+
x2 = seat['x'] + seat_type['width']
46+
y2 = seat['y'] + seat_type['height']
47+
output.append({
48+
'x1': x1,
49+
'y1': y1,
50+
'x2': x2,
51+
'y2': y2,
52+
'seat': seat_idx,
53+
'hall': hall,
54+
'row': row,
55+
})
56+
57+
print(json.dumps(output, indent=4))

lib/location.py

Lines changed: 66 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,14 @@
1+
import logging
12
import re
23
from collections import namedtuple
34

45
from layout import Rectangle
56

7+
8+
def even(x):
9+
return round(x/2.)*2
10+
11+
612
def 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):
2026
def 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

128164
def 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

tests/TestSeatmap.py

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -62,12 +62,12 @@ def testAddCoordinates(self):
6262
self.assertEquals(len(tables), 1, "Wrong number of tables in database")
6363
self.assertEquals(tables[0].name, "B19", "Wrong table name")
6464
self.assertEquals(tables[0].hall, "B", "Wrong hall name")
65-
self.assertEquals(tables[0].x1, 0, "Wrong x1 coordinate")
65+
self.assertEquals(tables[0].x2, 0, "Wrong x2 coordinate")
6666
self.assertEquals(tables[0].y1, 8, "Wrong y1 coordinate")
6767
self.assertEquals(tables[0].y2, 0, "Wrong y2 coordinate")
6868
self.assertEquals(tables[0].x_start, 0, "Wrong x_start coordinate")
69-
self.assertEquals(tables[0].y_start, 3, "Wrong y_start coordinate")
70-
self.assertEquals(tables[0].width, 158, "Wrong width")
69+
self.assertEquals(tables[0].y_start, 0, "Wrong y_start coordinate")
70+
self.assertEquals(tables[0].width, 152, "Wrong width")
7171
self.assertEquals(tables[0].height, 8, "Wrong height")
7272
self.assertEquals(tables[0].horizontal, 1, "Wrong horizontal flag")
7373

@@ -82,16 +82,16 @@ def testSwitchLocation(self):
8282
switches[0].name,
8383
"b19-a.event.dreamhack.local",
8484
"Wrong switch name")
85-
self.assertEquals(switches[0].x, 118.5, "Wrong x coordinate")
86-
self.assertEquals(switches[0].y, 4, "Wrong y coordinate")
85+
self.assertEquals(switches[0].x, 114, "Wrong x coordinate")
86+
self.assertEquals(switches[0].y, -4, "Wrong y coordinate")
8787
self.assertEquals(switches[0].table_name, "B19", "Wrong table name")
8888

8989
self.assertEquals(
9090
switches[1].name,
9191
"b19-b.event.dreamhack.local",
9292
"Wrong switch name")
93-
self.assertEquals(switches[1].x, 39.5, "Wrong x coordinate")
94-
self.assertEquals(switches[1].y, 4, "Wrong y coordinate")
93+
self.assertEquals(switches[1].x, 38, "Wrong x coordinate")
94+
self.assertEquals(switches[1].y, -4, "Wrong y coordinate")
9595
self.assertEquals(switches[1].table_name, "B19", "Wrong table name")
9696

9797
def testSwitchLocationWithMixedLayout(self):
@@ -105,40 +105,40 @@ def testSwitchLocationWithMixedLayout(self):
105105
switches[0].name,
106106
"c19-a.event.dreamhack.local",
107107
"Wrong switch name")
108-
self.assertEquals(switches[0].x, 4, "Wrong x coordinate")
109-
self.assertEquals(switches[0].y, 129.66666666666666, "Wrong y coordinate")
108+
self.assertEquals(switches[0].x, -2, "Wrong x coordinate")
109+
self.assertEquals(switches[0].y, 130, "Wrong y coordinate")
110110
self.assertEquals(switches[0].table_name, "C19", "Wrong table name")
111111

112112
self.assertEquals(
113113
switches[1].name,
114114
"c19-b.event.dreamhack.local",
115115
"Wrong switch name")
116-
self.assertEquals(switches[1].x, 4, "Wrong x coordinate")
117-
self.assertEquals(switches[1].y, 77, "Wrong y coordinate")
116+
self.assertEquals(switches[1].x, -2, "Wrong x coordinate")
117+
self.assertEquals(switches[1].y, 78, "Wrong y coordinate")
118118
self.assertEquals(switches[1].table_name, "C19", "Wrong table name")
119119

120120
self.assertEquals(
121121
switches[2].name,
122122
"c19-c.event.dreamhack.local",
123123
"Wrong switch name")
124-
self.assertEquals(switches[2].x, 4, "Wrong x coordinate")
125-
self.assertEquals(switches[2].y, 24.333333333333332, "Wrong y coordinate")
124+
self.assertEquals(switches[2].x, -2, "Wrong x coordinate")
125+
self.assertEquals(switches[2].y, 24, "Wrong y coordinate")
126126
self.assertEquals(switches[2].table_name, "C19", "Wrong table name")
127127

128128
self.assertEquals(
129129
switches[3].name,
130130
"b19-a.event.dreamhack.local",
131131
"Wrong switch name")
132-
self.assertEquals(switches[3].x, 118.5, "Wrong x coordinate")
133-
self.assertEquals(switches[3].y, 4, "Wrong y coordinate")
132+
self.assertEquals(switches[3].x, 118, "Wrong x coordinate")
133+
self.assertEquals(switches[3].y, -4, "Wrong y coordinate")
134134
self.assertEquals(switches[3].table_name, "B19", "Wrong table name")
135135

136136
self.assertEquals(
137137
switches[4].name,
138138
"b19-b.event.dreamhack.local",
139139
"Wrong switch name")
140-
self.assertEquals(switches[4].x, 39.5, "Wrong x coordinate")
141-
self.assertEquals(switches[4].y, 4, "Wrong y coordinate")
140+
self.assertEquals(switches[4].x, 40, "Wrong x coordinate")
141+
self.assertEquals(switches[4].y, -4, "Wrong y coordinate")
142142
self.assertEquals(switches[4].table_name, "B19", "Wrong table name")
143143

144144

0 commit comments

Comments
 (0)