def cs_filter(data_frame: pd.DataFrame) -> pd.DataFrame: """Filter out all commits that are not in the case study if one was selected.""" if case_study is None or data_frame.empty: return data_frame # use a trie for fast prefix lookup revisions = CharTrie() for revision in case_study.revisions: revisions[revision.hash] = True return data_frame[data_frame["revision"].apply( lambda x: revisions.has_node(x.hash) != 0)]
class Solver: def __init__(self, cells, dictionary=None): self.cells = [ Cell( c['letter'], c.get('points', 1), c.get('P', 1), c.get('S', 1), ) for c in cells ] self.letters = [c['letter'] for c in cells] self.candidates = {} # word => (positions, value) self.dictionary = dictionary if not dictionary: self.dictionary = CharTrie() print('Loading custom words ... ', end="") with open('SK-custom.txt') as f: self.dictionary.update( (w, True) for w in f.read().splitlines()) print(len(self.dictionary)) def word_value(self, visited): val = 0 S = 1 for pos in visited: cell = self.cells[pos] val += cell.points * cell.P S *= cell.S return val * S def next_char(self, visited, pos): visited = visited + (pos, ) word = ''.join((self.letters[p] for p in visited)) has = self.dictionary.has_node(word) if has & CharTrie.HAS_VALUE: newval = self.word_value(visited) if self.candidates.get(word, (None, 0))[1] < newval: self.candidates[word] = (visited, newval) # print(word) # Don't continue if thera are no words with this prefix if not has & CharTrie.HAS_SUBTRIE: return row = pos // 4 col = pos % 4 prev_row = row - 1 next_row = row + 1 prev_col = col - 1 next_col = col + 1 if next_row < 4: # Adds the charcter S the current pos pos = next_row * 4 + col if pos not in visited: self.next_char(visited, pos) #Adds the character SE the current pos pos = next_row * 4 + next_col if next_col < 4 and pos not in visited: self.next_char(visited, pos) if next_col < 4: # Adds the charcter E of the current pos pos = row * 4 + next_col if pos not in visited: self.next_char(visited, pos) #Adds the character NE the current pos pos = prev_row * 4 + next_col if prev_row >= 0 and pos not in visited: self.next_char(visited, pos) if prev_row >= 0: # Adds the charcter N the current pos pos = prev_row * 4 + col if pos not in visited: self.next_char(visited, pos) # Adds the charcter NW of the current pos pos = prev_row * 4 + prev_col if prev_col >= 0 and pos not in visited: self.next_char(visited, pos) if prev_col >= 0: # Adds the charcter W of the current pos pos = row * 4 + prev_col if pos not in visited: self.next_char(visited, pos) # Adds the charcter SW of the current pos pos = next_row * 4 + prev_col if next_row < 4 and pos not in visited: self.next_char(visited, pos) def solve_and_swipe(self): for pos in range(0, 16): self.next_char((), pos) # sort by length pyautogui.moveTo(x0, y0, duration=0.1) pyautogui.click(duration=0.1) for word, visited_val in self.candidates.items(): print(word, visited_val[1]) self.swipe(visited_val[0]) def swipe(self, positions): grid = 94 pos = positions[0] pyautogui.moveTo(x0 + (pos % 4) * grid, y0 + (pos // 4) * grid, duration=0.1) pyautogui.mouseDown(button='left', logScreenshot=False, _pause=False, duration=0.1) for pos in positions[1:]: pyautogui.moveTo(x0 + (pos % 4) * grid, y0 + (pos // 4) * grid, duration=0.1) pyautogui.mouseUp(button='left', logScreenshot=False, _pause=False, duration=0.1)
class Save: def __init__(self, season='recent'): self.athlete_web = nx.DiGraph() self.athletes_by_name = CharTrie() self.athletes_by_id = {} self.athletes_by_index = [] self.race_history = set() self.athletes_considered = set() self.rankings = [] self.search_queue = [] self.season = season @classmethod def load(self, filename='my_save.bin'): with open(filename, 'rb') as file: s = pickle.load(file) return s def save(self, filename='my_save.bin'): with open(filename, 'wb') as file: pickle.dump(self, file) def update_athlete(self, athlete): if athlete.id in self: self[athlete.id].merge(athlete) else: self.athletes_by_id[athlete.id] = athlete self.athletes_by_name[athlete.name] = athlete self.athletes_by_index.append(athlete.id) self.athlete_web.add_node(athlete.id) def consider_athlete(self, a_ID): self.athletes_considered.add(a_ID) def add_race(self, race): self.race_history.add(race) def get_prefix_matches(self, name, count): if self.athletes_by_name.has_node(name): return tuple(map(lambda athlete: athlete.name + ': ' + str(athlete.id), \ self.athletes_by_name.values(prefix=name)[:count])) else: return () def get_ranking(self, id): return self.rankings.index(id) + 1 def update_graph(self): for race in self.race_history: surpassers = [] for runner_id in map(lambda x: x[0], race.results): for surpasser_id in surpassers: self[runner_id].lose() if self.athlete_web.has_edge(surpasser_id, runner_id): self.athlete_web[surpasser_id][runner_id]['count'] += 1 else: self.athlete_web.add_edge(surpasser_id, runner_id, count=1) surpassers.append(runner_id) for persons_defeated in map(lambda item: item[1], self.athlete_web.adj.items()): for person_defeated, connection in persons_defeated.items(): connection['weight'] = connection['count'] / self[ person_defeated].losses #takes athletes as starting points and dives into athletic.net. def import_data(self, num_races_to_add, athlete_id=None, progress_frame=None, backup_csv=None, \ focus_local=False, season='recent'): if athlete_id: self.search_queue.append(athlete_id) race_scraper.search_for_races(self, num_races_to_add, \ progress_frame=progress_frame, focus_local=focus_local, season=season) self.update_graph() self.update_rankings() if backup_csv: with open(backup_csv, 'r') as file: reader = csv.reader(file) athletes = set(map(tuple, reader)) with open(backup_csv, 'a') as file: writer = csv.writer(file, delimiter=',') for athlete in self.athletes_by_id.values(): if (athlete.name, str(athlete.id)) not in athletes: writer.writerow([athlete.name, athlete.id]) def update_rankings(self, precision=100): system = nx.to_numpy_array(self.athlete_web) rankings_by_index = self.get_rankings(system, precision=precision) score_pairs = [(self.athlete_at_index(pair[0]), pair[1]) for pair in enumerate(rankings_by_index)] score_pairs.sort(key=lambda x: -1 * x[1]) self.rankings = list(map(lambda x: x[0], score_pairs)) #We also assign an index elf.get_rankings(system)l athletes so we can reclaim them from a vector/matrix. def athlete_at_index(self, index): return self.athletes_by_index[index] def get_rankings(self, matrix, precision=100): current_scores = np.full(len(matrix), 1) for _ in range(precision): current_scores = np.matmul(matrix, current_scores) return current_scores #can subscript Save object using either athlete or athlete id for the same result. def __getitem__(self, request): if type(request) == int: return self.athletes_by_id[request] return self.athletes_by_name[request] def __contains__(self, request): if type(request) == int: return request in self.athletes_by_id return request in self.athletes_by_name def __len__(self): return len(self.athletes_by_index) def __repr__(self): return 'Save object containing ' + str(len(self)) + ' athletes.' def __str__(self): return ''.join([str(a[0] + 1) + '. ' + str(self.athletes_by_id[a[1]]) + '\n' for \ a in enumerate(self.rankings)])