<commit_before>import sys
import time
import logging
from threading import Thread
import urwid
from .leetcode import Leetcode
from views.home import HomeView
from views.detail import DetailView
from views.help import HelpView
from views.loading import *
from views.viewhelper import *
from .config import config
import auth
from .model import DetailData

palette = [
    ('body', 'dark cyan', ''),
    ('focus', 'white', ''),
    ('head', 'white', 'dark gray'),
    ('lock', 'dark gray', ''),
    ('tag', 'white', 'light cyan', 'standout'),
    ('hometag', 'dark red', '')
    ]

class Terminal(object):
    def __init__(self):
        self.home_view = None
        self.loop = None
        self.leetcode = Leetcode()
        self.help_view = None
        self.quit_confirm_view = None
        self.submit_confirm_view = None
        self.view_stack = []
        self.detail_view = None
        self.search_view = None
        self.loading_view = None
        self.logger = logging.getLogger(__name__)

    @property
    def current_view(self):
        return None if not len(self.view_stack) else self.view_stack[-1]

    @property
    def is_home(self):
        return len(self.view_stack) == 1

    def goto_view(self, view):
        self.loop.widget = view
        self.view_stack.append(view)

    def go_back(self):
        self.view_stack.pop()
        self.loop.widget = self.current_view

    def keystroke(self, key):
        if self.quit_confirm_view and self.current_view == self.quit_confirm_view:
            if key is 'y':
                raise urwid.ExitMainLoop()
            else:
                self.go_back()

        elif self.submit_confirm_view and self.current_view == self.submit_confirm_view:
            self.go_back()
            if key is 'y':
                self.send_code(self.detail_view.data)

        elif self.current_view == self.search_view:
            if key is 'enter':
                text = self.search_view.contents[1][0].original_widget.get_edit_text()
                self.home_view.handle_search(text)
                self.go_back()
            elif key is 'esc':
                self.go_back()

        elif key in ('q', 'Q'):
            self.goto_view(self.make_quit_confirmation())

        elif key is 's':
            self.goto_view(self.make_submit_confirmation())

        elif not self.is_home and (key is 'left' or key is 'h'):
            self.go_back()

        elif key is 'H':
            if not self.help_view:
                self.make_helpview()
            self.goto_view(self.help_view)

        elif key is 'R':
            if self.is_home:
                self.reload_list()

        elif key is 'f':
            if self.is_home:
                self.enter_search()

        elif key in ('enter', 'right'):
            if self.is_home and self.home_view.is_current_item_enterable():
                self.enter_detail(self.home_view.get_current_item_data())

        else:
            return key

    def enter_search(self):
        self.make_search_view()
        self.goto_view(self.search_view)

    def enter_detail(self, data):
        self.show_loading('Loading Quiz', 17, self.current_view)
        self.t = Thread(target=self.run_retrieve_detail, args=(data,))
        self.t.start()

    def reload_list(self):
        '''Press R in home view to retrieve quiz list'''
        items = self.leetcode.hard_retrieve_home()
        if items:
            self.home_view = self.make_listview(items)
            self.view_stack = []
            self.goto_view(self.home_view)

    def make_quit_confirmation(self):
        text = urwid.AttrMap(urwid.Text('Do you really want to quit ? (y/n)'), 'body')
        self.quit_confirm_view = urwid.Overlay(text, self.current_view, 'left',
                                               ('relative', 100), 'bottom', None)
        return self.quit_confirm_view

    def make_submit_confirmation(self):
        text = urwid.AttrMap(urwid.Text('Do you want to submit your code ? (y/n)'), 'body')
        self.submit_confirm_view = urwid.Overlay(text, self.current_view, 'left',
                                               ('relative', 100), 'bottom', None)
        return self.submit_confirm_view

    def make_search_view(self):
        text = urwid.AttrMap(urwid.Edit('Search by id: ', ''), 'body')
        self.search_view = urwid.Overlay(text, self.current_view, 'left',
                                               ('relative', 100), 'bottom', None)
        return self.search_view

    def make_detailview(self, data):
        self.detail_view = DetailView(data, self.leetcode, self.loop)
        return self.detail_view

    def make_listview(self, data):
        header = self.make_header()
        self.home_view = HomeView(data, header)
        return self.home_view

    def make_header(self):
        if self.leetcode.is_login:
            columns = [
                ('fixed', 15, urwid.Padding(urwid.AttrWrap(
                    urwid.Text('%s' % config.username),
                    'head', ''))),
                urwid.AttrWrap(urwid.Text('You have solved %d / %d problems. ' %
                    (len(self.leetcode.solved), len(self.leetcode.items))), 'head', ''),
            ]
            return urwid.Columns(columns)
        else:
            text = urwid.AttrWrap(urwid.Text('Not login'), 'head')
        return text

    def make_helpview(self):
        self.help_view = HelpView()
        return self.help_view

    def show_loading(self, text, width, host_view=urwid.SolidFill()):
        self.loading_view = LoadingView(text, width, host_view, self.loop)
        self.loop.widget = self.loading_view
        self.loading_view.start()

    def end_loading(self):
        if self.loading_view:
            self.loading_view.end()
            self.loading_view = None

    def retrieve_home_done(self, data):
        self.home_view = self.make_listview(data)
        self.view_stack = []
        self.goto_view(self.home_view)
        self.end_loading()
        delay_refresh(self.loop)

    def retrieve_detail_done(self, data):
        data.quizid = self.home_view.listbox.get_focus()[0].data.id
        data.url = self.home_view.listbox.get_focus()[0].data.url
        self.goto_view(self.make_detailview(data))
        self.end_loading()
        delay_refresh(self.loop)

    def run_retrieve_home(self):
        self.leetcode.is_login = auth.is_login()
        if not self.leetcode.is_login:
            self.leetcode.is_login = auth.login()

        if self.loading_view:
            self.loading_view.set_text('Loading')
        data = self.leetcode.hard_retrieve_home()
        if data:
            self.retrieve_home_done(data)
        else:
            self.end_loading()
            toast = Toast('Request fail!', 10, self.current_view, self.loop)
            toast.show()
            self.logger.error('get quiz list fail')

    def run_retrieve_detail(self, data):
        ret = self.leetcode.retrieve_detail(data)
        if ret:
            self.retrieve_detail_done(ret)
        else:<commit_msg>fix bug not asign data to detaildata.id<commit_after>import sys
import time
import logging
from threading import Thread
import urwid
from .leetcode import Leetcode
from views.home import HomeView
from views.detail import DetailView
from views.help import HelpView
from views.loading import *
from views.viewhelper import *
from .config import config
import auth
from .model import DetailData

palette = [
    ('body', 'dark cyan', ''),
    ('focus', 'white', ''),
    ('head', 'white', 'dark gray'),
    ('lock', 'dark gray', ''),
    ('tag', 'white', 'light cyan', 'standout'),
    ('hometag', 'dark red', '')
    ]

class Terminal(object):
    def __init__(self):
        self.home_view = None
        self.loop = None
        self.leetcode = Leetcode()
        self.help_view = None
        self.quit_confirm_view = None
        self.submit_confirm_view = None
        self.view_stack = []
        self.detail_view = None
        self.search_view = None
        self.loading_view = None
        self.logger = logging.getLogger(__name__)

    @property
    def current_view(self):
        return None if not len(self.view_stack) else self.view_stack[-1]

    @property
    def is_home(self):
        return len(self.view_stack) == 1

    def goto_view(self, view):
        self.loop.widget = view
        self.view_stack.append(view)

    def go_back(self):
        self.view_stack.pop()
        self.loop.widget = self.current_view

    def keystroke(self, key):
        if self.quit_confirm_view and self.current_view == self.quit_confirm_view:
            if key is 'y':
                raise urwid.ExitMainLoop()
            else:
                self.go_back()

        elif self.submit_confirm_view and self.current_view == self.submit_confirm_view:
            self.go_back()
            if key is 'y':
                self.send_code(self.detail_view.data)

        elif self.current_view == self.search_view:
            if key is 'enter':
                text = self.search_view.contents[1][0].original_widget.get_edit_text()
                self.home_view.handle_search(text)
                self.go_back()
            elif key is 'esc':
                self.go_back()

        elif key in ('q', 'Q'):
            self.goto_view(self.make_quit_confirmation())

        elif key is 's':
            self.goto_view(self.make_submit_confirmation())

        elif not self.is_home and (key is 'left' or key is 'h'):
            self.go_back()

        elif key is 'H':
            if not self.help_view:
                self.make_helpview()
            self.goto_view(self.help_view)

        elif key is 'R':
            if self.is_home:
                self.reload_list()

        elif key is 'f':
            if self.is_home:
                self.enter_search()

        elif key in ('enter', 'right'):
            if self.is_home and self.home_view.is_current_item_enterable():
                self.enter_detail(self.home_view.get_current_item_data())

        else:
            return key

    def enter_search(self):
        self.make_search_view()
        self.goto_view(self.search_view)

    def enter_detail(self, data):
        self.show_loading('Loading Quiz', 17, self.current_view)
        self.t = Thread(target=self.run_retrieve_detail, args=(data,))
        self.t.start()

    def reload_list(self):
        '''Press R in home view to retrieve quiz list'''
        items = self.leetcode.hard_retrieve_home()
        if items:
            self.home_view = self.make_listview(items)
            self.view_stack = []
            self.goto_view(self.home_view)

    def make_quit_confirmation(self):
        text = urwid.AttrMap(urwid.Text('Do you really want to quit ? (y/n)'), 'body')
        self.quit_confirm_view = urwid.Overlay(text, self.current_view, 'left',
                                               ('relative', 100), 'bottom', None)
        return self.quit_confirm_view

    def make_submit_confirmation(self):
        text = urwid.AttrMap(urwid.Text('Do you want to submit your code ? (y/n)'), 'body')
        self.submit_confirm_view = urwid.Overlay(text, self.current_view, 'left',
                                               ('relative', 100), 'bottom', None)
        return self.submit_confirm_view

    def make_search_view(self):
        text = urwid.AttrMap(urwid.Edit('Search by id: ', ''), 'body')
        self.search_view = urwid.Overlay(text, self.current_view, 'left',
                                               ('relative', 100), 'bottom', None)
        return self.search_view

    def make_detailview(self, data):
        self.detail_view = DetailView(data, self.leetcode, self.loop)
        return self.detail_view

    def make_listview(self, data):
        header = self.make_header()
        self.home_view = HomeView(data, header)
        return self.home_view

    def make_header(self):
        if self.leetcode.is_login:
            columns = [
                ('fixed', 15, urwid.Padding(urwid.AttrWrap(
                    urwid.Text('%s' % config.username),
                    'head', ''))),
                urwid.AttrWrap(urwid.Text('You have solved %d / %d problems. ' %
                    (len(self.leetcode.solved), len(self.leetcode.items))), 'head', ''),
            ]
            return urwid.Columns(columns)
        else:
            text = urwid.AttrWrap(urwid.Text('Not login'), 'head')
        return text

    def make_helpview(self):
        self.help_view = HelpView()
        return self.help_view

    def show_loading(self, text, width, host_view=urwid.SolidFill()):
        self.loading_view = LoadingView(text, width, host_view, self.loop)
        self.loop.widget = self.loading_view
        self.loading_view.start()

    def end_loading(self):
        if self.loading_view:
            self.loading_view.end()
            self.loading_view = None

    def retrieve_home_done(self, data):
        self.home_view = self.make_listview(data)
        self.view_stack = []
        self.goto_view(self.home_view)
        self.end_loading()
        delay_refresh(self.loop)

    def retrieve_detail_done(self, data):
        data.id = self.home_view.listbox.get_focus()[0].data.id
        data.url = self.home_view.listbox.get_focus()[0].data.url
        self.goto_view(self.make_detailview(data))
        self.end_loading()
        delay_refresh(self.loop)

    def run_retrieve_home(self):
        self.leetcode.is_login = auth.is_login()
        if not self.leetcode.is_login:
            self.leetcode.is_login = auth.login()

        if self.loading_view:
            self.loading_view.set_text('Loading')
        data = self.leetcode.hard_retrieve_home()
        if data:
            self.retrieve_home_done(data)
        else:
            self.end_loading()
            toast = Toast('Request fail!', 10, self.current_view, self.loop)
            toast.show()
            self.logger.error('get quiz list fail')

    def run_retrieve_detail(self, data):
        ret = self.leetcode.retrieve_detail(data)
        if ret:
            self.retrieve_detail_done(ret)
        else:
{'fraction_non_alphanumeric': 0.11165392240158595, 'fraction_numerical': 0.002973661852166525, 'mean_word_length': 2.086756993006993, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 12, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1835071', 'n_tokens_mistral': 4359, 'n_tokens_neox': 4206, 'n_words': 895}