diff options
author | emkael <emkael@tlen.pl> | 2020-02-18 17:08:58 +0100 |
---|---|---|
committer | emkael <emkael@tlen.pl> | 2020-02-18 17:08:58 +0100 |
commit | 4ca15ee0719bddd9311ca5941fe20375ae29d888 (patch) | |
tree | d0b04f15f1362208146ab053982a40443526f077 | |
parent | eb3e6c4116e9343e55594667200bb39e3a8ddd13 (diff) |
LIN format support
-rw-r--r-- | dealconvert/formats/lin.py | 123 |
1 files changed, 123 insertions, 0 deletions
diff --git a/dealconvert/formats/lin.py b/dealconvert/formats/lin.py new file mode 100644 index 0000000..0c740c1 --- /dev/null +++ b/dealconvert/formats/lin.py @@ -0,0 +1,123 @@ +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: + print 'error, duplicate board number with differing layout' + deals[deal_number] = layout + else: + print 'layout not parsed: ' + fields['md'][0] + dealset = [] + for number, layout in deals.iteritems(): + 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: + first_hand = int(value[0])-1 # 0 = S, 1 = W, 2 = N, 3 = E + hands = value[1:].split(',') + layout = [[], [], [], []] + for i, hand in enumerate(hands): + layout[(first_hand+i+2)%4] = self._parse_md_hand(hand) # N <-> S, E <-> W + 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+dealer-3) % 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') |