def run(file_path): dis = Dissector() parser = Parser() extrator = Extractor() if os.path.isdir(file_path): dir_files_list = os.listdir(file_path) for files in dir_files_list: sample = Sample(os.path.join(file_path, files)) dis.extract_file(sample) parser.parse(sample) extrator.extract(sample) sample.print_info() else: sample = Sample(file_path) dis.extract_file(sample) parser.parse(sample) extrator.extract(sample) sample.print_info()
def process_sample(file_path): print file_path config = Config() load_sucess = config.load_config() if load_sucess: dis = Dissector() parser = Parser() extrator = Extractor() operator = Operator(config) r_generator = Report_Generator() sample = Sample(file_path) rlt = dis.extract_file(sample, config.get_output_dir()) bin_time_list = list() if rlt: parser.parse(sample) extrator.extract(sample) # config.print_info() operator.operate(sample, config) r_generator.write_report(sample) return sample
def process_sample(file_path): print file_path config=Config() load_sucess=config.load_config() if load_sucess: dis=Dissector() parser=Parser() extrator=Extractor() operator=Operator(config) r_generator=Report_Generator() sample=Sample(file_path) rlt=dis.extract_file(sample,config.get_output_dir()) bin_time_list=list() if rlt: parser.parse(sample) extrator.extract(sample) # config.print_info() operator.operate(sample,config) r_generator.write_report(sample) return sample
def test_GetDueTodayTask(self): extractor = Extractor() result1 = extractor.extract("Apa saja deadline hari ini?", Context.getDueTodayTask) result2 = extractor.extract("Deadline tubes hari ini apa saja, ya?", Context.getDueTodayTask) result3 = extractor.extract("yang deadline pada hari ini", Context.getDueTodayTask) result4 = extractor.extract( "Bot, minta daftar deadline dong pada hari ini. Makasih :)", Context.getDueTodayTask) result5 = extractor.extract( "Untuk tucil, deadline pada hari ini apa saja?", Context.getDueTodayTask) result6 = extractor.extract( "Tubes yang deadline pada hari ini apa saja?", Context.getDueTodayTask) assert result1 != None assert result1.jenisTask == "" assert result2 != None assert result2.jenisTask == "tubes" assert result3 != None assert result3.jenisTask == "" assert result4 != None assert result4.jenisTask == "" assert result5 != None assert result5.jenisTask == "tucil" assert result6 != None assert result6.jenisTask == "tubes"
def hello2(): user_input = request.form["user-input"] print("\"{}\"".format(user_input)) context_identifier = ContextIdentifier() context = context_identifier.getContext(user_input) bot_response = "" suggested_word = [] if context == Context.unknown: print("Unknown?") suggested_word = SpellChecker().getWordSuggestion(user_input) elif context == Context.help: bot_response = "Terdapat beberapa hal yang dapat dilakukan:\n" bot_response += "- Menambah tugas (coba \"Tolong ingatkan kalau ada kuis IF3110 Bab 2 pada 22/04/21\")\n" bot_response += "- Melihat semua tugas (coba \"bot tugas apa saja sejauh ini ya?\")\n" bot_response += "-. Melihat tugas pada periode tertentu (coba \"Apa saja deadline antara 03/04/2021 sampai 15/04/2021\")\n" bot_response += "- Melihat tugas beberapa hari/minggu ke depan (coba \"Ada tugas apa saja 2 hari ke depan\")\n" bot_response += "- Melihat tugas yang deadline-nya hari ini (coba \"Deadline tucil hari ini apa saja, ya?\")\n" bot_response += "- Menampilkan deadline dari suatu tugas tertentu (coba \"Deadline tucil IF2230 itu kapan?\")\n" bot_response += "- Memperbarui tugas (coba \"Deadline tucil IF2230 diundur menjadi 02/02/2021\")\n" bot_response += "- Menghapus/menyelesaikan tugas (coba \"bot ujian IF2230 sudah selesai ya jadi gausah disimpan lagi\")\n" bot_response += "Kata kunci:\n" + "\n".join(list(map(lambda x: "- " + x, ["kuis", "tubes", "tucil", "ujian"]))) else: extractor = Extractor() print("\"{}\"".format(user_input)) command = extractor.extract(user_input, context) if command == None: suggested_word = SpellChecker().getWordSuggestion(user_input) else: command.execute() bot_response = command.getResult() if bot_response == "": if len(suggested_word) > 0: bot_response = "Mungkin maksud kata kunci Anda: " + ", ".join(suggested_word) else: bot_response = "Saya tidak paham .-." chat_data.append((user_input, bot_response.split("\n"))) return render_template("index.html", message_data = chat_data[(-5 if len(chat_data) >= 5 else 0):])
def test_AddTask(self): extractor = Extractor() # Normal result1 = extractor.extract( "Halo bot, tolong ingetin kalau ada kuis IF3110 Bab 2 sampai 3 pada 22/04/21", Context.addTask) assert result1 != None assert result1.matkul == "IF3110" assert result1.jenis == "kuis" assert result1.deskripsi == "Bab 2 sampai 3" assert result1.tahun == 2021 assert result1.bulan == 4 assert result1.tanggal == 22 # Normal dengan tanggal yang berbeda format, UAS adalah ujian result2 = extractor.extract( "Ingatkan saya ada UAS IF2230 pada 20 Mei 2021. Saya sedang chaos nih. :(", Context.addTask) assert result2 != None assert result2.matkul == "IF2230" assert result2.jenis == "ujian" assert result2.deskripsi == "UAS" assert result2.tahun == 2021 assert result2.bulan == 5 assert result2.tanggal == 20 # Tahun yang sama secara implisit, UTS adalah ujian result3 = extractor.extract( "Beritahukan saya tentang UTS IF2250 pada 1 Januari", Context.addTask) assert result3 != None assert result3.matkul == "IF2250" assert result3.jenis == "ujian" assert result3.deskripsi == "UTS" assert result3.tahun == datetime.now().year assert result3.bulan == 1 assert result3.tanggal == 1 # Tanggal tidak diawali dengan kata pada result4 = extractor.extract( "saya ingin menambahkan tucil IF2220 tentang String Matching yang deadline-nya sudah dekat: 28 April", Context.addTask) assert result4 != None assert result4.matkul == "IF2220" assert result4.jenis == "tucil" assert result4.deskripsi == "String Matching" assert result4.tahun == datetime.now().year assert result4.bulan == 4 assert result4.tanggal == 28 # Tidak ada tanggal (invalid) result7 = extractor.extract( "Ada tubes IF2210 tentang Worms. Ingatkan.", Context.addTask) assert result7 == None # Tidak ada matkul (invalid) result8 = extractor.extract( "Ada tucil tentang objek. Deadline 7 September. Ingatkan.", Context.addTask) assert result8 == None # Tidak ada jenis tugas (invalid) result9 = extractor.extract( "Ingatkan tentang IF2211 tentang BFS dan DFS. Deadline 5 Desember.", Context.addTask) assert result9 == None
class Puzzle(): """ Class used to store all informations about the puzzle """ def log(self, *args): """ Helper to log informations to the GUI """ print(' '.join(map(str, args))) if self.viewer: self.viewer.addLog(args) def __init__(self, path, viewer=None, green_screen=False): """ Extract informations of pieces in the img at `path` and start computation of the solution """ green_screen = True self.pieces_ = None factor = 0.40 while self.pieces_ is None: factor += 0.01 self.extract = Extractor(path, viewer, green_screen, factor) self.pieces_ = self.extract.extract() self.viewer = viewer self.green_ = green_screen self.connected_directions = [] self.diff = {} self.edge_to_piece = {} for p in self.pieces_: for e in p.edges_: self.edge_to_piece[e] = p self.extremum = (-1, -1, 1, 1) self.log('>>> START solving puzzle') border_pieces = [] non_border_pieces = [] connected_pieces = [] # Separate border pieces from the other for piece in self.pieces_: if piece.number_of_border(): border_pieces.append(piece) else: non_border_pieces.append(piece) self.possible_dim = self.compute_possible_size(len(self.pieces_), len(border_pieces)) # Start by a corner piece for piece in border_pieces: if piece.number_of_border() > 1: connected_pieces = [piece] border_pieces.remove(piece) break self.log("Number of border pieces: ", len(border_pieces) + 1) self.export_pieces('/tmp/stick{0:03d}'.format(1) + ".png", '/tmp/colored{0:03d}'.format(1) + ".png", 'Border types'.format(1), 'Step {0:03d}'.format(1), display_border=True) self.log('>>> START solve border') start_piece = connected_pieces[0] self.corner_pos = [((0, 0), start_piece)] # we start with a corner for i in range(4): if start_piece.edge_in_direction( Directions.S).connected and start_piece.edge_in_direction( Directions.W).connected: break start_piece.rotate_edges(1) self.extremum = (0, 0, 1, 1) self.strategy = Strategy.BORDER connected_pieces = self.solve(connected_pieces, border_pieces) self.log('>>> START solve middle') self.strategy = Strategy.FILL self.solve(connected_pieces, non_border_pieces) self.log('>>> SAVING result...') self.translate_puzzle() self.export_pieces("/tmp/stick.png", "./images/output/solved.png", display=True) # Two sets of pieces: Already connected ones and pieces remaining to connect to the others # The first piece has an orientation like that: # N edges: 0 # W E 3 1 # S 2 # # Pieces are placed on a grid like that (X is the first piece at position (0, 0)): # +--+--+--+ # | | | | # +--+--+--+ # | | X| | # +--+--+--+ # | | | | # +--+--+--+ # # Then if we test the NORTH edge: # +--+--+--+ # | | X| | # +--+--+--+ # | | X| | # +--+--+--+ # | | | | # +--+--+--+ # Etc until the puzzle is complete i.e. there is no pieces left on left_pieces. def solve(self, connected_pieces, left_pieces, border=False): """ Solve the puzzle by finding the optimal piece in left_pieces matching the edges available in connected_pieces :param connected_pieces: pieces already connected to the puzzle :param left_pieces: remaining pieces to place in the puzzle :param border: Boolean to determine if the strategy is border :return: List of connected pieces """ if len(self.connected_directions) == 0: self.connected_directions = [ ((0, 0), connected_pieces[0]) ] # ((x, y), p), x & y relative to the first piece, init with 1st piece self.diff = self.compute_diffs( left_pieces, self.diff, connected_pieces[0] ) # edge on the border of the block -> edge on a left piece -> diff between edges else: self.diff = self.add_to_diffs(left_pieces) while len(left_pieces) > 0: self.log("<--- New match ---> pieces left: ", len(left_pieces), 'extremum:', self.extremum, 'puzzle dimension:', display_dim(self.possible_dim)) block_best_e, best_e = self.best_diff(self.diff, self.connected_directions, left_pieces) block_best_p, best_p = self.edge_to_piece[ block_best_e], self.edge_to_piece[best_e] stick_pieces(block_best_p, block_best_e, best_p, best_e, final_stick=True) self.update_direction(block_best_e, best_p, best_e) self.connect_piece(self.connected_directions, block_best_p, block_best_e.direction, best_p) connected_pieces.append(best_p) del left_pieces[left_pieces.index(best_p)] self.diff = self.compute_diffs(left_pieces, self.diff, best_p, edge_connected=block_best_e) self.export_pieces( '/tmp/stick{0:03d}'.format(len(self.connected_directions)) + ".png", '/tmp/colored{0:03d}'.format(len(self.connected_directions)) + ".png", name_colored='Step {0:03d}'.format( len(self.connected_directions))) return connected_pieces def compute_diffs(self, left_pieces, diff, new_connected, edge_connected=None): """ Compute the diff between the left pieces edges and the new_connected piece edges by sticking them and compute the distance :param left_pieces: remaining pieces to place in the puzzle :param diff: pre computed diff between edges to speed up the process :param new_connected: Connected pieces to test for a match :return: updated diff matrix """ # Remove former edge from the bloc border if edge_connected is not None: del diff[edge_connected] # build the list of edge to test edges_to_test = [] for piece in left_pieces: for edge in piece.edges_: if not edge.connected: edges_to_test.append((piece, edge)) # Remove the edge of the new piece from the bloc border diffs for e in new_connected.edges_: for _, v in diff.items(): if e in v: del v[e] if e.connected: continue diff_e = {} for piece, edge in edges_to_test: if not e.is_compatible(edge): continue for e2 in piece.edges_: e2.backup_shape() stick_pieces(new_connected, e, piece, edge) if self.green_: diff_e[edge] = real_edge_compute(edge, e) else: diff_e[edge] = generated_edge_compute(edge, e) for e2 in piece.edges_: e2.restore_backup_shape() diff[e] = diff_e return diff def fallback(self, diff, connected_direction, left_piece, strat=Strategy.NAIVE): """ If a strategy does not work fallback to another one """ self.log('Fail to solve the puzzle with', self.strategy, 'falling back to', strat) old_strat = self.strategy self.strategy = Strategy.NAIVE best_bloc_e, best_e = self.best_diff(diff, connected_direction, left_piece) self.strategy = old_strat return best_bloc_e, best_e def best_diff(self, diff, connected_direction, left_piece): """ Find the best matching edge for a piece edge :param diff: pre computed diff between edges to speed up the process :param connected_direction: Direction of the edge to connect :param left_piece: Piece to connect :return: the best edge found in the bloc """ best_bloc_e, best_e, best_p, min_diff = None, None, None, float('inf') minX, minY, maxX, maxY = self.extremum if self.strategy == Strategy.FILL: best_coords = [] # this is ugly for i in range(4, -1, -1): # 4 to 0 best_coord = [] for x in range(minX, maxX + 1): for y in range(minY, maxY + 1): neighbor = list( filter( lambda e: is_neigbhor( (x, y), e[0], connected_direction), connected_direction)) if len(neighbor) == i: best_coord.append(((x, y), neighbor)) best_coords.append(best_coord) for best_coord in best_coords: for c, neighbor in best_coord: for p in left_piece: for rotation in range(4): diff_score = 0 p.rotate_edges(1) last_test = None, None for block_c, block_p in neighbor: direction_exposed = Directions( sub_tuple(c, block_c)) edge_exposed = block_p.edge_in_direction( direction_exposed) edge = p.edge_in_direction( get_opposite_direction(direction_exposed)) if edge_exposed.connected or edge.connected or not edge.is_compatible( edge_exposed): diff_score = float('inf') break else: diff_score += diff[edge_exposed][edge] last_test = edge_exposed, edge if diff_score < min_diff: best_bloc_e, best_e, min_diff = last_test[ 0], last_test[1], diff_score if best_e is not None: break elif len(best_coord): self.log('Fall back to a worst', self.strategy) if best_e is None: best_bloc_e, best_e = self.fallback(diff, connected_direction, left_piece) return best_bloc_e, best_e elif self.strategy == Strategy.BORDER: best_coord = [] for x in range(minX, maxX + 1): for y in range(minY, maxY + 1): neighbor = list( filter( lambda e: is_neigbhor( (x, y), e[0], connected_direction), connected_direction)) if len(neighbor) == 1 or (len(neighbor) == 2 and len(left_piece) == 1): best_coord.append(((x, y), neighbor[0])) for c, neighbor in best_coord: for p in left_piece: for rotation in range(4): diff_score = 0 p.rotate_edges(1) block_c, block_p = neighbor direction_exposed = Directions(sub_tuple(c, block_c)) edge_exposed = block_p.edge_in_direction( direction_exposed) edge = p.edge_in_direction( get_opposite_direction(direction_exposed)) if p.type == TypePiece.ANGLE: if not corner_puzzle_alignement( c, p, self.corner_pos): diff_score = float('inf') elif not self.corner_place_fit_size(c): diff_score = float('inf') if p.type == TypePiece.BORDER and self.is_edge_at_corner_place( c): diff_score = float('inf') if diff_score != 0 or edge_exposed.connected or edge.connected \ or not edge.is_compatible(edge_exposed) or not p.is_border_aligned(block_p): diff_score = float('inf') else: diff_score = diff[edge_exposed][edge] if diff_score < min_diff: best_bloc_e, best_e, min_diff = edge_exposed, edge, diff_score if best_e is None: best_bloc_e, best_e = self.fallback(diff, connected_direction, left_piece, strat=Strategy.FILL) return best_bloc_e, best_e elif self.strategy == Strategy.NAIVE: for block_e, block_e_diff in diff.items(): for e, diff_score in block_e_diff.items(): if diff_score < min_diff: best_bloc_e, best_e, min_diff = block_e, e, diff_score return best_bloc_e, best_e else: return None, None def add_to_diffs(self, left_pieces): """ build the list of edge to test """ edges_to_test = [] for piece in left_pieces: for edge in piece.edges_: if not edge.connected: edges_to_test.append((piece, edge)) for e, diff_e in self.diff.items(): for piece, edge in edges_to_test: if not e.is_compatible(edge): continue for e2 in piece.edges_: e2.backup_shape() stick_pieces(self.edge_to_piece[e], e, piece, edge) if self.green_: diff_e[edge] = real_edge_compute(edge, e) else: diff_e[edge] = generated_edge_compute(edge, e) for e2 in piece.edges_: e2.restore_backup_shape() return self.diff def update_direction(self, e, best_p, best_e): """ Update the direction of the edge after matching it """ opp = get_opposite_direction(e.direction) step = step_direction(opp, best_e.direction) for edge in best_p.edges_: edge.direction = rotate_direction(edge.direction, step) def connect_piece(self, connected_directions, curr_p, dir, best_p): """ Then we need to search the other pieces already in the puzzle that are going to be also connected: +--+--+--+ | | X| O| +--+--+--+ | | X| X| +--+--+--+ | | | | +--+--+--+ For example if I am going to put a piece at the marker 'O' only one edge will be connected to the piece therefore we need to search the adjacent pieces and connect them properly """ old_coord = list(filter(lambda x: x[1] == curr_p, connected_directions))[0][0] new_coord = add_tuple(old_coord, dir.value) for (coord, p) in connected_directions: for d in directions: if equals_tuple(coord, add_tuple(new_coord, d.value)): for edge in best_p.edges_: if edge.direction == d: edge.connected = True break for edge in p.edges_: if edge.direction == get_opposite_direction(d): edge.connected = True break connected_directions.append((new_coord, best_p)) minX, minY, maxX, maxY = self.extremum coeff = [1, 1, 1, 1] for i, d in enumerate(directions): if best_p.edge_in_direction(d).connected: coeff[i] = 0 self.extremum = (min(minX, new_coord[0] - coeff[3]), min(minY, new_coord[1] - coeff[2]), max(maxX, new_coord[0] + coeff[1]), max(maxY, new_coord[1] + coeff[0])) if best_p.type == TypePiece.ANGLE: self.corner_place_fit_size(new_coord, update_dim=True) self.corner_pos.append((new_coord, best_p)) else: self.update_dimension() self.log('Placed:', best_p.type, 'at', new_coord) def translate_puzzle(self): """ Translate all pieces to the top left corner to be sure the puzzle is in the image """ minX = sys.maxsize minY = sys.maxsize for p in self.pieces_: for e in p.edges_: for pixel in e.shape: if pixel[0] < minX: minX = pixel[0] if pixel[1] < minY: minY = pixel[1] for p in self.pieces_: for e in p.edges_: for ip, _ in enumerate(e.shape): e.shape[ip] += (-minX, -minY) for piece in self.pieces_: for p in piece.img_piece_: p.translate(minX, minY) def export_pieces(self, path_contour, path_colored, name_contour=None, name_colored=None, display=True, display_border=False): """ Export the contours and the colored image :param path_contour: Path used to export contours :param path_colored: Path used to export the colored image :return: the best edge found in the bloc """ minX, minY = float('inf'), float('inf') maxX, maxY = -float('inf'), -float('inf') midX, midY = 0, 0 for piece in self.pieces_: for p in piece.img_piece_: x, y = p.pos minX, minY = min(minX, x), min(minY, y) maxX, maxY = max(maxX, x), max(maxY, y) colored_img = np.zeros((maxX - minX, maxY - minY, 3)) border_img = np.zeros((maxX - minX, maxY - minY, 3)) averageR = 0 averageG = 0 averageB = 0 length = 0 for piece in self.pieces_: for p in piece.img_piece_: p.apply(colored_img, dx=-minX, dy=-minY) # Contours midX = 0 midY = 0 #rando = 0 l = [] for e in piece.edges_: for y, x in e.shape: l.append(x) length += 1 midX += x midY += y y, x = y - minY, x - minX if 0 <= y < border_img.shape[ 1] and 0 <= x < border_img.shape[0]: rgb = (0, 0, 0) if e.type == TypeEdge.HOLE: rgb = (102, 178, 255) if e.type == TypeEdge.HEAD: rgb = (255, 255, 102) if e.type == TypeEdge.UNDEFINED: rgb = (255, 0, 0) if e.connected: rgb = (0, 255, 0) border_img[x, y, 0] = rgb[2] border_img[x, y, 1] = rgb[1] border_img[x, y, 2] = rgb[0] averageR += border_img[x, y, 0] averageG += border_img[x, y, 1] averageB += border_img[x, y, 2] #print(len(e.shape)) xVal = ((midX / len(l)) / 640) * 2016 #640* 2016 # yVal = 2576-(midY/len(e.shape)) yVal = ((midY / len(l)) / 480) * 1504 #480* 1504 file.write(str(yVal) + " " + str(xVal) + "\n") averageR = averageR / length averageG = averageG / length averageB = averageB / length print("(" + str(averageR) + ", " + str(averageG) + ", " + str(averageB) + ")") if averageR > 95 and averageB > 95 and averageR < 140 and averageB < 140: print("Piece needs to be flipped.") file.write("\n") cv2.imwrite(path_contour, border_img) cv2.imwrite(path_colored, colored_img) if self.viewer and display: if display_border: self.viewer.addImage(name_contour, path_contour, display=False) self.viewer.addImage(name_colored, path_colored) def compute_possible_size(self, nb_piece, nb_border): """ Compute all possible size of the puzzle based on the number of pieces and the number of border pieces """ nb_edge_border = nb_border - 4 nb_middle = nb_piece - nb_border possibilities = [] for i in range(nb_edge_border // 2 + 1): w, h = i, (nb_edge_border // 2) - i if w * h == nb_middle: possibilities.append((w + 1, h + 1)) self.log('Possible sizes: (', nb_piece, 'pieces with', nb_border, 'borders among them):', display_dim(possibilities)) return possibilities def corner_place_fit_size(self, c, update_dim=False): """ Update the possible dimensions of the puzzle when a corner is placed """ def almost_equals(idx, target, val): return val[idx] == target or val[idx] == -target if len(self.possible_dim) == 1: # We have already picked a dimension return (c[0] == 0 or c[0] == self.possible_dim[0][0] or c[0] == -self.possible_dim[0][0]) and \ (c[1] == 0 or c[1] == self.possible_dim[0][1] or c[0] == -self.possible_dim[0][1]) else: if c[0] == 0: filtered = list( filter(lambda x: almost_equals(1, c[1], x), self.possible_dim)) if len(filtered): if update_dim and len(filtered) != len(self.possible_dim): self.log( 'Update possible dimensions with corner place:', display_dim(filtered)) self.possible_dim = filtered return True else: return False elif c[1] == 0: filtered = list( filter(lambda x: almost_equals(0, c[0], x), self.possible_dim)) if len(filtered): if update_dim and len(filtered) != len(self.possible_dim): self.log( 'Update possible dimensions with corner place:', display_dim(filtered)) self.possible_dim = filtered return True else: return False return False def is_edge_at_corner_place(self, c): """ Determine of an edge is at a corner place """ if len(self.possible_dim) == 1: # We have already picked a dimension return (c[0] == 0 or c[0] == self.possible_dim[0][0] or c[0] == -self.possible_dim[0][0]) and \ (c[1] == 0 or c[1] == self.possible_dim[0][1] or c[0] == -self.possible_dim[0][1]) return False def update_dimension(self): if len(self.possible_dim) == 1: return dims = [] _, _, maxX, maxY = self.extremum for x, y in self.possible_dim: if maxX <= x and maxY <= y: dims.append((x, y)) if len(dims) != len(self.possible_dim): self.log('Update possible dimensions with extremum', self.extremum, ':', display_dim(dims)) self.possible_dim = dims