Python Forum

Full Version: Total Strokes Calculator
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Hello all,

I'm trying to create a calculator where I want to see the total strokes in cumulative (sum per second) when I input the rate. For example: the rate is 60 Strokes per Minute, I'm trying to get how many strokes have been already totalized per second, like a a loop.

I have tried several things but could not reach what I need.. I was thinking in:

Total_strokes = (SPM/60) + last sum result (per second)

Could you help me on that? Huh Huh

Thanks!!
You also have to multiply the stroke rate by the time spent at that rate. So, if the rate is 120/min for 3 seconds then 60/min for 2 seconds the total strokes would be

total_strokes = 120/60*3 + 60/60*2 = 8 strokes for the 5 seconds.
(Aug-02-2022, 11:48 AM)jefsummers Wrote: [ -> ]You also have to multiply the stroke rate by the time spent at that rate. So, if the rate is 120/min for 3 seconds then 60/min for 2 seconds the total strokes would be

total_strokes = 120/60*3 + 60/60*2 = 8 strokes for the 5 seconds.

Thanks for your reply!

And do you think that I can make this generate automatically every 1 second? For example: summing with the last value?
You need something, which calls for example on KeyPress a callback, which does the logic.
You can record for each KeyPress a timestamp/timeout in a list. Another repeated function could delete the data which is for example older than 5 seconds. This is your observation window. To get the KeyPress per minute, count the elements after old values have been deleted from the list and then divide it by observation window and multiply by 60.

In addition, you can also count words, but this requires additional work to get it correctly.

Example with tkinter:
import time
from threading import Lock
from tkinter import END, Button, Label, StringVar, Text, Tk, INSERT


class KPM:
    def __init__(self, time_window):
        self.time_window = time_window
        self.lock = Lock()
        self.window = Tk()
        self.kpm = StringVar()
        self.wpm = StringVar()

        Label(self.window, textvariable=self.kpm, font=36).pack()
        Label(self.window, textvariable=self.wpm, font=36).pack()
        self.text_widget = Text(self.window, font=24)
        self.text_widget.pack()
        Button(self.window, text="Clear", command=self._clear).pack()
        Button(self.window, text="Exit", command=self.window.destroy).pack()

        self.window.bind_all("<KeyPress>", self.on_press)
        self.strokes = []
        self.words = []
        self._last_char = None

        self._show()

    def _clear(self):
        self.text_widget.delete("1.0", END)
        self.strokes.clear()
        self.words.clear()

    def _show(self):
        with self.lock:
            now = time.monotonic()
            self.strokes = [timeout for timeout in self.strokes if now < timeout]
            self.words = [timeout for timeout in self.words if now < timeout]
            kpm = len(self.strokes) / self.time_window * 60
            wpm = len(self.words) / self.time_window * 60
            self.kpm.set(f"{kpm:.0f} key presses per minute")
            self.wpm.set(f"{wpm:.0f} words per minute")
        self.window.after(200, self._show)

    def on_press(self, event):
        with self.lock:
            timeout = time.monotonic() + self.time_window
            self.strokes.append(timeout)

            # cursor_position = self.text_widget.index(INSERT)
            # too complicated to look backwwards ...

            if event.char == " " and self._last_char != " ":
                self.words.append(timeout)

            self._last_char = event.char

    def start(self):
        self.window.mainloop()


if __name__ == "__main__":
    KPM(time_window=5).start()
Other libraries which can read keyboard events:
Yes, where will you get the strokes/min value? Are you working from keystrokes as implied by DeadEye?
Exactly Jef, I want to ask an input for the user to enter the stroke/min (SPM) value and then, the code would calculate how many strokes has been already acumulated after every second while the code is running. Got it?
So like a teaching typing program, sort of.
DeaD_EyEs code will work, or you could tie it to elapsed time rather than the keypress event. Use time.sleep(1) in a loop and count the number of characters currently in the box, divided by the index of the loop. That would give you a running average.
If stroke rate is a constant (entered by the user), there is no reason to integrate. Record starting time, and whenever you want an expected strokes count:
expected_strokes = strokes_per_second * (time.time() - start_time).

If stroke rate is measured, it makes more sense to measure stroke count and compute stroke rate. As far as I know there is no way to measure stroke rate directly, so you are forced to count strokes and measure time and compute the derivative of stroke count over time. May as well use the accurate stroke counter instead of a messy computed stroke rate.