<commit_before>#!/usr/bin/python3
# -*- coding: utf-8

import curses
from functools import partial
import itertools
import json
import os
import signal
import sys
import time

from freecell import *

class Stats(object):

    def __init__(self, cfg):
        self.games_played = cfg.get('games', 0)
        self.games_won = cfg.get('won', 0)
        self.total_time = cfg.get('total_time', 0)
        self.lowest_time = cfg.get('lowest_time', 0)
        self.highest_time = cfg.get('highest_time', 0)

    def add_game(self):
        self.games_played += 1

    def add_game_won(self, t):
        self.games_played += 1
        self.games_won += 1
        self.total_time += t
        if self.lowest_time == 0 or t < self.lowest_time:
            self.lowest_time = t
        if t > self.highest_time:
            self.highest_time = t

    def get_average_time(self):
        if self.games_won == 0:
            return 0
        return self.total_time // self.games_won

    def get_win_rate(self):
        if self.games_played == 0:
            return 0
        return self.games_won * 100 // self.games_played

    def clear(self):
        self.games_played = 0
        self.games_won = 0
        self.total_time = 0
        self.lowest_time = 0
        self.highest_time = 0

    def save(self):
        return {
            'games': self.games_played,
            'won': self.games_won,
            'total_time': self.total_time,
            'lowest_time': self.lowest_time,
            'highest_time': self.highest_time,
        }

class FreeCellGame(object):

    STATS_FILE = '~/.config/mur-freecell/stats.cfg'

    def __init__(self, stdscr):
        self.stdscr = stdscr
        self.action_display = []
        self.action_input = []
        self.action_keys = set()
        # Grabs input; returns True to keep grabbing
        self.grab_input_callback = None
        self.locate_match = None
        self.message = None
        self.message_timeout = None
        self.paused = False
        self.pause_draw_callback = None
        self.queue_redraw = True
        self.quit = False
        self.stats = Stats(self.load_config(self.STATS_FILE))
        self.stopped = False
        self.try_sweep = False
        self.undo_list = []
        self.undo_index = None

    def repr_card(self, c):
        '''
        Returns a two-tuple (card string, curses attr)
        '''
        attr = 0
        if c.color == 'red':
            attr = curses.color_pair(1)
        if self.highlight(c):
            attr |= curses.A_REVERSE
        return '{} {:>2}'.format(c.face_char, c.name), attr

    def repr_stack(self, s):
        attr = 0
        c = s.top()
        if c.color == 'red':
            attr = curses.color_pair(1)
        if any(self.highlight(i) for i in s):
            attr |= curses.A_REVERSE
        return '{} {:>2}'.format(c.face_char, c.name), attr

    def grab_input(self, cb, force = False):
        if not force and self.grab_input_callback is not None:
            raise Exception('Input is already grabbed')
        self.grab_input_callback = cb

    def prompt_confirmation(self, msg, cb):
        self.set_message(msg + ' (y/n)', None)
        self.grab_input(partial(self.confirm_callback, cb = cb))

    def confirm_callback(self, ch, cb):
        if ch == ord('y'):
            cb()
        self.clear_message()
        return False

    def clear_message(self):
        self.message = None
        self.message_timeout = None
        self.queue_redraw = True

    def set_message(self, msg, timeout = 1):
        self.message = msg
        if timeout:
            self.message_timeout = time.time() + timeout
        self.queue_redraw = True

    def draw(self):
        win = self.stdscr

        y, x = win.getmaxyx()
        win.clear()

        self.draw_title(y, x)
        self.draw_clock(y, x)

        if self.paused:
            self.draw_pause(y, x)
        elif self.stopped:
            self.draw_stopped(y, x)
        else:
            self.draw_field(y, x)

        self.draw_message(y, x)
        self.refresh()

    def draw_field(self, y, x):
        fc = self.freecell
        win = self.stdscr
<commit_msg>Fix message display without timeout<commit_after>#!/usr/bin/python3
# -*- coding: utf-8

import curses
from functools import partial
import itertools
import json
import os
import signal
import sys
import time

from freecell import *

class Stats(object):

    def __init__(self, cfg):
        self.games_played = cfg.get('games', 0)
        self.games_won = cfg.get('won', 0)
        self.total_time = cfg.get('total_time', 0)
        self.lowest_time = cfg.get('lowest_time', 0)
        self.highest_time = cfg.get('highest_time', 0)

    def add_game(self):
        self.games_played += 1

    def add_game_won(self, t):
        self.games_played += 1
        self.games_won += 1
        self.total_time += t
        if self.lowest_time == 0 or t < self.lowest_time:
            self.lowest_time = t
        if t > self.highest_time:
            self.highest_time = t

    def get_average_time(self):
        if self.games_won == 0:
            return 0
        return self.total_time // self.games_won

    def get_win_rate(self):
        if self.games_played == 0:
            return 0
        return self.games_won * 100 // self.games_played

    def clear(self):
        self.games_played = 0
        self.games_won = 0
        self.total_time = 0
        self.lowest_time = 0
        self.highest_time = 0

    def save(self):
        return {
            'games': self.games_played,
            'won': self.games_won,
            'total_time': self.total_time,
            'lowest_time': self.lowest_time,
            'highest_time': self.highest_time,
        }

class FreeCellGame(object):

    STATS_FILE = '~/.config/mur-freecell/stats.cfg'

    def __init__(self, stdscr):
        self.stdscr = stdscr
        self.action_display = []
        self.action_input = []
        self.action_keys = set()
        # Grabs input; returns True to keep grabbing
        self.grab_input_callback = None
        self.locate_match = None
        self.message = None
        self.message_timeout = None
        self.paused = False
        self.pause_draw_callback = None
        self.queue_redraw = True
        self.quit = False
        self.stats = Stats(self.load_config(self.STATS_FILE))
        self.stopped = False
        self.try_sweep = False
        self.undo_list = []
        self.undo_index = None

    def repr_card(self, c):
        '''
        Returns a two-tuple (card string, curses attr)
        '''
        attr = 0
        if c.color == 'red':
            attr = curses.color_pair(1)
        if self.highlight(c):
            attr |= curses.A_REVERSE
        return '{} {:>2}'.format(c.face_char, c.name), attr

    def repr_stack(self, s):
        attr = 0
        c = s.top()
        if c.color == 'red':
            attr = curses.color_pair(1)
        if any(self.highlight(i) for i in s):
            attr |= curses.A_REVERSE
        return '{} {:>2}'.format(c.face_char, c.name), attr

    def grab_input(self, cb, force = False):
        if not force and self.grab_input_callback is not None:
            raise Exception('Input is already grabbed')
        self.grab_input_callback = cb

    def prompt_confirmation(self, msg, cb):
        self.set_message(msg + ' (y/n)', None)
        self.grab_input(partial(self.confirm_callback, cb = cb))

    def confirm_callback(self, ch, cb):
        if ch == ord('y'):
            cb()
        self.clear_message()
        return False

    def clear_message(self):
        self.message = None
        self.message_timeout = None
        self.queue_redraw = True

    def set_message(self, msg, timeout = 1):
        self.message = msg
        if timeout is None:
            self.message_timeout = None
        else:
            self.message_timeout = time.time() + timeout
        self.queue_redraw = True

    def draw(self):
        win = self.stdscr

        y, x = win.getmaxyx()
        win.clear()

        self.draw_title(y, x)
        self.draw_clock(y, x)

        if self.paused:
            self.draw_pause(y, x)
        elif self.stopped:
            self.draw_stopped(y, x)
        else:
            self.draw_field(y, x)

        self.draw_message(y, x)
        self.refresh()

    def draw_field(self, y, x):
        fc = self.freecell
        win = self.stdscr

{'fraction_non_alphanumeric': 0.10758440323347598, 'fraction_numerical': 0.007132667617689016, 'mean_word_length': 1.879192334017796, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7596743', 'n_tokens_mistral': 2832, 'n_tokens_neox': 2631, 'n_words': 623}