Example #1
0
    def __init__(self):
        self.help_text = ' n:Next  N:Prev  t:Play for time  T:Go to time  l:Play for lines  L:Play to line  a:Aggregate  .:Repeat'
        self.screen = None
        self.quotebook = BookViewerBook()
        self.max_reverse = 100
        self.quotebook_history = deque(maxlen=self.max_reverse)
        self.infile = []
        self.curr_index = -1
        self.last_skipped = 0
        self.aggregate = False

        self.keys = {
        'EXIT': 113,  # q
        'REPEAT': 46,  # .
        'PREVIOUS': 78,  # N
        'NEXT': 110,  # n
        'PLAY_FOR_TIME': 116,  # t
        'PLAY_TO_TIME': 84,  # T
        'PLAY_FOR_LINES': 108,  # l
        'PLAY_TO_LINE': 76,  # L
        'AGGREGATE': 97,  # a
        'ESCAPE': 27,  # <ESC>
        }
Example #2
0
 def reset(self):
     self.quotebook = BookViewerBook()
     self.quotebook_history.clear()
     self.curr_index = -1
Example #3
0
class BookViewer(object):
    def __init__(self):
        self.help_text = ' n:Next  N:Prev  t:Play for time  T:Go to time  l:Play for lines  L:Play to line  a:Aggregate  .:Repeat'
        self.screen = None
        self.quotebook = BookViewerBook()
        self.max_reverse = 100
        self.quotebook_history = deque(maxlen=self.max_reverse)
        self.infile = []
        self.curr_index = -1
        self.last_skipped = 0
        self.aggregate = False

        self.keys = {
        'EXIT': 113,  # q
        'REPEAT': 46,  # .
        'PREVIOUS': 78,  # N
        'NEXT': 110,  # n
        'PLAY_FOR_TIME': 116,  # t
        'PLAY_TO_TIME': 84,  # T
        'PLAY_FOR_LINES': 108,  # l
        'PLAY_TO_LINE': 76,  # L
        'AGGREGATE': 97,  # a
        'ESCAPE': 27,  # <ESC>
        }

    def reset(self):
        self.quotebook = BookViewerBook()
        self.quotebook_history.clear()
        self.curr_index = -1

    def process_line(self, save_history=False):
        # Save the history
        if save_history:
            self.quotebook_history.append(cPickle.dumps(self.quotebook, protocol=-1))
        else:
            self.quotebook_history.clear()

        # Play line
        line = self.infile[self.curr_index + 1]
        if line[0] == 'B':
            self.quotebook.bid(line.rstrip())
        elif line[0] == 'A':
            self.quotebook.ask(line.rstrip())
        else:
            self.quotebook.trade(line.rstrip())

        self.curr_index += 1

    def reverse_book(self):
        if len(self.quotebook_history) > 0:
            self.quotebook = cPickle.loads(self.quotebook_history.pop())
            self.curr_index -= 1

    def read_file(self, filename):
        try:
            reader = open(sys.argv[1], 'r')
            for line in reader:
                self.infile.append(line)
        except IOError:
            print('Cannot open input file: %s' % filename)
            sys.exit(1)

    def play_lines(self, number):
        target_index = self.curr_index + number
        if target_index > self.curr_index:
            max_index = target_index if target_index < len(self.infile) else len(self.infile) - 1
            while self.curr_index < max_index:
                if max_index - self.curr_index <= self.max_reverse:
                    self.process_line(save_history=True)
                else:
                    self.process_line(save_history=False)
        elif target_index < self.curr_index and target_index >= 0:
            # Negative lines
            reverse_lines = self.curr_index - target_index
            while reverse_lines > 0 and len(self.quotebook_history) > 0:
                self.reverse_book()
                reverse_lines -= 1

    def play_to_line(self, line):
        # subtract 1 because lines start at 1 not 0
        self.play_lines(line - self.curr_index - 1)

    def play_time(self, time):
        target_time = self.quotebook.last_timestamp + time
        if target_time >= self.quotebook.last_timestamp:
            while self.quotebook.last_timestamp < target_time and \
                            len(self.infile) > self.curr_index + 1:
                if target_time - self.quotebook.last_timestamp <= 5000 \
                        or self.curr_index > len(self.infile) - self.max_reverse:
                    self.process_line(save_history=True)
                else:
                    self.process_line(save_history=False)
        elif target_time < self.quotebook.last_timestamp and target_time >= 0:
            # Reverse time
            while self.quotebook.last_timestamp > target_time \
                    and len(self.quotebook_history) > 0:
                self.reverse_book()
            if self.quotebook.last_timestamp > target_time and self.curr_index > 0:
                # Play up to the line
                self.reset()
                self.play_time(target_time)

    def play_to_time(self, time):
        self.play_time(time - self.quotebook.last_timestamp)

    def get_int_value(self, message):
        dimensions = self.screen.getmaxyx()
        if len(message) < dimensions[1]:
            empty = dimensions[1] - len(message) - 2
            self.screen.addstr(dimensions[0] - 2, len(message) + 1, \
                               " " * empty, curses.A_STANDOUT)
        self.screen.addstr(dimensions[0] - 2, 1, message, curses.A_STANDOUT)
        curses.curs_set(1);
        curses.echo()  # show cursor
        value = self.screen.getstr()
        self.draw_help()
        curses.curs_set(0);
        curses.noecho()
        try:
            return int(value)
        except ValueError:
            return None

    def process_key(self, character):
        if character == self.keys['PREVIOUS']:
            self.play_lines(-1)
        elif character == self.keys['NEXT']:
            self.play_lines(1)
        elif character == self.keys['PLAY_FOR_TIME']:
            value = self.get_int_value('Milliseconds: ')
            if value != None:
                self.last_skipped = value
                self.play_time(value)
        elif character == self.keys['PLAY_TO_TIME']:
            value = self.get_int_value('Milliseconds: ')
            if value != None:
                self.play_to_time(value)
        elif character == self.keys['PLAY_FOR_LINES']:
            value = self.get_int_value('Lines: ')
            if value != None:
                self.last_skipped = value
                self.play_lines(value)
        elif character == self.keys['PLAY_TO_LINE']:
            value = self.get_int_value('Line: ')
            if value != None:
                self.play_to_line(value)
        elif character == self.keys['AGGREGATE']:
            # Toggle tier aggregation
            self.aggregate = True if self.aggregate == False else False

    def draw_book(self):
        dimensions = self.screen.getmaxyx()
        length = int(dimensions[0] - 5)
        width = int((dimensions[1] - 3) / 3)

        # Bids
        bid_win = curses.newwin(length, width, 3, 2)
        book = ''
        if self.aggregate:
            book = self.quotebook.bid_book_aggregated_str().split('\n')
        else:
            book = self.quotebook.bid_book_str().split('\n')
        for idx, line in enumerate(book):
            if idx == 0:
                bid_win.addstr(idx, 1, line, curses.A_STANDOUT)
            elif idx == length:
                break
            else:
                bid_win.addstr(idx, 1, line)
        bid_win.refresh()

        # Asks
        ask_win = curses.newwin(length, width, 3, 3 + width)
        book = ''
        if self.aggregate:
            book = self.quotebook.ask_book_aggregated_str().split('\n')
        else:
            book = self.quotebook.ask_book_str().split('\n')
        for idx, line in enumerate(book):
            if idx == 0:
                ask_win.addstr(idx, 1, line, curses.A_STANDOUT)
            elif idx == length:
                break
            else:
                ask_win.addstr(idx, 1, line)
        ask_win.refresh()

        # Trades
        trade_win = curses.newwin(length, width, 3, 3 + (width * 2) - 1)
        book = self.quotebook.trade_book_str().split('\n')
        for idx, line in enumerate(book):
            if idx == 0:
                trade_win.addstr(idx, 1, line, curses.A_STANDOUT)
            elif idx == length:
                break
            else:
                trade_win.addstr(idx, 1, line)
        trade_win.refresh()

    def draw_help(self):
        dimensions = self.screen.getmaxyx()
        self.screen.addstr(dimensions[0] - 2, 1, self.help_text, curses.A_STANDOUT)
        if len(self.help_text) < self.screen.getmaxyx()[1] - 4:
            empty = self.screen.getmaxyx()[1] - len(self.help_text) - 3
            self.screen.addstr(dimensions[0] - 2, len(self.help_text) + 1, " " * empty, \
                               curses.A_STANDOUT)

    def draw_screen(self):
        self.screen.clear()
        self.screen.border(0)
        self.screen.refresh()
        self.draw_help()

    def main(self, stdscr):
        # Draw the shortcut key bar
        self.screen = stdscr
        self.draw_screen()

        # Read the file
        self.read_file(sys.argv[1])
        self.play_lines(1)

        exit = False
        last_pressed = None
        while not exit:
            self.draw_book()

            # Print current line
            line = self.infile[self.curr_index].rstrip() + ' (line ' \
                   + str(self.curr_index + 1) + ')'
            if self.aggregate:
                line += '  [AGGREGATED VIEW]'
            dimensions = self.screen.getmaxyx()
            if len(line) < dimensions[1] - 4:
                empty = dimensions[1] - len(line) - 10
                line += (" " * empty)
            self.screen.addstr(1, 3, line.replace(',', ', '))

            # Refresh the screen
            self.screen.refresh()
            character = self.screen.getch()

            if character == curses.KEY_RESIZE:
                # Window resize
                self.draw_screen()
                self.draw_book()
            elif character == self.keys['REPEAT'] and last_pressed != None:
                if last_pressed == self.keys['PLAY_FOR_LINES']:
                    self.play_lines(self.last_skipped)
                elif last_pressed == self.keys['PLAY_FOR_TIME']:
                    self.play_time(self.last_skipped)
                else:
                    self.process_key(last_pressed)
            elif character == self.keys['EXIT']:
                exit = True
            else:
                last_pressed = character
                self.process_key(character)