1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
|
from collections import OrderedDict
import re
from . import DealFormat
from .. import dto
class LINFormat(DealFormat):
_qx_format = re.compile(r'^[oc](\d+)$')
_ah_format = re.compile(r'^[A-Za-z ]* (\d+)$')
_md_hand_format = re.compile(r'^S(.*)H(.*)D(.*)C(.*)$')
_suit_cards = 'AKQJT98765432'
@property
def suffix(self):
return '.lin'
def parse_content(self, content):
deals = OrderedDict()
event = ''
lines = [line.strip() for line in content.readlines()]
for line in lines:
chunks = line.split('|')
fields = {}
while len(chunks) > 1:
field_name = chunks.pop(0)
field_value = chunks.pop(0)
if field_name not in fields:
fields[field_name] = []
fields[field_name].append(field_value)
if 'vg' in fields:
event = fields['vg'][0].split(',')[0]
if 'md' in fields:
deal_number = None
for field in ['qx', 'ah']:
if field in fields:
match = getattr(
self, '_%s_format' % (field)).match(
fields[field][0])
if match:
deal_number = int(match.group(1))
break
if deal_number is not None:
layout = self._parse_md_field(fields['md'][0])
if layout:
if deal_number in deals:
if deals[deal_number] != layout:
raise RuntimeError('multiple boards #%d with different layouts' % (deal_number))
deals[deal_number] = layout
else:
print('layout not parsed: ' + fields['md'][0])
dealset = []
for number, layout in deals.items():
deal = dto.Deal()
deal.event = event
deal.number = number
deal.hands = layout
deal.dealer = deal.get_dealer(deal.number)
deal.vulnerable = deal.get_vulnerability(deal.number)
dealset.append(deal)
return dealset
def _parse_md_field(self, value):
try:
hands = value[1:].split(',')
layout = [[], [], [], []]
for i, hand in enumerate(hands):
layout[(i+2)%4] = self._parse_md_hand(hand) # hands always start from S
for j, single_hand in enumerate(layout):
if not sum([len(suit) for suit in single_hand]): # fill 4th hand if necessary
for k, suit in enumerate(single_hand):
layout[j][k] = ''.join([
c for c in self._suit_cards
if c not in ''.join([layout[h][k] for h in range(0, 4) if h != j])
])
for j, single_hand in enumerate(layout):
for k, suit in enumerate(single_hand):
layout[j][k] = list(suit)
return layout
except:
return None
def _parse_md_hand(self, hand):
match = self._md_hand_format.match(hand)
if match:
return [''.join(sorted(
list(match.group(i)),
key=lambda c: self._suit_cards.index(c)))
for i in range(1, 5)]
return ['', '', '', '']
def output_content(self, out_file, dealset):
event_name = ([deal.event for deal in dealset if deal.event] or [''])[0]
first_deal = min([deal.number for deal in dealset])
last_deal = max([deal.number for deal in dealset])
lines = [
'vg|%s,SEGMENT 1,I,%d,%d,HOME,0,AWAY,0|' % (event_name, first_deal, last_deal),
'rs|,,,,,,,,,,,|',
'pn|,,,,,,,|pg||'
]
for deal in dealset:
dealer = (deal.dealer + 3) % 4 or 4
layout = ''
for i in range(0, 4):
for s, suit in enumerate(deal.hands[(i+2) % 4]):
layout += 'SHDC'[s]
layout += ''.join(suit)
if i < 3:
layout += ','
vulnerability = ('b' if deal.vulnerable['EW'] else 'n') \
if deal.vulnerable['NS'] \
else ('e' if deal.vulnerable['EW'] else '0')
for room in ['o', 'c']:
lines.append(
'qx|%s%d|pn|,,,,,,,|md|%d%s|sv|%s|pg||' % (
room, deal.number,
dealer, layout,
vulnerability
)
)
for line in lines:
out_file.write(line + '\r\n')
|