-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsolution.py
150 lines (117 loc) · 4.58 KB
/
solution.py
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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from pprint import pprint
import time
from collections import defaultdict
class App:
def __init__(self):
self.game_url = "https://setwithfriends.com/"
self.opts = webdriver.FirefoxOptions()
self.opts.add_argument("--incognito")
self.driver = webdriver.Firefox(options=self.opts)
def run(self):
self.driver.get(self.game_url)
selectText = """1. Press (P/p)lay to play\n2. Press (Q/q)uit to quit\n>> """
while True:
inp = input(selectText)
if inp.isalpha():
if inp.lower() == 'q':
break
elif inp.lower() == 'p':
for _ in range(20):
self.play()
time.sleep(0.5)
self.driver.quit()
def get_active_cards(self):
root = self.driver.find_element_by_id("root")
cont = root.find_element_by_class_name("MuiContainer-root")
g1 = cont.find_elements_by_css_selector('div[class*="MuiPaper-root MuiPaper-elevation1 MuiPaper-rounded"]')[1]
g2 = g1.find_elements_by_css_selector('div')
self.activeCardConts = []
for div in g2:
if 'visible' in div.get_attribute('style'):
cardCont = div.find_element_by_css_selector('div')
self.activeCardConts.append(cardCont)
cc = self.activeCardConts
def find_a_set(self, cards):
# (shape, color, shading, number)
for card1 in cards:
for card2 in cards:
for card3 in cards:
if card1 != card2 and card2 != card3 and card3 != card1:
shapes, colors, shadings, numbers = map(lambda _: defaultdict(int), range(4))
for card in [card1, card2, card3]:
shape, color, shading, number = card
shapes[shape] += 1
colors[color] += 1
shadings[shading] += 1
numbers[number] += 1
if self.isSet(shapes, colors, shadings, numbers):
return (card1, card2, card3)
def isSet(self, shapes, colors, shadings, numbers):
# counts of those metric for 3 choosen cards
for metric in [shapes, colors, shadings, numbers]:
# Not a set if we find at least one metric categorized as 2 of and 1 of
if 2 in metric.values():
return False
return True
def play(self):
# Sets the activeCardConts
self.get_active_cards()
get_card_cont = {}
cards = []
for activeCardCont in self.activeCardConts:
card = self.extract_card_info(activeCardCont)
get_card_cont[card] = activeCardCont
cards.append(card)
for card in (m:=self.find_a_set(cards)):
card_element = get_card_cont[card]
card_element.click()
def extract_card_info(self, cardCont):
# cardCont: instance of FirefoxWebElement class
colorMap = {
'#800080': 'violet',
'#ff47ff': 'violet',
'#ff0101': 'red',
'#ffb047': 'red',
'#008002': 'green',
'#00b803': 'green'
}
"""
div # The card div itself
- [svg]
- [use]
use1: {
# Shade
href: #shapeName
fill: #... // Striped/Shaded
mask: ... // Non-empty -> Shaded
// No stroke
}
use2: {
# Border
href: ...
stroke: #...
}
"""
svgs = cardCont.find_elements_by_css_selector('svg')
# Check only one because the every one of them are identical
svg = svgs[0]
uses = svg.find_elements_by_css_selector('use')
# Shading
use1 = uses[0]
href, fill, mask = map(lambda attr: use1.get_attribute(attr), ['href', 'fill', 'mask'])
# Color
use2 = uses[1]
stroke = use2.get_attribute('stroke')
shape = href.strip("#")
color = colorMap[stroke]
shading = 'open' if fill == 'transparent' else ('solid' if mask == "" else 'shaded')
number = len(svgs)
#print(shape, color, shading, number)
return (shape, color, shading, number)
def main():
app = App()
app.run()
if __name__ == "__main__":
main()