Beispiel #1
0
    def _get_track_map(self, track_type, session=False):
        """Return dictionary of tracks along with top resolution and range of values.
        
        TODO: Test sum of arrays vs length of arrays to get top resolution
        """
        start_time = self['Ticks']['Session'][track_type] if session else 0

        top_resolution = None
        max_records = 0
        min_value = float('inf')
        max_value = -float('inf')
        result = {}
        for resolution, maps in get_items(self['Resolution']):
            array = numpy.max(maps[track_type] - start_time, 0)
            num_records = numpy.count(array)
            if num_records:
                result[resolution] = array

                #Find resolution with most data
                if num_records > max_records:
                    max_records = num_records
                    top_resolution = resolution

                #Find the highest and lowest recorded values
                min_value = min(min_value, numpy.min(array))
                max_value = max(max_value, numpy.max(array))

        if not result:
            return None

        return top_resolution, (int(min_value), int(max_value)), result
Beispiel #2
0
    def _iterate(self, maps, command, extra=None):
        for key in maps.keys():

            if isinstance(key, str):
                self._iterate(maps[key], command, extra)

            elif command == 'separate':
                array = maps[key]
                maps[key] = len(self._map_list)
                self._map_list.append(array)

            elif command == 'join':
                index = maps[key]
                maps[key] = extra[index]

            elif command == 'convert':
                array = maps[key]
                width, height = key
                numpy_array = numpy.array((width, height),
                                          create=True,
                                          dtype='int64')
                for x, y in array:
                    numpy_array[y][x] = array[(x, y)]
                maps[key] = numpy_array

            elif command == 'trim':
                if key == (0, 0):
                    del maps[key]
                #Delete any empty maps
                #Disabled for now as groups currently need each resolution to exist
                if False and not numpy.count(maps[key]):
                    del maps[key]
Beispiel #3
0
    def get_clicks(self, double_click=False, session=False):
        session = 'Session' if session else 'All'
        click_type = 'Double' if double_click else 'Single'

        top_resolution = None
        max_records = 0
        min_value = float('inf')
        max_value = -float('inf')
        result = {}
        for resolution, maps in get_items(self['Resolution']):
            click_maps = (maps['Clicks'][session][click_type]['Left'],
                          maps['Clicks'][session][click_type]['Middle'],
                          maps['Clicks'][session][click_type]['Right'])

            #Get information on array
            contains_data = False
            for array in click_maps:
                num_records = numpy.count(array)
                if num_records:
                    contains_data = True

                #Find resolution with most data
                if num_records > max_records:
                    max_records = num_records
                    top_resolution = resolution

                #Find the highest and lowest recorded values
                min_value = min(min_value, numpy.min(array))
                max_value = max(max_value, numpy.max(array))

            if contains_data:
                result[resolution] = click_maps

        if not result:
            return None

        return top_resolution, (int(min_value), int(max_value)), result
Beispiel #4
0
    def _generate(self, resolution, data):

        if numpy.count(data) < CONFIG['GenerateCSV']['MinimumPoints']:
            return None
        output = numpy.set_type(data, str)
        return '\n'.join(','.join(row) for row in output)
Beispiel #5
0
def background_process(q_recv, q_send):
    """Function to handle all the data from the main thread."""
    try:
        NOTIFY(START_THREAD)
        NOTIFY.send(q_send)
        
        store = {'Data': load_data(),
                 'LastProgram': None,
                 'Resolution': None,
                 'ResolutionTemp': None,
                 'Offset': (0, 0),
                 'LastResolution': None,
                 'ActivitySinceLastSave': False,
                 'SavesSkipped': 0,
                 'CustomResolution': None,
                 'LastClick': None,
                 'KeyTrack': {'LastKey': None,
                              'Time': None,
                              'Backspace': False}
                }
        
        NOTIFY(DATA_LOADED)
        try:
            NOTIFY(QUEUE_SIZE, q_recv.qsize())
        except NotImplementedError:
            pass
        NOTIFY.send(q_send)
        
        while True:
            received_data = q_recv.get()
            
            check_resolution = False
            
            #Increment the amount of time the script has been running for
            if 'Ticks' in received_data:
                store['Data']['Ticks']['Total'] += received_data['Ticks']
            
            #Save the data
            if 'Save' in received_data:
                if store['ActivitySinceLastSave']:
                    _save_wrapper(q_send, store['LastProgram'], store['Data'], False)
                    store['ActivitySinceLastSave'] = False
                    store['SavesSkipped'] = 0
                    
                    try:
                        NOTIFY(QUEUE_SIZE, q_recv.qsize())
                    except NotImplementedError:
                        pass
                else:
                    store['SavesSkipped'] += 1
                    
                    try:
                        NOTIFY(SAVE_SKIP, CONFIG['Save']['Frequency'] * store['SavesSkipped'], q_recv.qsize())
                    except NotImplementedError:
                        pass
                q_send.put({'SaveFinished': None})
            
            #Check for new program loaded
            if 'Program' in received_data:
                current_program = received_data['Program']
                
                if current_program != store['LastProgram']:
                    
                    if current_program is None:
                        NOTIFY(APPLICATION_LOADING)
                    else:
                        NOTIFY(APPLICATION_LOADING, current_program)
                    NOTIFY.send(q_send)
                    
                    #Save old profile
                    _save_wrapper(q_send, store['LastProgram'], store['Data'], True)
                    
                    #Load new profile
                    store['LastProgram'] = current_program
                    store['Data'] = load_data(current_program)
                    store['ActivitySinceLastSave'] = False
                    
                    #Check new resolution
                    try:
                        store['CustomResolution'] = received_data['CustomResolution']
                    except AttributeError:
                        pass
                    if store['CustomResolution'] is None:
                        _check_resolution(store['Data']['Maps'], store['Resolution'])
                    else:
                        _check_resolution(store['Data']['Maps'], store['CustomResolution'][1])
                        
                    if store['Data']['Ticks']['Total']:
                        NOTIFY(DATA_LOADED)
                    else:
                        NOTIFY(DATA_NOTFOUND)
                    
                    try:
                        NOTIFY(QUEUE_SIZE, q_recv.qsize())
                    except NotImplementedError:
                        pass
                NOTIFY.send(q_send)
            
            if 'CustomResolution' in received_data:
                store['CustomResolution'] = received_data['CustomResolution']
                if store['CustomResolution'] is not None:
                    _check_resolution(store['Data']['Maps'], store['CustomResolution'][1])

            if 'Resolution' in received_data:
                store['Resolution'] = received_data['Resolution']
                _check_resolution(store['Data']['Maps'], store['Resolution'])
            
            if 'MonitorLimits' in received_data:
                store['ResolutionTemp'] = received_data['MonitorLimits']
            
            #Record key presses
            if 'KeyPress' in received_data:
                store['ActivitySinceLastSave'] = True
                
                for key in received_data['KeyPress']:
                
                    _record_keypress(store['Data']['Keys'], 'Pressed', key)
                    
                    #Record mistakes
                    if key == 'BACK':
                        last = store['KeyTrack']['LastKey']
                        if last is not None and last != 'BACK':
                            store['KeyTrack']['Backspace'] = last
                        else:
                            store['KeyTrack']['Backspace'] = False
                    elif store['KeyTrack']['Backspace']:
                        _record_keypress(store['Data']['Keys'], 'Mistakes', store['KeyTrack']['Backspace'], key)
                        store['KeyTrack']['Backspace'] = False
                    
                    #Record interval between key presses
                    if store['KeyTrack']['Time'] is not None:
                        time_difference = store['Data']['Ticks']['Total'] - store['KeyTrack']['Time']
                        _record_keypress(store['Data']['Keys'], 'Intervals', 'Total', time_difference)
                        _record_keypress(store['Data']['Keys'], 'Intervals', 'Individual', store['KeyTrack']['LastKey'], key, time_difference)
                    
                    store['KeyTrack']['LastKey'] = key
                    store['KeyTrack']['Time'] = store['Data']['Ticks']['Total']
            
            #Record time keys are held down
            if 'KeyHeld' in received_data:
                store['ActivitySinceLastSave'] = True
                
                for key in received_data['KeyHeld']:
                    _record_keypress(store['Data']['Keys'], 'Held', key)
            
            #Calculate and track mouse movement
            if 'MouseMove' in received_data:
                store['ActivitySinceLastSave'] = True
                resolution = 0
                _resolution = -1
                
                start, end = received_data['MouseMove']
                #distance = find_distance(end, start)
                
                #Calculate the pixels in the line
                if end is None:
                    raise TypeError('debug - mouse moved without coordinates')
                if start is None:
                    mouse_coordinates = [end]
                else:
                    mouse_coordinates = [start] + calculate_line(start, end) + [end]
                    
                #Make sure resolution exists in data
                if store['CustomResolution'] is not None:
                    _check_resolution(store['Data']['Maps'], store['CustomResolution'][1])
                    
                elif MULTI_MONITOR:
                    try:
                        #Don't bother calculating offset for each pixel
                        #if both start and end are on the same monitor
                        resolution, (x_offset, y_offset) = monitor_offset(start, store['ResolutionTemp'])
                        _resolution = monitor_offset(end, store['ResolutionTemp'])[0]
                    except TypeError:
                        if not resolution:
                            mouse_coordinates = [] 
                    else:
                        _check_resolution(store['Data']['Maps'], resolution)
                        if resolution != _resolution:
                            _check_resolution(store['Data']['Maps'], resolution)
                        _resolutions = [resolution, _resolution]
                        
                #Write each pixel to the dictionary
                for (x, y) in mouse_coordinates:
                
                    try:
                        (x, y), resolution = _find_resolution_offset(x, y, store)
                    except TypeError:
                        continue
                        
                    store['Data']['Maps']['Tracks'][resolution][y][x] = store['Data']['Ticks']['Tracks']
                        
                store['Data']['Ticks']['Tracks'] += 1
                
                #Compress tracks if the count gets too high
                max_track_value = CONFIG['Advanced']['CompressTrackMax']
                if not max_track_value:
                    max_track_value = MAX_INT
                if store['Data']['Ticks']['Tracks'] > max_track_value:
                    compress_multplier = CONFIG['Advanced']['CompressTrackAmount']
                    NOTIFY(TRACK_COMPRESS_START, 'track')
                    NOTIFY.send(q_send)
                    
                    tracks = store['Data']['Maps']['Tracks']
                    for resolution in tracks.keys():
                        tracks[resolution] = numpy.divide(tracks[resolution], compress_multplier, as_int=True)
                        if not numpy.count(tracks[resolution]):
                            del tracks[resolution]
                            
                    NOTIFY(TRACK_COMPRESS_END, 'track')
                    try:
                        NOTIFY(QUEUE_SIZE, q_recv.qsize())
                    except NotImplementedError:
                        pass
                        
                    store['Data']['Ticks']['Tracks'] //= compress_multplier
                    store['Data']['Ticks']['Session']['Tracks'] //= compress_multplier
                    store['Data']['Ticks']['Tracks'] = int(store['Data']['Ticks']['Tracks'])
                    store['Data']['Ticks']['Session']['Tracks'] = int(store['Data']['Ticks']['Session']['Tracks'])
                
            #Record mouse clicks
            if 'MouseClick' in received_data:
                store['ActivitySinceLastSave'] = True
                
                for mouse_button_index, (x, y) in received_data['MouseClick']:
                    
                    try:
                        (x, y), resolution = _find_resolution_offset(x, y, store)
                    except TypeError:
                        continue
                    
                    mouse_button = ['Left', 'Middle', 'Right'][mouse_button_index]
                    store['Data']['Maps']['Click']['Single'][mouse_button][resolution][y][x] += 1
                    store['Data']['Maps']['Session']['Click']['Single'][mouse_button][resolution][y][x] += 1
                    
            #Record double clicks
            if 'DoubleClick' in received_data:
                store['ActivitySinceLastSave'] = True
                
                for mouse_button_index, (x, y) in received_data['DoubleClick']:
                                            
                    try:
                        (x, y), resolution = _find_resolution_offset(x, y, store)
                    except TypeError:
                        continue
                    
                    mouse_button = ['Left', 'Middle', 'Right'][mouse_button_index]
                    store['Data']['Maps']['Click']['Double'][mouse_button][resolution][y][x] += 1
                    store['Data']['Maps']['Session']['Click']['Double'][mouse_button][resolution][y][x] += 1
                
            store['Data']['Ticks']['Recorded'] += 1
            
            if 'Quit' in received_data or 'Exit' in received_data:
                break

            NOTIFY.send(q_send)
        
        #Exit process (this shouldn't happen for now)
        NOTIFY(THREAD_EXIT)
        NOTIFY.send(q_send)
        _save_wrapper(q_send, store['LastProgram'], store['Data'], False)
            
    except Exception as e:
        q_send.put(traceback.format_exc())
        
    except KeyboardInterrupt:
        pass