Skip to content

Commit

Permalink
Revert "resolved #103"
Browse files Browse the repository at this point in the history
This reverts commit b7c9937.
  • Loading branch information
0dm committed May 10, 2023
1 parent b7c9937 commit 659b9d7
Show file tree
Hide file tree
Showing 14 changed files with 147 additions and 171 deletions.
14 changes: 7 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,12 +92,12 @@ More ReplayStrategies coming soon! (see [Contributing](#Contributing)).

Our goal is to automate the task described and demonstrated in a `Recording`.
That is, given a new `Screenshot`, we want to generate the appropriate
`Action`(s) based on the previously recorded `Action`s in order to
`InputEvent`(s) based on the previously recorded `InputEvent`s in order to
accomplish the task specified in the `Recording.task_description`, while
accounting for differences in screen resolution, window size, application
behavior, etc.

If it's not clear what `Action` is appropriate for the given `Screenshot`,
If it's not clear what `InputEvent` is appropriate for the given `Screenshot`,
(e.g. if the GUI application is behaving in a way we haven't seen before),
we can ask the user to take over temporarily to demonstrate the appropriate
course of action.
Expand All @@ -107,9 +107,9 @@ course of action.
The dataset consists of the following entities:
1. `Recording`: Contains information about the screen dimensions, platform, and
other metadata.
2. `Action`: Represents a user input event such as a mouse click or key
press. Each `Action` has an associated `Screenshot` taken immediately
before the event occurred. `Action`s are aggregated to remove
2. `InputEvent`: Represents a user input event such as a mouse click or key
press. Each `InputEvent` has an associated `Screenshot` taken immediately
before the event occurred. `InputEvent`s are aggregated to remove
unnecessary events (see [visualize](#visualize).)
3. `Screenshot`: Contains the PNG data of a screenshot taken during the
recording.
Expand All @@ -119,7 +119,7 @@ The dataset consists of the following entities:
You can assume that you have access to the following functions:
- `create_recording("doing taxes")`: Creates a recording.
- `get_latest_recording()`: Gets the latest recording.
- `get_events(recording)`: Returns a list of `Action` objects for the given
- `get_events(recording)`: Returns a list of `InputEvent` objects for the given
recording.

### Instructions
Expand All @@ -142,7 +142,7 @@ feedback and iterate on the approach.
Your submission will be evaluated based on the following criteria:

1. **Functionality** : Your implementation should correctly generate the new
`Action` objects that can be replayed in order to accomplish the task in
`InputEvent` objects that can be replayed in order to accomplish the task in
the original recording.

2. **Code Quality** : Your code should be well-structured, clean, and easy to
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
"""add Recording; Action; ScreenShot; WindowEvent
"""add Recording; InputEvent; ScreenShot; WindowEvent
Revision ID: b206c80f7640
Revises:
Expand Down
24 changes: 0 additions & 24 deletions alembic/versions/c4e73dc5200e_rename_input_event_to_action.py

This file was deleted.

12 changes: 6 additions & 6 deletions puterbot/crud.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@
import sqlalchemy as sa

from puterbot.db import Session
from puterbot.models import Action, Screenshot, Recording, WindowEvent
from puterbot.models import InputEvent, Screenshot, Recording, WindowEvent


BATCH_SIZE = 1

db = Session()
actions = []
input_events = []
screenshots = []
window_events = []

Expand Down Expand Up @@ -42,13 +42,13 @@ def _insert(event_data, table, buffer=None):
return result


def insert_action(recording_timestamp, event_timestamp, event_data):
def insert_input_event(recording_timestamp, event_timestamp, event_data):
event_data = {
**event_data,
"timestamp": event_timestamp,
"recording_timestamp": recording_timestamp,
}
_insert(event_data, Action, actions)
_insert(event_data, InputEvent, input_events)


def insert_screenshot(recording_timestamp, event_timestamp, event_data):
Expand Down Expand Up @@ -97,8 +97,8 @@ def _get(table, recording_timestamp):
)


def get_actions(recording):
return _get(Action, recording.timestamp)
def get_input_events(recording):
return _get(InputEvent, recording.timestamp)


def get_screenshots(recording, precompute_diffs=True):
Expand Down
84 changes: 42 additions & 42 deletions puterbot/events.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@

from puterbot.common import KEY_EVENTS, MOUSE_EVENTS
from puterbot.crud import (
get_actions,
get_input_events,
get_window_events,
get_screenshots,
)
from puterbot.models import Action
from puterbot.models import InputEvent
from puterbot.utils import (
get_double_click_distance_pixels,
get_double_click_interval_seconds,
Expand All @@ -25,42 +25,42 @@

def get_events(recording, process=True, meta=None):
start_time = time.time()
actions = get_actions(recording)
input_events = get_input_events(recording)
window_events = get_window_events(recording)
screenshots = get_screenshots(recording)

raw_action_dicts = rows2dicts(actions)
logger.debug(f"raw_action_dicts=\n{pformat(raw_action_dicts)}")
raw_input_event_dicts = rows2dicts(input_events)
logger.debug(f"raw_input_event_dicts=\n{pformat(raw_input_event_dicts)}")

num_actions = len(actions)
num_input_events = len(input_events)
num_window_events = len(window_events)
num_screenshots = len(screenshots)

num_actions_raw = num_actions
num_input_events_raw = num_input_events
num_window_events_raw = num_window_events
num_screenshots_raw = num_screenshots
duration_raw = actions[-1].timestamp - actions[0].timestamp
duration_raw = input_events[-1].timestamp - input_events[0].timestamp

num_process_iters = 0
if process:
while True:
logger.info(
f"{num_process_iters=} "
f"{num_actions=} "
f"{num_input_events=} "
f"{num_window_events=} "
f"{num_screenshots=}"
)
actions, window_events, screenshots = process_events(
actions, window_events, screenshots,
input_events, window_events, screenshots = process_events(
input_events, window_events, screenshots,
)
if (
len(actions) == num_actions and
len(input_events) == num_input_events and
len(window_events) == num_window_events and
len(screenshots) == num_screenshots
):
break
num_process_iters += 1
num_actions = len(actions)
num_input_events = len(input_events)
num_window_events = len(window_events)
num_screenshots = len(screenshots)
if num_process_iters == MAX_PROCESS_ITERS:
Expand All @@ -71,8 +71,8 @@ def get_events(recording, process=True, meta=None):
lambda num, raw_num: f"{num} of {raw_num} ({(num / raw_num):.2%})"
)
meta["num_process_iters"] = num_process_iters
meta["num_actions"] = format_num(
num_actions, num_actions_raw,
meta["num_input_events"] = format_num(
num_input_events, num_input_events_raw,
)
meta["num_window_events"] = format_num(
num_window_events, num_window_events_raw,
Expand All @@ -81,16 +81,16 @@ def get_events(recording, process=True, meta=None):
num_screenshots, num_screenshots_raw,
)

duration = actions[-1].timestamp - actions[0].timestamp
if len(actions) > 1:
duration = input_events[-1].timestamp - input_events[0].timestamp
if len(input_events) > 1:
assert duration > 0, duration
meta["duration"] = format_num(duration, duration_raw)

end_time = time.time()
duration = end_time - start_time
logger.info(f"{duration=}")

return actions # , window_events, screenshots
return input_events # , window_events, screenshots


def make_parent_event(child, extra=None):
Expand All @@ -108,7 +108,7 @@ def make_parent_event(child, extra=None):
extra = extra or {}
for key, val in extra.items():
event_dict[key] = val
return Action(**event_dict)
return InputEvent(**event_dict)


def merge_consecutive_mouse_move_events(events, by_diff_distance=True):
Expand Down Expand Up @@ -232,7 +232,7 @@ def get_merged_events(
return merged_events


return merge_consecutive_actions(
return merge_consecutive_input_events(
"mouse_move", events, is_target_event, get_merged_events,
)

Expand All @@ -256,7 +256,7 @@ def get_merged_events(to_merge, state):
return [merged_event]


return merge_consecutive_actions(
return merge_consecutive_input_events(
"mouse_scroll", events, is_target_event, get_merged_events,
)

Expand Down Expand Up @@ -381,7 +381,7 @@ def get_merged_events(to_merge, state):
return merged


return merge_consecutive_actions(
return merge_consecutive_input_events(
"mouse_click", events, is_target_event, get_merged_events,
)

Expand Down Expand Up @@ -467,7 +467,7 @@ def get_merged_events(to_merge, state):
merged_events.append(merged_event)
return merged_events

return merge_consecutive_actions(
return merge_consecutive_input_events(
"keyboard", events, is_target_event, get_merged_events,
)

Expand Down Expand Up @@ -530,12 +530,12 @@ def get_merged_events(to_merge, state):
return merged_events


return merge_consecutive_actions(
return merge_consecutive_input_events(
"redundant_mouse_move", events, is_target_event, get_merged_events,
)


def merge_consecutive_actions(
def merge_consecutive_input_events(
name, events, is_target_event, get_merged_events,
):
"""Merge consecutive input events into a single event"""
Expand Down Expand Up @@ -573,11 +573,11 @@ def include_merged_events(to_merge):


def discard_unused_events(
referred_events, actions, referred_timestamp_key,
referred_events, input_events, referred_timestamp_key,
):
referred_event_timestamps = set([
getattr(action, referred_timestamp_key)
for action in actions
getattr(input_event, referred_timestamp_key)
for input_event in input_events
])
num_referred_events_before = len(referred_events)
referred_events = [
Expand All @@ -593,13 +593,13 @@ def discard_unused_events(
return referred_events


def process_events(actions, window_events, screenshots):
num_actions = len(actions)
def process_events(input_events, window_events, screenshots):
num_input_events = len(input_events)
num_window_events = len(window_events)
num_screenshots = len(screenshots)
num_total = num_actions + num_window_events + num_screenshots
num_total = num_input_events + num_window_events + num_screenshots
logger.info(
f"before {num_actions=} {num_window_events=} {num_screenshots=} "
f"before {num_input_events=} {num_window_events=} {num_screenshots=} "
f"{num_total=}"
)
process_fns = [
Expand All @@ -610,9 +610,9 @@ def process_events(actions, window_events, screenshots):
merge_consecutive_mouse_click_events,
]
for process_fn in process_fns:
actions = process_fn(actions)
input_events = process_fn(input_events)
# TODO: keep events in which window_event_timestamp is updated
for prev_event, event in zip(actions, actions[1:]):
for prev_event, event in zip(input_events, input_events[1:]):
try:
assert prev_event.timestamp <= event.timestamp, (
process_fn, prev_event, event,
Expand All @@ -621,26 +621,26 @@ def process_events(actions, window_events, screenshots):
logger.exception(exc)
import ipdb; ipdb.set_trace()
window_events = discard_unused_events(
window_events, actions, "window_event_timestamp",
window_events, input_events, "window_event_timestamp",
)
screenshots = discard_unused_events(
screenshots, actions, "screenshot_timestamp",
screenshots, input_events, "screenshot_timestamp",
)
num_actions_ = len(actions)
num_input_events_ = len(input_events)
num_window_events_ = len(window_events)
num_screenshots_ = len(screenshots)
num_total_ = num_actions_ + num_window_events_ + num_screenshots_
pct_actions = num_actions_ / num_actions
num_total_ = num_input_events_ + num_window_events_ + num_screenshots_
pct_input_events = num_input_events_ / num_input_events
pct_window_events = num_window_events_ / num_window_events
pct_screenshots = num_screenshots_ / num_screenshots
pct_total = num_total_ / num_total
logger.info(
f"after {num_actions_=} {num_window_events_=} {num_screenshots_=} "
f"after {num_input_events_=} {num_window_events_=} {num_screenshots_=} "
f"{num_total=}"
)
logger.info(
f"{pct_actions=} {pct_window_events=} {pct_screenshots=} "
f"{pct_input_events=} {pct_window_events=} {pct_screenshots=} "
f"{pct_total=}"

)
return actions, window_events, screenshots
return input_events, window_events, screenshots
12 changes: 6 additions & 6 deletions puterbot/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,11 @@ class Recording(Base):
platform = sa.Column(sa.String)
task_description = sa.Column(sa.String)

actions = sa.orm.relationship("Action", back_populates="recording")
input_events = sa.orm.relationship("InputEvent", back_populates="recording")


class Action(Base):
__tablename__ = "action"
class InputEvent(Base):
__tablename__ = "input_event"

id = sa.Column(sa.Integer, primary_key=True)
name = sa.Column(sa.String)
Expand All @@ -46,10 +46,10 @@ class Action(Base):
canonical_key_name = sa.Column(sa.String)
canonical_key_char = sa.Column(sa.String)
canonical_key_vk = sa.Column(sa.String)
parent_id = sa.Column(sa.Integer, sa.ForeignKey("action.id"))
parent_id = sa.Column(sa.Integer, sa.ForeignKey("input_event.id"))

children = sa.orm.relationship("Action")
recording = sa.orm.relationship("Recording", back_populates="actions")
children = sa.orm.relationship("InputEvent")
recording = sa.orm.relationship("Recording", back_populates="input_events")
screenshot = sa.orm.relationship("Screenshot")
window_event = sa.orm.relationship("WindowEvent")

Expand Down
Loading

0 comments on commit 659b9d7

Please sign in to comment.