summaryrefslogtreecommitdiff
path: root/dealconvert/formats/lin.py
blob: 43c5ac32ec528b753f6812c0b8ecc059a18c384a (plain)
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')