from dataclasses import dataclass RESET='\033[0m' COLORS={'r':'\033[31m','y':'\033[33m','g':'\033[32m','b':'\033[34m'} COLOR_ORDER={'r':0,'y':1,'g':2,'b':3} @dataclass(frozen=True) class Card: color: str|None value: int|None joker: bool=False uid: int=0 def text(self): if self.joker: return f'{COLORS["r"]}J{RESET}' return f'{COLORS[self.color]}{self.value}{RESET}' def plain(self): return 'J' if self.joker else f'{self.color}{self.value}' def deck(): cards=[] uid=0 for _ in range(2): for c in COLORS: for n in range(1,14): cards.append(Card(c,n,False,uid)); uid+=1 for _ in range(2): cards.append(Card(None,None,True,uid)); uid+=1 return cards def points(card): return 30 if card.joker else card.value def valid_group(cards): if not 3 <= len(cards) <= 4: return False normal=[c for c in cards if not c.joker] jok=len(cards)-len(normal) if not normal: return False return len({c.value for c in normal})==1 and len({c.color for c in normal})==len(normal) and len(normal)+jok>=3 def valid_run(cards, wrap=False): if not 3 <= len(cards) <= 13: return False normal=sorted((c for c in cards if not c.joker), key=lambda x:x.value) jok=len(cards)-len(normal) if not normal or len({c.color for c in normal}) != 1: return False if len({c.value for c in normal}) != len(normal): return False if not wrap: gaps=sum(b.value-a.value-1 for a,b in zip(normal,normal[1:])) return gaps <= jok and normal[-1].value-normal[0].value+1+jok <= 13 # 13-1-Umlauf: Werte liegen auf einem Kreis 1..13, die Folge ist ein # zusammenhängender Bogen. Alle Lücken außer der größten müssen durch # Joker gefüllt werden. gaps=[b.value-a.value-1 for a,b in zip(normal,normal[1:])] gaps.append(normal[0].value+13-normal[-1].value-1) return 13-len(normal)-jok <= max(gaps) def valid(cards, wrap=False): return valid_group(cards) or valid_run(cards, wrap) def kind(cards, wrap=False): if valid_run(cards, wrap): return 'Folge' if valid_group(cards): return 'Satz' return 'UNGÜLTIG' def sort_hand(cards): return sorted(cards,key=lambda c:(c.joker, COLOR_ORDER.get(c.color,99), c.value or 99))