Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I get the amount of time for which a key is pressed on a keyboard

I am working on a project in which I have to develop bio-passwords based on user's keystroke style. Suppose a user types a password for 20 times, his keystrokes are recorded, like

holdtime : time for which a particular key is pressed. digraph time : time it takes to press a different key.

suppose a user types a password " COMPUTER". I need to know the time for which every key is pressed. something like :

holdtime for the above password is

C-- 200ms O-- 130ms M-- 150ms P-- 175ms U-- 320ms T-- 230ms E-- 120ms R-- 300ms

The rational behind this is , every user will have a different holdtime. Say a old person is typing the password, he will take more time then a student. And it will be unique to a particular person. To do this project, I need to record the time for each key pressed. I would greatly appreciate if anyone can guide me in how to get these times.

Editing from here.. Language is not important, but I would prefer it in C. I am more interested in getting the dataset.

like image 908
Adi Avatar asked Dec 22 '22 03:12

Adi


2 Answers

Record the KeyDown and KeyUp events, and do a diff on the timestamps of each.

http://code.activestate.com/recipes/203830/

Edit: You may want to check out wxPython, it should help you out:

http://www.wxpython.org/onlinedocs.php

in particular:

http://docs.wxwidgets.org/stable/wx_wxkeyevent.html#wxkeyevent

like image 105
jvenema Avatar answered Dec 27 '22 06:12

jvenema


You mentioned you'd prefer it in C, but since you tagged it Python... :)

Also, since you say you're looking for building a dataset, I assume you'll have to invite users to type in arbitrary text, so you'll need some sort of interface (graphical or otherwise).

Here's a quick example using pygame. You can trivially modify it to ask users to type specific words, but, as it is, it'll just let the user type in arbitrary text, record pressing times for all keypresses, and print each hold and digraph times, in the order that the user typed it, when it exits (i.e., when the user presses Esc).

As Kibibu noticed, showing the user what he's typing in realtime introduces a delay which might mask real key-pressing times, so this code only displays what the user has typed when he types "Enter".

Update: it now calculates digraph as well as hold times (excluding Enter in both cases).

Update2: Per Adi's request, changed from displaying average to displaying each individual time, in order.

import sys
from collections import defaultdict
from time import time
import pygame
from pygame.key import name as keyname
from pygame.locals import *

# Mapping of a key to a list of holdtimes (from which you can average, etc)
holdtimes = defaultdict(list)
# Mapping of a key pair to a list of digraph times
digraphs = defaultdict(list)
# Keys which have been pressed down, but not up yet.
pending = {}
# Last key to be de-pressed, corresponding time).
last_key = None
# Text that the user has typed so far (one sublist for every Enter pressed)
typed_text = [[]]

def show_times():
    all_text = [k for line in typed_text for k in line]
    print "Holdtimes:"
    for key in all_text:
        print "%s: %.5f" % (key, holdtimes[key].pop(0))

    print "Digraphs:"
    for key1, key2 in zip(all_text, all_text[1:]):
        print "(%s, %s): %.5f" % (key1, key2,
                                  digraphs[(key1, key2)].pop(0))

def time_keypresses(events):
    global last_key
    for event in events:
        if event.type == KEYDOWN:
            # ESC exits the program
            if event.key == K_ESCAPE:
                show_times()
                sys.exit(0)

            t = pending[event.key] = time()
            if last_key is not None:
                if event.key != K_RETURN:
                    digraphs[(last_key[0], keyname(event.key))].append(t - last_key[1])
                last_key = None
        elif event.type == KEYUP:
            if event.key == K_RETURN:
                update_screen()
                typed_text.append([])
                pending.pop(event.key)
                last_key = None
            else:
                t = time()
                holdtimes[keyname(event.key)].append(t - pending.pop(event.key))
                last_key = [keyname(event.key), t]
                typed_text[-1].append(keyname(event.key))
        # Any other event handling you might have would go here...

def update_screen():
    global screen
    screen.fill((255, 255, 255))

    header_font = pygame.font.Font(None, 42)
    header = header_font.render("Type away! Press 'Enter' to show.", True, (0, 0, 0))
    header_rect = header.get_rect()
    header_rect.centerx = screen.get_rect().centerx
    header_rect.centery = screen.get_rect().centery - 100

    text_font = pygame.font.Font(None, 32)
    user_text = text_font.render("".join(typed_text[-1]) if typed_text[-1] else "...",
                                 True, (0, 0, 255))
    text_rect = user_text.get_rect()
    text_rect.centerx = screen.get_rect().centerx
    text_rect.centery = screen.get_rect().centery    

    screen.blit(header, header_rect)
    screen.blit(user_text, text_rect)

    pygame.display.update()


if __name__ == '__main__':
    pygame.init()
    window = pygame.display.set_mode((800, 600))
    screen = pygame.display.get_surface()
    update_screen()
    while True:
        time_keypresses(pygame.event.get())
like image 38
rbp Avatar answered Dec 27 '22 07:12

rbp