Beispiel #1
0
    def randomized_select(self, select_range, priority_fn, lowestPriority=False):
        solution = list()
        total_profit = 0
        bag = Bag(self.P, self.M, self.constraints)
        options = list()
        for item in self.items:
            options.append((item, priority_fn(item)))
        options.sort(key=lambda x: -x[1])
        if lowestPriority:
            options = list(reversed(options))
        options = [x[0] for x in options]

        while len(options) > 0 and not bag.full():
            items = options[:min(select_range, len(options))]
            item = items[int(random() * len(items))]
            options.remove(item)
            print(" progress: {0:.2f} %".format(max(bag._weight / bag.P, bag._cost/bag.M) * 100), end="\r")
            if bag.has_enough_weight_for(item.weight) and bag.has_enough_money_for(item.cost):
                bag.take(item)
                solution.append(item)
                total_profit += item.profit
                new_options = list()
                for x in options:
                    if bag.can_take(x.classNumber):
                        new_options.append(x)
                options = new_options
        return (total_profit, solution)
Beispiel #2
0
    def randomized_select(self, select_range, priority_fn, lowestPriority=False):
        solution = list()
        total_profit = 0
        bag = Bag(self.P, self.M, self.constraints)
        options = list()
        for item in self.items:
            options.append((item, priority_fn(item)))
        options.sort(key=lambda x: -x[1])
        if lowestPriority:
            options = list(reversed(options))
        options = [x[0] for x in options]

        while len(options) > 0 and not bag.full():
            items = options[:min(select_range, len(options))]
            item = items[int(random() * len(items))]
            options.remove(item)
            print(" progress: {0:.2f} %".format(max(bag._weight / bag.P, bag._cost/bag.M) * 100), end="\r")
            if bag.has_enough_weight_for(item.weight) and bag.has_enough_money_for(item.cost):
                bag.take(item)
                solution.append(item)
                total_profit += item.profit
                new_options = list()
                for x in options:
                    if bag.can_take(x.classNumber):
                        new_options.append(x)
                options = new_options
        return (total_profit, solution)
Beispiel #3
0
 def greedy_on_fn(self, priority_fn, lowestPriority=False):
     solution = list()
     total_profit = 0
     bag = Bag(self.P, self.M, self.constraints)
     queue = get_priority_queue(self.items, priority_fn, lowestPriority)
     
     while not queue.isEmpty() and not bag.full():
         item = queue.pop()
         #print(" remaining items: {0:.2f}%".format(queue.count / self.N * 100), end="\r")
         print(" progress: {0:.2f} %".format(max(bag._weight / bag.P, bag._cost/bag.M) * 100), end="\r")
         if bag.has_enough_weight_for(item.weight) and bag.has_enough_money_for(item.cost):
             if bag.can_take(item.classNumber):
                 solution.append(item)
                 bag.take(item)
                 total_profit += item.profit
     return (total_profit, solution)
Beispiel #4
0
 def greedy_on_fn(self, priority_fn, lowestPriority=False):
     solution = list()
     total_profit = 0
     bag = Bag(self.P, self.M, self.constraints)
     queue = get_priority_queue(self.items, priority_fn, lowestPriority)
     
     while not queue.isEmpty() and not bag.full():
         item = queue.pop()
         #print(" remaining items: {0:.2f}%".format(queue.count / self.N * 100), end="\r")
         print(" progress: {0:.2f} %".format(max(bag._weight / bag.P, bag._cost/bag.M) * 100), end="\r")
         if bag.has_enough_weight_for(item.weight) and bag.has_enough_money_for(item.cost):
             if bag.can_take(item.classNumber):
                 solution.append(item)
                 bag.take(item)
                 total_profit += item.profit
     return (total_profit, solution)
Beispiel #5
0
def deliver_one(instructions,
                meta_request,
                db_connection_info=MongoConnectionInfo()):

    connected_bag = Bag(db_connection_info)
    package = connected_bag.take(meta_request)
    package_content = io.BytesIO(package)
    return gz_unbox(unbox_instructions=instructions, mem=package_content)
Beispiel #6
0
    def run_algorithm(self, num_solution_before_stop=100000, time_out=1000000):
        """
        This is where we implement our logic and algorithms

        Useful Parameters:
        self.P -- max weight we can carry
        self.M -- max purchasing power in dollars
        self.N -- total number of avaliable items
        self.C -- total number of constraints
        self.items -- all items avaliable for choice
        self.constraints -- a Constraint class with constraints
        """

        # STEP: Create a hashmap from class number to its items
        item_map = dict()
        for item in self.items:
            if item.classNumber not in item_map:
                item_map[item.classNumber] = set()
            item_map[item.classNumber].add(item)

        # STEP: Calculate the total weight, cost, value, and profit of each class
        def get_class_stats(items):
            total_weight = 0
            total_cost = 0
            total_value = 0
            total_profit = 0
            for item in items:
                total_weight += item.weight
                total_cost += item.cost
                total_value += item.value
                total_profit += item.profit
            return (total_weight, total_cost, total_value, total_profit)

        class_stats = dict() # Format: key: class -> value: (weight, cost, value, profit)
        for classNumber in item_map.keys():
            class_stats[classNumber] = get_class_stats(item_map[classNumber])

        # STEP: Create a BAG instance
        bag = Bag(self.P, self.M, self.constraints)

        # STEP: PriorityQueues of class's values

        fn_extract_profit_per_weight_ratio = lambda x: x.profit_per_weight_ratio()
        
        def fn_extractclass_ratio(x):
            weight, _, _, profit = class_stats[x]
            if weight == 0:
                ratio = float("inf")
            else:
                ratio = profit / weight
            return ratio


        class_queue = PriorityQueue(lowest_priority=False) # based on class's item profit_per_weight_ratio
        for classNumber in item_map.keys():
            class_queue.push(classNumber, fn_extractclass_ratio(classNumber))

        def add_to_queue(items, fn_extract_priority, queue):
            for item in items:
                priority_value = fn_extract_priority(item)
                queue.push(item, -priority_value)
            return queue

        def get_queue_of_items(items, fn_extract_priority):
            queue = PriorityQueue(lowest_priority=False)
            return add_to_queue(items, fn_extract_priority, queue)


        # STEP: pick from the bag with highest ratio
        solutions_found = dict()
        num_solution_found = 0
        iteration = 0

        class_not_used_due_to_conflict = Queue()

        add_back_conflicts = True

        while num_solution_found <= num_solution_before_stop and iteration <= time_out:
            while not class_queue.isEmpty() and iteration <= time_out:
                iteration += 1
                if iteration % (time_out / 1000) == 0:
                    print("iteration {0} -- rate: {1:.2f} %".format(iteration, iteration / time_out * 100), end="\r")
                if not class_not_used_due_to_conflict.isEmpty():
                    class_to_use  = class_not_used_due_to_conflict.pop()
                    add_back_conflicts = not add_back_conflicts
                else: 
                    class_to_use = class_queue.pop()
                    add_back_conflicts = not add_back_conflicts
                if bag.can_take(class_to_use):
                    items_queue = get_queue_of_items(item_map[class_to_use], \
                                                fn_extract_profit_per_weight_ratio)
                    item = items_queue.pop()
                    while bag.take(item):
                        if not items_queue.isEmpty():
                            item = items_queue.pop()
                        else:
                            break
                    num_solution_found += 1
                    solutions_found[bag.score()] =  bag.items()
                    print("solution {0} found".format(num_solution_found))
                else:
                    class_not_used_due_to_conflict.push(class_to_use)
                if num_solution_found >= num_solution_before_stop:
                    break
            # print("iteration {0}".format(iteration))
            iteration += 1
            if add_back_conflicts:
                add_to_queue(class_not_used_due_to_conflict.list, fn_extractclass_ratio, class_queue)
            if num_solution_found >= num_solution_before_stop:
                break

        # STEP: return the best combination found
        bestSolution = []
        bestProfit = 0
        for profit, soln in solutions_found.items():
            if profit > bestProfit:
                bestProfit = profit
                bestSolution = soln
        return bestSolution
Beispiel #7
0
    def run_algorithm(self, num_solution_before_stop=100000, time_out=1000000):
        """
        This is where we implement our logic and algorithms

        Useful Parameters:
        self.P -- max weight we can carry
        self.M -- max purchasing power in dollars
        self.N -- total number of avaliable items
        self.C -- total number of constraints
        self.items -- all items avaliable for choice
        self.constraints -- a Constraint class with constraints
        """

        # STEP: Create a hashmap from class number to its items
        item_map = dict()
        for item in self.items:
            if item.classNumber not in item_map:
                item_map[item.classNumber] = set()
            item_map[item.classNumber].add(item)

        # STEP: Calculate the total weight, cost, value, and profit of each class
        def get_class_stats(items):
            total_weight = 0
            total_cost = 0
            total_value = 0
            total_profit = 0
            for item in items:
                total_weight += item.weight
                total_cost += item.cost
                total_value += item.value
                total_profit += item.profit
            return (total_weight, total_cost, total_value, total_profit)

        class_stats = dict() # Format: key: class -> value: (weight, cost, value, profit)
        for classNumber in item_map.keys():
            class_stats[classNumber] = get_class_stats(item_map[classNumber])

        # STEP: Create a BAG instance
        bag = Bag(self.P, self.M, self.constraints)

        # STEP: PriorityQueues of class's values

        fn_extract_profit_per_weight_ratio = lambda x: x.profit_per_weight_ratio()
        
        def fn_extractclass_ratio(x):
            weight, _, _, profit = class_stats[x]
            if weight == 0:
                ratio = float("inf")
            else:
                ratio = profit / weight
            return ratio


        class_queue = PriorityQueue(lowest_priority=False) # based on class's item profit_per_weight_ratio
        for classNumber in item_map.keys():
            class_queue.push(classNumber, fn_extractclass_ratio(classNumber))

        def add_to_queue(items, fn_extract_priority, queue):
            for item in items:
                priority_value = fn_extract_priority(item)
                queue.push(item, -priority_value)
            return queue

        def get_queue_of_items(items, fn_extract_priority):
            queue = PriorityQueue(lowest_priority=False)
            return add_to_queue(items, fn_extract_priority, queue)


        # STEP: pick from the bag with highest ratio
        solutions_found = dict()
        num_solution_found = 0
        iteration = 0

        class_not_used_due_to_conflict = Queue()

        add_back_conflicts = True

        while num_solution_found <= num_solution_before_stop and iteration <= time_out:
            while not class_queue.isEmpty() and iteration <= time_out:
                iteration += 1
                if iteration % (time_out / 1000) == 0:
                    print("iteration {0} -- rate: {1:.2f} %".format(iteration, iteration / time_out * 100), end="\r")
                if not class_not_used_due_to_conflict.isEmpty():
                    class_to_use  = class_not_used_due_to_conflict.pop()
                    add_back_conflicts = not add_back_conflicts
                else: 
                    class_to_use = class_queue.pop()
                    add_back_conflicts = not add_back_conflicts
                if bag.can_take(class_to_use):
                    items_queue = get_queue_of_items(item_map[class_to_use], \
                                                fn_extract_profit_per_weight_ratio)
                    item = items_queue.pop()
                    while bag.take(item):
                        if not items_queue.isEmpty():
                            item = items_queue.pop()
                        else:
                            break
                    num_solution_found += 1
                    solutions_found[bag.score()] =  bag.items()
                    print("solution {0} found".format(num_solution_found))
                else:
                    class_not_used_due_to_conflict.push(class_to_use)
                if num_solution_found >= num_solution_before_stop:
                    break
            # print("iteration {0}".format(iteration))
            iteration += 1
            if add_back_conflicts:
                add_to_queue(class_not_used_due_to_conflict.list, fn_extractclass_ratio, class_queue)
            if num_solution_found >= num_solution_before_stop:
                break

        # STEP: return the best combination found
        bestSolution = []
        bestProfit = 0
        for profit, soln in solutions_found.items():
            if profit > bestProfit:
                bestProfit = profit
                bestSolution = soln
        return bestSolution
class Gameplay:
    def __init__(self) -> None:
        self.matrix = Matrix()
        self.bag = Bag()
        self.piece: Piece
        self.score = Score()
        self.input: Input
        self.cancel_input: Input

        self.popups: List[Popup] = []

        self.holder: Optional[Piece] = None
        self.hold_lock = False

        self.level = 1

        self.countdown = 3
        self.countdown_last = ctx.now - 1.0
        self.game_over = False
        self.game_over_sent = False

        self.last_fall: float
        self.fall_interval = 1.0

        self.last_piece_movement_counter = 0

        self.t_spin = False

        self.clearing = False
        self.clearing_rows: List[int] = []
        self.clearing_last: float

        self.garbage_adding = False
        self.garbage_hole = 0
        self.garbage_left = 0
        self.garbage_last: float

        self.send = False
        self.cancel = False

    def get_matrix(self) -> Matrix:
        return self.matrix

    def get_piece(self) -> Piece:
        return self.piece

    def get_bag(self) -> Bag:
        return self.bag

    def get_popups(self) -> List[Popup]:
        return self.popups

    def clear_popups(self) -> None:
        self.popups = []

    def set_device(self, device: Device) -> None:
        self.input = Input(device)
        self.cancel_input = Input(device)

    def initialize(self) -> None:
        self.input.bind({
            "down": self.action_down,
            "right": self.action_right,
            "left": self.action_left,
            "rotate_right": self.action_rotate_right,
            "rotate_left": self.action_rotate_left,
            "soft_fall": self.action_soft_fall,
            "hard_fall": self.action_hard_fall,
            "hold": self.action_hold,
        })

        self.cancel_input.bind({"cancel": self.action_cancel})

        self.new_piece()

    def action_cancel(self) -> None:
        self.cancel = True

    def action_down(self) -> None:
        if self.piece.move(0, 1, self.matrix.collision):
            self.reset_fall()
            ctx.mixer.play("move")

    def action_right(self) -> None:
        if self.piece.move(1, 0, self.matrix.collision):
            ctx.mixer.play("move")
            if self.piece.touching_floor:
                self.reset_fall()

    def action_left(self) -> None:
        if self.piece.move(-1, 0, self.matrix.collision):
            ctx.mixer.play("move")
            if self.piece.touching_floor:
                self.reset_fall()

    def action_rotate_right(self) -> None:
        if self.piece.rotate(self.matrix.collision, clockwise=True):
            ctx.mixer.play("rotate")
            if self.piece.touching_floor:
                self.reset_fall()

    def action_rotate_left(self) -> None:
        if self.piece.rotate(self.matrix.collision, clockwise=False):
            ctx.mixer.play("rotate")
            if self.piece.touching_floor:
                self.reset_fall()

    def action_soft_fall(self) -> None:
        rows = self.piece.fall(self.matrix.collision)
        if rows > 0:
            ctx.mixer.play("soft_fall")
            self.reset_fall()
            self.score.update_soft_drop(rows)

    def action_hard_fall(self) -> None:
        rows = self.piece.fall(self.matrix.collision)
        self.lock_piece()
        if rows > 0:
            ctx.mixer.play("hard_fall")
            self.score.update_hard_drop(rows)

    def action_hold(self) -> None:
        if self.hold_lock:
            ctx.mixer.play("hold_fail")
            return

        self.hold_lock = True

        if self.holder is not None:
            self.holder, self.piece = self.piece, self.holder
            self.reset_piece()
        else:
            self.holder = self.piece
            self.new_piece()

        self.send = True
        ctx.mixer.play("hold")

    def new_piece(self) -> None:
        self.send = True
        self.piece = self.bag.take()
        self.piece.reset()
        self.reset_fall()

        if self.matrix.collision(self.piece):
            self.game_over = True

        if self.garbage_left > 0:
            self.garbage_adding = True
            self.garbage_last = ctx.now

    def reset_piece(self) -> None:
        self.piece.reset()

        for rows in range(self.piece.shape.grid[0].height, 0, -1):
            if self.piece.move(0, rows, self.matrix.collision):
                break

        self.reset_fall()

    def reset_fall(self) -> None:
        self.last_fall = ctx.now

    def lock_piece(self) -> None:
        self.hold_lock = False
        self.t_spin = False

        if self.matrix.collision(
                self.piece) or not self.matrix.lock(self.piece):
            self.game_over = True
        else:
            if TSpin.detect(self.matrix, self.piece):
                self.t_spin = True

            self.new_piece()

        if self.game_over:
            return

        rows = self.matrix.get_full_rows()
        if rows:
            popup = self.score.update_clear(self.level, rows, self.t_spin)
            ctx.mixer.play("erase" + str(len(rows)))
            self.clear_rows(rows)
            self.popups.append(popup)

        else:
            self.score.reset_combo()

    def clear_rows(self, rows: List[int]) -> None:
        self.clearing = True
        self.clearing_rows = rows
        self.clearing_last = ctx.now + 0.15

        for row in rows:
            self.matrix.erase_row(row)

    def add_garbage(self, hole: int, count: int) -> None:
        self.garbage_hole = hole
        self.garbage_left = count

    def update(self) -> None:
        self.cancel_input.update()

        if self.clearing:
            if ctx.now - self.clearing_last > 0.02:
                self.send = True
                self.matrix.collapse_row(self.clearing_rows.pop(0))
                self.clearing_last = ctx.now
                ctx.mixer.play("line_fall")

                if not self.clearing_rows:
                    self.clearing = False
                    self.reset_piece()
        elif self.garbage_adding:
            if ctx.now - self.garbage_last > 0.03:
                self.send = True
                self.matrix.add_garbage(self.garbage_hole)
                self.garbage_last = ctx.now
                ctx.mixer.play("garbage")
                self.garbage_left -= 1

                if self.garbage_left == 0:
                    self.garbage_adding = False
                    self.reset_piece()

        if self.game_over:
            if not self.game_over_sent:
                self.game_over_sent = True
                self.send = True

            return

        if self.countdown >= 0:
            if ctx.now - self.countdown_last > 1.0:
                self.send = True
                self.countdown_last = ctx.now
                ctx.mixer.play("countdown")

                if self.countdown == 0:
                    self.popups.append(
                        Popup("GO!", size=6, color="green", duration=0.4))

                    ctx.mixer.play("go")
                    ctx.mixer.play_music("main_theme")
                else:
                    self.popups.append(
                        Popup(str(self.countdown), size=6, duration=0.4))

                self.countdown -= 1
            return

        self.input.update()

        if self.piece.movement_counter != self.last_piece_movement_counter:
            self.send = True

        self.last_piece_movement_counter = self.piece.movement_counter

        if ctx.now - self.last_fall > self.fall_interval:
            self.send = True
            if self.piece.move(0, 1, self.matrix.collision):
                self.reset_fall()
            else:
                self.lock_piece()

    def draw(self, x: int, y: int, draw_piece=True) -> None:
        self.matrix.draw(x, y)

        if draw_piece and self.piece:
            self.matrix.get_ghost(self.piece).draw(x, y)
            self.piece.draw(x, y)

        self.score.draw(x, y - 70)
        self.bag.draw(x + 340, y + 70)

        if self.holder is not None:
            holder_x = int(x - 65 - self.holder.shape.get_width(0) * 11.25)
            self.holder.shape.draw(0, holder_x, y + 60, 22, 1.0)
        else:
            shape.SHAPE_HOLD_NONE.draw(0, x - 85, y + 60, 22, 1.0)

        Text.draw("Hold", centerx=x - 75, top=y + 20)
        Text.draw("Next", centerx=x + 370, top=y + 20)