Esempio n. 1
0
 def clear_data(self):
     if self.thread is not None:
         self.thread.stop()
     self.tree.delete(*self.tree.get_children())
     self.queue = queue.Queue()
     self.state = auction.AuctionState()
     self.state.update({
         'action': 'initialize',
         'timestamp': dt.datetime.now(),
         'api_token': self.api_token
     })
Esempio n. 2
0
def test_failed_bid_case():
    auc = auction.AuctionState()
    lines = [
        "[Wed Jun 23 23:24:33 2019] You tell your raid, '!Bids open !2 Cloak of Flames'",
        "[Wed Jun 23 23:07:49 2019] Foo -> Quaff: Cloak of Flames  35",
        "[Wed Jun 23 23:07:49 2019] Bar -> Quaff: Cloak of Flames  56",
        "[Wed Jun 23 23:07:49 2019] Bar -> Quaff: I don't understand the rules, help?",
    ]
    for line in lines:
        action = parse.handle_line(line, set(['Cloak of Flames']))
        # we assume that every action was parsed properly. parse failures will cause a type error here
        update = auc.update(action)
    assert update.status_messages[
        0] == "Failed to parse bid: Bar -> Quaff: I don't understand the rules, help?"
Esempio n. 3
0
def test_whole_auction_case_4():
    auc = auction.AuctionState()
    lines = [
        "[Wed Jun 23 23:24:33 2019] You tell your raid, '!Bids open !2 Cloak of Flames'",
        "[Wed Jun 23 23:07:49 2019] Foo -> Quaff: Cloak of Flames  35",
        "[Wed Jun 23 23:07:49 2019] Bar -> Quaff: Cloak of Flames  56",
        "[Wed Jun 23 23:24:33 2019] You tell your raid, '!Bids closed Cloak of Flames '",
        "[Wed Jun 23 23:24:34 2019] You tell your raid, '!correction !award Cloak of Flames !to Baz 30'",
    ]
    for line in lines:
        action = parse.handle_line(line, set(['Cloak of Flames']))
        # we assume that every action was parsed properly. parse failures will cause a type error here
        update = auc.update(action)
    assert len(auc.concluded_auctions) == 1
    assert update.update_rows[0].winner == 'Baz'
    assert update.update_rows[0].price == '30'
Esempio n. 4
0
def test_whole_auction_case_1():
    auc = auction.AuctionState()
    lines = [
        "[Wed Jun 12 23:24:33 2019] You tell your raid, '!Bids open Cloak of Flames'",
        "[Wed Jun 12 23:07:49 2019] Foobar -> Quaff: Cloak of Flames  10",
        "[Wed Jun 12 23:07:49 2019] Playerone -> Quaff: Cloak of Flames  10",
        "[Wed Jun 12 23:07:49 2019] Playerone -> Quaff: Cloak of Flames  11",
        "[Wed Jun 12 23:24:33 2019] You tell your raid, '!Bids closed Cloak of Flames '",
    ]
    for line in lines:
        # we assume that every action was parsed properly. parse failures will cause a type error here
        action = parse.handle_line(line, set(['Cloak of Flames']))
        auc.update(action)
    finished_auction = auc.concluded_auctions[0]
    assert finished_auction['item'] == 'Cloak of Flames'
    assert len(finished_auction['bids']) == 2
Esempio n. 5
0
def test_failed_bid_case():
    auc = auction.AuctionState("Tester")
    lines = [
        "[Wed Jun 23 23:24:33 2019] You tell your raid, '!Bids open !2 Cloak of Flames'",
        "[Wed Jun 23 23:07:49 2019] Foo tells you, 'Cloak of Flames  35'",
        "[Wed Jun 23 23:07:49 2019] Bar tells you, 'Cloak of Flames  56'",
        "[Wed Jun 23 23:07:49 2019] Bar tells you, 'I don't understand the rules, help?",
    ]
    for line in lines:
        actions = parse.handle_line(line, set(['Cloak of Flames']))
        # we assume that every action was parsed properly. parse failures will cause a type error here
        if not isinstance(actions, list):
            actions = [actions]
        for action in actions:
            update = auc.update(action)
    assert update.status_messages[
        0] == "Failed to parse bid: Bar tells you, 'I don't understand the rules, help?"
Esempio n. 6
0
def test_preregister_bid_alt():
    auc = auction.AuctionState("Tester")
    lines = [
        "[Wed Jun 12 23:24:32 2019] You told Grunt, '!preregister Cloak of Flames 20 alt'",
        "[Wed Jun 12 23:24:33 2019] You tell your raid, '!Bids open Cloak of Flames'",
        "[Wed Jun 12 23:07:49 2019] Foobar tells you, 'Cloak of Flames  5'",
        "[Wed Jun 12 23:07:49 2019] Playerone tells you, 'Cloak of Flames  5'",
        "[Wed Jun 12 23:24:33 2019] You tell your raid, '!Bids closed Cloak of Flames '",
    ]

    body = {
        'message': 'Cloak of Flames awarded to - Tester for 1',
        'warnings': []
    }
    responses.add(responses.POST,
                  'http://padkp.net/api/resolve_auction/',
                  json=body)
    for line in lines:
        # we assume that every action was parsed properly. parse failures will cause a type error here
        actions = parse.handle_line(line, set(['Cloak of Flames']))
        if not isinstance(actions, list):
            actions = [actions]
        for action in actions:
            update = auc.update(action)

    data = json.loads(responses.calls[0].request.body)
    finished_auction = auc.concluded_auctions['Cloak of Flames']

    assert finished_auction['item'] == 'Cloak of Flames'
    assert len(finished_auction['bids']) == 6
    assert update.update_rows[
        0].winner == 'Cloak of Flames awarded to - Tester for 1'
    assert data['bids'] == [{
        'name': 'Tester',
        'bid': 20,
        'tag': 'ALT'
    }, {
        'name': "Foobar",
        'bid': 5,
        'tag': ''
    }, {
        'name': 'Playerone',
        'bid': 5,
        'tag': ''
    }]
Esempio n. 7
0
def test_whole_auction_correction_after_close_multibid_case():
    auc = auction.AuctionState("Tester")
    lines = [
        "[Wed Jun 12 23:24:33 2019] You tell your raid, '!Bids open !2 Cloak of Flames'",
        "[Wed Jun 12 23:07:49 2019] Foobar tells you, 'Cloak of Flames  10'",
        "[Wed Jun 12 23:07:49 2019] Playerone tells you, 'Cloak of Flames  10'",
        "[Wed Jun 12 23:07:49 2019] Playerone tells you, 'Cloak of Flames  11, 15 alt'",
        "[Wed Jun 12 23:24:33 2019] You tell your raid, '!Bids closed Cloak of Flames '",
        "[Wed Jun 23 23:24:34 2019] You tell your raid, '!correction !award Cloak of Flames !to Baz 30, Foobar 15'",
    ]

    body = {
        'message': 'Cloak of Flames awarded to - Tester for 1',
        'warnings': []
    }
    responses.add(responses.POST,
                  'http://padkp.net/api/resolve_auction/',
                  json=body)
    responses.add(responses.POST,
                  'http://padkp.net/api/correct_auction/',
                  json=body)

    for line in lines:
        # we assume that every action was parsed properly. parse failures will cause a type error here
        actions = parse.handle_line(line, set(['Cloak of Flames']))
        if not isinstance(actions, list):
            actions = [actions]
        for action in actions:
            update = auc.update(action)

    close_finger = json.loads(responses.calls[0].request.body)['fingerprint']
    correct_finger = json.loads(responses.calls[1].request.body)['fingerprint']
    data = json.loads(responses.calls[1].request.body)

    assert len(auc.concluded_auctions) == 1
    assert close_finger == correct_finger
    assert data['bids'] == [{
        'name': 'Baz',
        'bid': '30'
    }, {
        'name': 'Foobar',
        'bid': '15'
    }]
Esempio n. 8
0
def test_preregister_bid():
    auc = auction.AuctionState()
    auc.my_name = "Tester"
    lines = [
        "[Wed Jun 12 23:24:32 2019] You told Grunt, '!preregister Cloak of Flames 20'",
        "[Wed Jun 12 23:24:33 2019] You tell your raid, '!Bids open Cloak of Flames'",
        "[Wed Jun 12 23:07:49 2019] Foobar -> Quaff: Cloak of Flames  10",
        "[Wed Jun 12 23:07:49 2019] Playerone -> Quaff: Cloak of Flames  10",
        "[Wed Jun 12 23:24:33 2019] You tell your raid, '!Bids closed Cloak of Flames '",
    ]
    for line in lines:
        # we assume that every action was parsed properly. parse failures will cause a type error here
        action = parse.handle_line(line, set(['Cloak of Flames']))
        update = auc.update(action)
    finished_auction = auc.concluded_auctions[0]
    assert finished_auction['item'] == 'Cloak of Flames'
    assert len(finished_auction['bids']) == 3
    assert update.update_rows[0].winner == 'Tester'
    assert update.update_rows[0].price == '20'
Esempio n. 9
0
def test_whole_auction_cancel_pre_close_case():
    auc = auction.AuctionState("Tester")
    lines = [
        "[Wed Jun 12 23:24:33 2019] You tell your raid, '!Bids open Cloak of Flames'",
        "[Wed Jun 12 23:07:49 2019] Foobar tells you, 'Cloak of Flames  10'",
        "[Wed Jun 12 23:07:49 2019] Playerone tells you, 'Cloak of Flames  10'",
        "[Wed Jun 12 23:07:49 2019] Playerone tells you, 'Cloak of Flames  11, 15 alt'",
        "[Wed Jun 12 23:24:33 2019] You tell your raid, '!Cancel Cloak of Flames '",
    ]

    for line in lines:
        # we assume that every action was parsed properly. parse failures will cause a type error here
        actions = parse.handle_line(line, set(['Cloak of Flames']))
        if not isinstance(actions, list):
            actions = [actions]
        for action in actions:
            update = auc.update(action)

    assert len(auc.concluded_auctions) == 0
    assert auc.active_auctions == {}
Esempio n. 10
0
def test_whole_auction_case_2():
    auc = auction.AuctionState()
    lines = [
        "[Wed Jun 12 23:01:33 2019] You tell your raid, '!Bids open Green Dragon Scale'",
        "[Wed Jun 12 23:02:49 2019] Foobar -> Quaff: Cloak of Flames  10",
        "[Wed Jun 12 23:03:49 2019] Foobar -> Quaff: Green Dragon Scale  10",
        "[Wed Jun 12 23:04:49 2019] Grunt -> Quaff: Green Dragon Scale  4",
        "[Wed Jun 12 23:05:49 2019] Papapa -> Quaff: Green Dragon Scale  5",
        "[Wed Jun 12 23:06:49 2019] Baz -> Quaff: Green Dragon Scale  10",
        "[Wed Jun 12 23:07:33 2019] You tell your raid, '!Bids closed Green Dragon Scale'",
    ]
    for line in lines:
        action = parse.handle_line(
            line, set(['Cloak of Flames', 'Green Dragon Scale']))
        auc.update(action)
    assert len(
        auc.concluded_auctions) == 0  # bids are tied, auction wasn't completed
    tied_auction = list(auc.active_auctions.values())[0]
    assert tied_auction['item'] == 'Green Dragon Scale'
    assert len(tied_auction['bids']) == 4
Esempio n. 11
0
def test_whole_auction_case_3():
    auc = auction.AuctionState()
    lines = [
        "[Wed Jun 12 23:01:33 2019] You tell your raid, '!Bids open Amulet of Necropotence'",
        "[Wed Jun 12 23:07:49 2019] Foo -> Quaff: Amulet of Necropotence 90",
        "[Wed Jun 12 23:07:49 2019] Bar -> Quaff: Amulet of Necropotence 112 ALT",
        "[Wed Jun 12 23:07:49 2019] Baz -> Quaff: Amulet of Necropotence 75",
        "[Wed Jun 12 23:07:49 2019] Qux -> Quaff: Amulet of Necropotence 40",
        "[Wed Jun 12 23:07:49 2019] Quux -> Quaff: Amulet of Necropotence 2",
        "[Wed Jun 12 23:07:49 2019] Thud -> Quaff: Amulet of Necropotence 89",
        "[Wed Jun 12 23:07:49 2019] Waldo -> Quaff: Amulet of Necropotence 13",
        "[Wed Jun 12 23:24:33 2019] You tell your raid, '!Bids closed Amulet of Necropotence'",
    ]
    for line in lines:
        action = parse.handle_line(line, set(['Amulet of Necropotence']))
        # we assume that every action was parsed properly. parse failures will cause a type error here
        update = auc.update(action)

    assert len(auc.concluded_auctions) == 1
    assert len(update.update_rows) == 1
    assert update.update_rows[0].winner == 'Foo'
Esempio n. 12
0
def test_whole_auction_case_1():
    auc = auction.AuctionState("Tester")
    lines = [
        "[Wed Jun 12 23:24:33 2019] You tell your raid, '!Bids open Cloak of Flames'",
        "[Wed Jun 12 23:07:49 2019] Foobar tells you, 'Cloak of Flames  10'",
        "[Wed Jun 12 23:07:49 2019] Playerone tells you, 'Cloak of Flames  10'",
        "[Wed Jun 12 23:07:49 2019] Playerone tells you, 'Cloak of Flames  11'",
        "[Wed Jun 12 23:24:33 2019] You tell your raid, '!Bids closed Cloak of Flames '",
    ]

    body = {
        'message': 'Cloak of Flames awarded to - Playerone for 11',
        'warnings': []
    }

    responses.add(responses.POST,
                  'http://padkp.net/api/resolve_auction/',
                  json=body)
    for line in lines:
        # we assume that every action was parsed properly. parse failures will cause a type error here
        actions = parse.handle_line(line, set(['Cloak of Flames']))
        if not isinstance(actions, list):
            actions = [actions]
        for action in actions:
            auc.update(action)
    data = json.loads(responses.calls[0].request.body)
    finished_auction = auc.concluded_auctions['Cloak of Flames']
    assert finished_auction['item'] == 'Cloak of Flames'
    assert len(finished_auction['bids']) == 4
    assert data['bids'] == [{
        'name': 'Foobar',
        'bid': 10,
        'tag': ''
    }, {
        'name': 'Playerone',
        'bid': 11,
        'tag': ''
    }]
    assert data['item_name'] == 'Cloak of Flames'
    assert data['item_count'] == 1
Esempio n. 13
0
def test_whole_auction_cancel_after_close_case():
    auc = auction.AuctionState("Tester")
    lines = [
        "[Wed Jun 12 23:24:33 2019] You tell your raid, '!Bids open Cloak of Flames'",
        "[Wed Jun 12 23:07:49 2019] Foobar tells you, 'Cloak of Flames  10'",
        "[Wed Jun 12 23:07:49 2019] Playerone tells you, 'Cloak of Flames  10'",
        "[Wed Jun 12 23:07:49 2019] Playerone tells you, 'Cloak of Flames  11, 15 alt'",
        "[Wed Jun 12 23:24:33 2019] You tell your raid, '!Bids closed Cloak of Flames '",
        "[Wed Jun 12 23:24:33 2019] You tell your raid, '!Cancel Cloak of Flames '",
    ]

    body = {
        'message': 'Cloak of Flames awarded to - Tester for 1',
        'warnings': []
    }
    responses.add(responses.POST,
                  'http://padkp.net/api/resolve_auction/',
                  json=body)
    responses.add(responses.POST,
                  'http://padkp.net/api/cancel_auction/',
                  json=body)

    for line in lines:
        # we assume that every action was parsed properly. parse failures will cause a type error here
        actions = parse.handle_line(line, set(['Cloak of Flames']))
        if not isinstance(actions, list):
            actions = [actions]
        for action in actions:
            update = auc.update(action)

    close_finger = json.loads(responses.calls[0].request.body)['fingerprint']
    cancel_finger = json.loads(responses.calls[1].request.body)['fingerprint']

    assert len(auc.concluded_auctions) == 0
    assert auc.active_auctions == {}
    assert close_finger == cancel_finger
Esempio n. 14
0
File: gui.py Progetto: rcuhljr/PADKP
    def __init__(self, master):
        self.master = master
        self.frame = tkinter.Frame(self.master)

        menu_bar = tkinter.Menu(master)
        file_menu = tkinter.Menu(menu_bar, tearoff=0)
        file_menu.add_command(label="Open log file (Ctrl-F)", command=self.open_log_file)
        file_menu.add_command(label="Choose raid dump directory (Ctrl-R)", command=self.choose_raid_dump_dir)
        file_menu.add_command(label="Enter API token (Ctrl-T)", command=self.ask_api_token)
        file_menu.add_command(label="Close (Ctrl-Q)", command=self.confirm_quit)
        menu_bar.add_cascade(label="File", menu=file_menu)

        auction_menu = tkinter.Menu(menu_bar, tearoff=0)
        auction_menu.add_command(label="See auction details (Ctrl-D)", command=self.open_details_window)
        auction_menu.add_command(label="Copy grats message (Ctrl-G)", command=self.copy_grats_message)
        auction_menu.add_command(label="Copy all concluded auctions (Ctrl-Shift-C)", command=self.copy_report)
        auction_menu.add_command(label="Copy concluded auctions from selection (Ctrl-C)", command=self.copy_report_from_selection)
        auction_menu.add_command(label="Charge DKP (Ctrl-B)", command=self.charge_dkp)
        menu_bar.add_cascade(label="Auctions", menu=auction_menu)

        dkp_menu = tkinter.Menu(menu_bar, tearoff=0)
        dkp_menu.add_command(label="Award DKP (Ctrl-W)", command=self.open_award_dkp_window)
        menu_bar.add_cascade(label="Awards", menu=dkp_menu)

        master.config(menu=menu_bar)

        columns = ['item', 'item_count', 'status', 'winner', 'price']
        self.tree = ttk.Treeview(self.master, columns=columns)
        self.tree.heading('#0', text='time')
        self.tree.heading('#1', text='item')
        self.tree.heading('#2', text='count')
        self.tree.heading('#3', text='status')
        self.tree.heading('#4', text='winner')
        self.tree.heading('#5', text='price')
        self.tree.column('#0', stretch=tkinter.YES)
        self.tree.column('#1', stretch=tkinter.YES)
        self.tree.column('#2', stretch=tkinter.YES)
        self.tree.column('#3', stretch=tkinter.YES)
        self.tree.column('#4', stretch=tkinter.YES)
        self.tree.column('#5', stretch=tkinter.YES)
        self.tree.grid(row=1, columnspan=4, sticky='nsw')

        self.button = tkinter.Button(master, text="Load log file (Ctrl-F)", command=self.open_log_file)
        self.button.grid(row=2, column=0)

        self.button = tkinter.Button(master, text="Auction details (Ctrl-D)",
                                     command=self.open_details_window)
        self.button.grid(row=2, column=1)

        self.button = tkinter.Button(master, text="Award DKP (Ctrl-W)", command=self.open_award_dkp_window)
        self.button.grid(row=2, column=2)

        self.button = tkinter.Button(master, text="Close (Ctrl-Q)", command=self.confirm_quit)
        self.button.grid(row=2, column=3)

        self.status_window = tkinter.Text(master, height= 10, wrap="word")
        self.status_window.grid(row=4, columnspan=4, sticky='nsew')
        self.scroll = tkinter.Scrollbar(master, orient="vertical", command=self.status_window.yview)
        self.scroll.grid(row=4, column=4, sticky='nse')
        self.status_window.configure(state='normal')
        self.status_window.configure(yscrollcommand=self.scroll.set)
        self.status_window.see("end")
        self.status_window.configure(state='disabled')

        self.raid_dump_pane = ttk.Treeview(master, columns=['time'], selectmode='browse')
        self.raid_dump_pane.grid(row=3, column=0, columnspan=4, sticky='ew')
        self.raid_dump_pane.heading('#0', text='dump')
        self.raid_dump_pane.heading('#1', text='time')
        self.raid_dump_files = set()

        self.master.protocol("WM_DELETE_WINDOW", self.confirm_quit)

        self.thread = None  # thread to asynchronously read data from the log file

        self.queue = queue.Queue()  # holds actions from the log file that update the state of the world
        self.state = auction.AuctionState()

        def auction_context_menu_popup(event):
            self.tree.focus()
            auction_context_menu.post(event.x_root, event.y_root)
        self.tree.bind("<Control-Button-1>", auction_context_menu_popup)
        self.tree.bind("<Button-3>", auction_context_menu_popup)
        auction_context_menu = tkinter.Menu(self.frame, tearoff=0)
        auction_context_menu.add_command(label="Copy grats message (Ctrl-G)", command=self.copy_grats_message)
        auction_context_menu.add_command(label="Copy all concluded auctions (Ctrl-Shift-C)", command=self.copy_report)
        auction_context_menu.add_command(label="Copy concluded auctions from selection (Ctrl-C)", command=self.copy_report_from_selection)
        auction_context_menu.add_command(label="Charge DKP (Ctrl-B)", command=self.charge_dkp)

        def raid_dump_context_menu_popup(event):
            self.raid_dump_pane.focus()
            raid_dump_context_menu.post(event.x_root, event.y_root)
        self.raid_dump_pane.bind("<Control-Button-1>", raid_dump_context_menu_popup)
        self.raid_dump_pane.bind("<Button-3>", raid_dump_context_menu_popup)
        raid_dump_context_menu = tkinter.Menu(self.frame, tearoff=0)
        raid_dump_context_menu.add_command(label="Award DKP (Ctrl-W)", command=self.open_award_dkp_window)
        raid_dump_context_menu.add_command(label="Quick award DKP (Ctrl-Shift-W)", command=self.quick_award_dkp)

        # add keyboard shortcuts
        self.master.bind("<Control-f>", lambda _: self.open_log_file())
        self.master.bind("<Control-c>", lambda _: self.copy_report_from_selection())
        self.master.bind("<Control-C>", lambda _: self.copy_report())
        self.master.bind("<Control-g>", lambda _: self.copy_grats_message())
        self.master.bind("<Control-q>", lambda _: self.confirm_quit())
        self.master.bind("<Control-d>", lambda _: self.open_details_window())
        self.master.bind("<Control-b>", lambda _: self.charge_dkp())
        self.master.bind("<Control-w>", lambda _: self.open_award_dkp_window())
        self.master.bind("<Control-Shift-W>", lambda _: self.quick_award_dkp())
        self.master.bind("<Control-t>", lambda _: self.ask_api_token())
        self.master.bind("<Control-r>", lambda _: self.choose_raid_dump_dir())

        self.master.after(1, self.tree.focus_force)

        self.my_name = ''
        self.config = config.load_saved_config()
        self.api_token_asked = False
        self.api_token = self.config.get('api_token', None)
        if 'log_file' in self.config and os.path.exists(self.config['log_file']):
            self.open_log_file(self.config['log_file'])

        if 'dump_path' in self.config and os.path.exists(self.config['dump_path']):
            self.show_raid_dumps()
        print("LOADED")
Esempio n. 15
0
File: gui.py Progetto: rcuhljr/PADKP
 def clear_data(self):
     if self.thread is not None:
         self.thread.stop()
     self.tree.delete(*self.tree.get_children())
     self.queue = queue.Queue()
     self.state = auction.AuctionState()
Esempio n. 16
0
def test_whole_auction_case_3():
    auc = auction.AuctionState("Tester")
    lines = [
        "[Wed Jun 12 23:01:33 2019] You tell your raid, '!Bids open Amulet of Necropotence'",
        "[Wed Jun 12 23:01:34 2019] You tell your raid, '!Bids open Amulet of Awesome'",
        "[Wed Jun 12 23:07:49 2019] Foo tells you, 'Amulet of Necropotence 90'",
        "[Wed Jun 12 23:07:49 2019] Bar tells you, 'Amulet of Necropotence 112 ALT'",
        "[Wed Jun 12 23:07:49 2019] Baz tells you, 'Amulet of Necropotence 75'",
        "[Wed Jun 12 23:07:49 2019] Qux tells you, 'Amulet of Necropotence 40'",
        "[Wed Jun 12 23:07:50 2019] Qux tells you, 'Amulet of Awesome 40'",
        "[Wed Jun 12 23:07:49 2019] Quux tells you, 'Amulet of Necropotence 2'",
        "[Wed Jun 12 23:24:33 2019] You tell your raid, '!Bids closed Amulet of Awesome'",
        "[Wed Jun 12 23:07:49 2019] Thud tells you, 'Amulet of Necropotence 89'",
        "[Wed Jun 12 23:07:49 2019] Waldo tells you, 'Amulet of Necropotence 13'",
        "[Wed Jun 12 23:24:33 2019] You tell your raid, '!Bids closed Amulet of Necropotence'",
    ]

    body = {
        'message': 'Cloak of Flames awarded to - Foo for 1',
        'warnings': ['bad bid 1', 'bad bid 2']
    }
    responses.add(responses.POST,
                  'http://padkp.net/api/resolve_auction/',
                  json=body)

    for line in lines:
        actions = parse.handle_line(
            line, set(['Amulet of Necropotence', 'Amulet of Awesome']))
        # we assume that every action was parsed properly. parse failures will cause a type error here
        if not isinstance(actions, list):
            actions = [actions]
        for action in actions:
            update = auc.update(action)

    data = json.loads(responses.calls[1].request.body)

    assert len(auc.concluded_auctions) == 2
    assert len(update.update_rows) == 1
    assert update.update_rows[
        0].winner == 'Cloak of Flames awarded to - Foo for 1'
    assert data['bids'] == [{
        'name': 'Foo',
        'bid': 90,
        'tag': ''
    }, {
        'name': "Bar",
        'bid': 112,
        'tag': 'ALT'
    }, {
        'name': 'Baz',
        'bid': 75,
        'tag': ''
    }, {
        'name': 'Qux',
        'bid': 40,
        'tag': ''
    }, {
        'name': 'Quux',
        'bid': 2,
        'tag': ''
    }, {
        'name': 'Thud',
        'bid': 89,
        'tag': ''
    }, {
        'name': 'Waldo',
        'bid': 13,
        'tag': ''
    }]
    assert update.update_rows[0].warnings == 'bad bid 1, bad bid 2'
Esempio n. 17
0
    def __init__(self, master):
        self.master = master
        self.frame = tkinter.Frame(self.master)

        menu_bar = tkinter.Menu(master)
        file_menu = tkinter.Menu(menu_bar, tearoff=0)
        file_menu.add_command(label="Open log file (Ctrl-F)",
                              command=self.open_log_file)
        file_menu.add_command(label="Choose raid dump directory (Ctrl-R)",
                              command=self.choose_raid_dump_dir)
        file_menu.add_command(label="Enter API token (Ctrl-T)",
                              command=self.reset_api_token)
        file_menu.add_command(label="Close (Ctrl-Q)",
                              command=self.confirm_quit)
        menu_bar.add_cascade(label="File", menu=file_menu)

        auction_menu = tkinter.Menu(menu_bar, tearoff=0)
        auction_menu.add_command(label="See auction details (Ctrl-D)",
                                 command=self.open_details_window)
        auction_menu.add_command(label="Copy grats message (Ctrl-G)",
                                 command=self.copy_grats_message)
        auction_menu.add_command(
            label="Copy all concluded auctions (Ctrl-Shift-C)",
            command=self.copy_report)
        auction_menu.add_command(
            label="Copy concluded auctions from selection (Ctrl-C)",
            command=self.copy_report_from_selection)

        menu_bar.add_cascade(label="Auctions", menu=auction_menu)

        dkp_menu = tkinter.Menu(menu_bar, tearoff=0)
        dkp_menu.add_command(label="Award DKP (Ctrl-W)",
                             command=self.open_award_dkp_window)
        menu_bar.add_cascade(label="Awards", menu=dkp_menu)

        waitlist_menu = tkinter.Menu(menu_bar, tearoff=0)
        waitlist_menu.add_command(label="View waitlist",
                                  command=self.open_waitlist_window)
        menu_bar.add_cascade(label="Waitlist", menu=waitlist_menu)

        master.config(menu=menu_bar)

        # Bug in this version of python/tkinkter with background colors in tree views.
        # https://stackoverflow.com/questions/56331001/python-tkinter-treeview-colors-are-not-updating
        def fixed_map(option):
            # Returns the style map for 'option' with any styles starting with
            # ("!disabled", "!selected", ...) filtered out

            # style.map() returns an empty list for missing options, so this should
            # be future-safe
            return [
                elm for elm in style.map("Treeview", query_opt=option)
                if elm[:2] != ("!disabled", "!selected")
            ]

        style = ttk.Style()
        style.map("Treeview",
                  foreground=fixed_map("foreground"),
                  background=fixed_map("background"))

        columns = ['item', 'item_count', 'status', 'results', 'warnings']
        self.tree = ttk.Treeview(self.master, columns=columns)
        self.tree.heading('#0', text='time')
        self.tree.heading('#1', text='item')
        self.tree.heading('#2', text='count')
        self.tree.heading('#3', text='status')
        self.tree.heading('#4', text='results')
        self.tree.heading('#5', text='warnings')
        self.tree.column('#0', stretch=tkinter.YES, minwidth=175)
        self.tree.column('#1', stretch=tkinter.YES, minwidth=200)
        self.tree.column('#2', stretch=tkinter.YES, minwidth=40)
        self.tree.column('#3', stretch=tkinter.YES, minwidth=75, width=75)
        self.tree.column('#4', stretch=tkinter.YES, minwidth=200)
        self.tree.column('#5', stretch=tkinter.YES, minwidth=300)
        self.tree.grid(row=1, columnspan=4, sticky='nsw')

        self.tree.tag_configure("charged", background='green')

        self.tree.tag_configure("warning", background='orange')

        self.tree.tag_configure("error", background='red')

        self.tree.tag_configure("corrected", background='yellow')

        self.button = tkinter.Button(master,
                                     text="Load log file (Ctrl-F)",
                                     command=self.open_log_file)
        self.button.grid(row=2, column=0)

        self.button = tkinter.Button(master,
                                     text="Auction details (Ctrl-D)",
                                     command=self.open_details_window)
        self.button.grid(row=2, column=1)

        self.button = tkinter.Button(master,
                                     text="Award DKP (Ctrl-W)",
                                     command=self.open_award_dkp_window)
        self.button.grid(row=2, column=2)

        self.button = tkinter.Button(master,
                                     text="Close (Ctrl-Q)",
                                     command=self.confirm_quit)
        self.button.grid(row=2, column=3)

        self.status_window = tkinter.Text(master, height=10, wrap="word")
        self.status_window.grid(row=4, columnspan=4, sticky='nsew')
        self.scroll = tkinter.Scrollbar(master,
                                        orient="vertical",
                                        command=self.status_window.yview)
        self.scroll.grid(row=4, column=4, sticky='nse')
        self.status_window.configure(state='normal')
        self.status_window.configure(yscrollcommand=self.scroll.set)
        self.status_window.see("end")
        self.status_window.configure(state='disabled')

        self.raid_dump_pane = ttk.Treeview(master,
                                           columns=['time'],
                                           selectmode='browse')
        self.raid_dump_pane.grid(row=3, column=0, columnspan=4, sticky='ew')
        self.raid_dump_pane.heading('#0', text='dump')
        self.raid_dump_pane.heading('#1', text='time')
        self.raid_dump_files = set()

        self.master.protocol("WM_DELETE_WINDOW", self.confirm_quit)

        self.thread = None  # thread to asynchronously read data from the log file

        # holds actions from the log file that update the state of the world
        self.queue = queue.Queue()
        self.state = auction.AuctionState()

        def auction_context_menu_popup(event):
            self.tree.focus()
            auction_context_menu.post(event.x_root, event.y_root)

        self.tree.bind("<Control-Button-1>", auction_context_menu_popup)
        self.tree.bind("<Button-3>", auction_context_menu_popup)
        auction_context_menu = tkinter.Menu(self.frame, tearoff=0)
        auction_context_menu.add_command(label="Copy grats message (Ctrl-G)",
                                         command=self.copy_grats_message)
        auction_context_menu.add_command(
            label="Copy all concluded auctions (Ctrl-Shift-C)",
            command=self.copy_report)
        auction_context_menu.add_command(
            label="Copy concluded auctions from selection (Ctrl-C)",
            command=self.copy_report_from_selection)

        def raid_dump_context_menu_popup(event):
            self.raid_dump_pane.focus()
            raid_dump_context_menu.post(event.x_root, event.y_root)

        self.raid_dump_pane.bind("<Control-Button-1>",
                                 raid_dump_context_menu_popup)
        self.raid_dump_pane.bind("<Button-3>", raid_dump_context_menu_popup)
        raid_dump_context_menu = tkinter.Menu(self.frame, tearoff=0)
        raid_dump_context_menu.add_command(label="Award DKP (Ctrl-W)",
                                           command=self.open_award_dkp_window)
        raid_dump_context_menu.add_command(
            label="Quick award DKP (Ctrl-Shift-W)",
            command=self.quick_award_dkp)
        raid_dump_context_menu.add_command(
            label="Award CASUAL RAID DKP (Ctrl-Shift-M)",
            command=self.casual_award_dkp)

        # add keyboard shortcuts
        self.master.bind("<Control-f>", lambda _: self.open_log_file())
        self.master.bind("<Control-c>",
                         lambda _: self.copy_report_from_selection())
        self.master.bind("<Control-C>", lambda _: self.copy_report())
        self.master.bind("<Control-g>", lambda _: self.copy_grats_message())
        self.master.bind("<Control-q>", lambda _: self.confirm_quit())
        self.master.bind("<Control-d>", lambda _: self.open_details_window())
        self.master.bind("<Control-w>", lambda _: self.open_award_dkp_window())
        self.master.bind("<Control-Shift-W>", lambda _: self.quick_award_dkp())
        self.master.bind("<Control-Shift-M>",
                         lambda _: self.casual_award_dkp())
        self.master.bind("<Control-t>", lambda _: self.reset_api_token())
        self.master.bind("<Control-r>", lambda _: self.choose_raid_dump_dir())

        self.master.after(1, self.tree.focus_force)

        self.my_name = ''
        self.config = config.load_saved_config()

        # trigger the various events that happen "on update"
        self.force_token = False
        self.ask_api_token()

        if 'log_file' in self.config and os.path.exists(
                self.config['log_file']):
            self.open_log_file(self.config['log_file'])

        if 'dump_path' in self.config and os.path.exists(
                self.config['dump_path']):
            self.show_raid_dumps()

        print("LOADED")