Чи є програмне забезпечення, яке періодично дозволяє мені робити розумові арифметичні вправи?


9

Я усвідомлюю свою ледачу природу і потрібно час від часу підштовхувати себе до виконання якоїсь основної ментальної арифметики. Тому я шукаю програмне забезпечення, яке періодично просить мене зробити коротку розумову арифметичну вправу (плюс, мінус, помножити, ділити).

Критерії:

  • Це повинно дозволити мені налаштувати інтервал часу
  • Він повинен інтегруватися в робочий стіл Ubuntu, тобто бути прихованим у фоновому режимі і відображатися (спливаюче вікно) лише під час виконання вправ

2
Я сумніваюся, що таке програмне забезпечення існує, але його можна було б легко створити за допомогою оболонки або сценарію python. Я завтра щось приготую, нагадайте
Сергій Колодяжний

Так, у bsdgames є арифметичні та такі, але вам доведеться самостійно автоматизувати періодичні спливаючі вікна.
mchid

Шановний @Serg, ласкаво нагадаю про твій кулінарний експеримент. :)
orschiro

1
Тож я опублікував відповідь, що не працює, яку я буду редагувати, продовжуючи працювати. Будь ласка, погляньте, дайте мені знати, що ви думаєте, яку функціональність додати чи видалити. Поки це консольний додаток, але з часом воно перетвориться на невелике спливаюче вікно.
Сергій Колодяжний

2
Виявляється, приємне питання, над яким працювати!
Яків Влійм

Відповіді:


8

1. Прямий варіант

Сценарій, наведений нижче, буде створювати завдання випадковим чином, + , - , × і ÷ . Ви можете (і повинні) встановити максимальну кількість, яку може використовувати сценарій, а також часовий інтервал між призначеннями.

Завдання

Завдання представлені у вікні запису Zenity:

введіть тут опис зображення

якщо відповідь неправильна:

введіть тут опис зображення

Якщо відповідь правильна:

введіть тут опис зображення

Сценарій

#!/usr/bin/env python3
from random import randint
import sys
import subprocess
import time

# maximum number & interval
max_n = int(sys.argv[1]); pause = int(sys.argv[2])

def fix_float(n):
    """
    if the assignment is a division, the script divides the random number by a
    number (integer) it can be divided by. it looks up those numbers, and picks
    one of them (at random). if the number is a prime number the assignment is
    changed into another type
    """
    try:
        divs = [i for i in range(2, n) if n%i == 0]
        pick = randint(1, len(divs))
        div_by = divs[pick-1]
        return [str(n)+" : "+str(div_by), int(n/div_by)]
    except (ValueError, IndexError):
        pass

def get_assignment():
    """
    get a random number within the user defined range, make the assignment and
    the textual presentation
    """
    n1 = randint(2, max_n); n2 = randint(2, max_n)
    assignments = [
        [str(n1)+" + "+str(n2), n1+n2],
        [str(n1)+" - "+str(n2), n1-n2],
        [str(n1)+" x "+str(n2), n1*n2],
        fix_float(n1),
        ]
    # pick an assignment (type) at random
    assignment = assignments[randint(0, 3)]
    # if the random number is a prime number and the assignment a division...
    assignment = assignment if assignment != None else assignments[1]
    # run the interface job
    try:
        answer = int(subprocess.check_output(["/bin/bash", "-c",
            'zenity --entry --title="Think hard:" --text='+'"'+assignment[0]+'"'
            ]).decode("utf-8"))
        if answer == assignment[1]:
            subprocess.Popen(["notify-send", "Coolcool"])
        else:
            subprocess.Popen([
                "notify-send", "Oooops, "+assignment[0]+\
                " = "+str(assignment[1])])
    except (subprocess.CalledProcessError, ValueError):
        pass

while True:
    time.sleep(pause)
    get_assignment()

Як користуватись

  1. Скопіюйте скрипт у порожній файл, збережіть його як mindpractice.py
  2. Запустіть його з максимально дозволеною кількістю та інтервалом (у секундах) між призначеннями як аргументи:

    python3 /path/to/mindpractice.py <max_number> <interval>

    напр

    python3 /path/to/mindpractice.py 1000 300

    робити розрахунки до цифр 1000з 5-хвилинною перервою між завданнями.

  3. Якщо все працює добре, ви можете додати його до запуску програм звичайним способом, або можна зробити пускову установку для перемикання, яку я можу додати пізніше :)

Примітка

  • Розділовий може знадобитися якийсь - то пояснення. Ви, мабуть, не хотіли б обчислювати поплавками. Тому, якщо призначення є діленням, скрипт шукає числа, на які його можна розділити, і вибирає одне (навмання). Якщо (основне) число виявляється простим числом, призначення змінюється на інший тип.

2. Більше варіантів

Як тільки ви почнете обчислювати, ви дізнаєтесь, що ділити на цифри (скажімо) 100 набагато простіше, ніж множення цифр на 100.

За допомогою нижченаведеного сценарію ви можете (і повинні) встановити максимум чисел на тип вправи (див. Інструкції нижче сценарію).

Сценарій

#!/usr/bin/env python3
from random import randint
import sys
import subprocess
import time

levels = sys.argv[1:]
pause = [int(arg.replace("p:", "")) for arg in levels if "p:" in arg][0]

def fix_float(n):
    """
    if the assignment is a division, the script divides the random number by a
    number (integer) it can be divided by. it looks up those numbers, and picks
    one of them (at random). if the number is a prime number the assignment is
    changed into another type
    """
    try:
        divs = [i for i in range(2, n) if n%i == 0]
        pick = randint(1, len(divs))
        div_by = divs[pick-1]
        return [str(n)+" : "+str(div_by), int(n/div_by)]
    except (ValueError, IndexError):
        pass

def get_assignment():
    """
    get a random number within the user defined range, make the assignment and
    the textual presentation
    """
    # pick an assignment (type) at random
    track = randint(0, 3)
    arg = ["a:", "s:", "m:", "d:"][track]
    max_n = [int(item.replace(arg, "")) for item in levels if arg in item][0]

    n1 = randint(2, max_n); n2 = randint(2, max_n)
    assignments = [
        [str(n1)+" + "+str(n2), n1+n2],
        [str(n1)+" - "+str(n2), n1-n2],
        [str(n1)+" x "+str(n2), n1*n2],
        fix_float(n1),
        ]
    assignment = assignments[track]     
    # if the random number is a prime number and the assignment a division...
    assignment = assignment if assignment != None else assignments[1]
    # run the interface job
    try:
        answer = int(subprocess.check_output(["/bin/bash", "-c",
            'zenity --entry --title="Think hard:" --text='+'"'+assignment[0]+'"'
            ]).decode("utf-8"))
        if answer == assignment[1]:
            subprocess.Popen(["notify-send", "Coolcool"])
        else:
            subprocess.Popen([
                "notify-send", "Oooops, "+assignment[0]+\
                " = "+str(assignment[1])])
    except (subprocess.CalledProcessError, ValueError):
        pass

while True:
    time.sleep(pause)
    get_assignment()

Як користуватись

  • Налаштуйте скрипт точно так само, як перший, але запустіть його аргументами (у будь-якому порядку, сценарій зв’яже правильні аргументи з правильним елементом):

    • p: пауза (перерва між завданнями, в секундах))
    • s: віднімання (максимальне число для обчислення з)
    • a: додати (максимальна кількість)
    • m: помножити (максимальна кількість)
    • d: ділити (максимальна кількість)

    Наприклад:

    python3 '/home/jacob/Desktop/num.py' a:10 d:100 s:10 m:10 p:300

    показувати вправу кожні п’ять хвилин, чисел до 10, крім ділення на цифру 100.


3. Давайте трохи захопимось

Можливість переглянути деякі статистичні дані

Версія нижче показує статистику після кожні 10 вправ:

введіть тут опис зображення

Додатково (може бути корисним при використанні для дітей), ви можете побачити, що пішло не так в останніх 100 неправильно відповідей вправ. У прихований файл записуються як завдання, так і їх (неправильні) відповіді:

введіть тут опис зображення

Цей логфайл розміщено:

~/.calculog

Сценарій

#!/usr/bin/env python3
from random import randint
import sys
import subprocess
import time
import os

log = os.environ["HOME"]+"/.calculog"

levels = sys.argv[1:]
pause = [int(arg.replace("p:", "")) for arg in levels if "p:" in arg][0]

def fix_float(n):
    """
    if the assignment is a division, the script divides the random number by a
    number (integer) it can be divided by. it looks up those numbers, and picks
    one of them (at random). if the number is a prime number the assignment is
    changed into another type
    """
    try:
        divs = [i for i in range(2, n) if n%i == 0]
        pick = randint(1, len(divs))
        div_by = divs[pick-1]
        return [str(n)+" : "+str(div_by), int(n/div_by)]
    except (ValueError, IndexError):
        pass

def get_assignment():
    """
    get a random number within the user defined range, make the assignment and
    the textual presentation
    """
    # pick an assignment (type) at random
    track = randint(0, 3)
    arg = ["a:", "s:", "m:", "d:"][track]
    max_n = [int(item.replace(arg, "")) for item in levels if arg in item][0]

    n1 = randint(2, max_n); n2 = randint(2, max_n)
    assignments = [
        [str(n1)+" + "+str(n2), n1+n2],
        [str(n1)+" - "+str(n2), n1-n2],
        [str(n1)+" x "+str(n2), n1*n2],
        fix_float(n1),
        ]
    assignment = assignments[track]     
    # if the random number is a prime number and the assignment a division...
    assignment = assignment if assignment != None else assignments[1]
    # run the interface job
    try:
        answer = int(subprocess.check_output(["/bin/bash", "-c",
            'zenity --entry --title="Think hard:" --text='+'"'+assignment[0]+'"'
            ]).decode("utf-8"))
        if answer == assignment[1]:
            subprocess.Popen(["notify-send", "Coolcool"])
            return "ok"
        else:
            subprocess.Popen([
                "notify-send", "Oooops, "+assignment[0]+\
                " = "+str(assignment[1])])
            open(log, "+a").write(assignment[0]+"\t\t"+str(answer)+"\n")
            try:
                history = open(log).read().splitlines()
                open(log, "wt").write(("\n").join(history[-100:])+"\n")     
            except FileNotFoundError:
                pass 
            return "mistake"
    except (subprocess.CalledProcessError, ValueError):
        return None

results = []
while True:
    time.sleep(pause)
    results.append(get_assignment())
    if len(results) >= 10:
        score = results.count("ok")
        subprocess.call([
            "zenity", "--info",
            '--title=Latest scores',
            '--text='+str(score)+' out of 10',
            '--width=160',
            ])
        results = []

Як користуватись

Використання майже так само, як варіант 2, але у вас буде доступний файл реєстрації та результати після кожні 10 завдань.


4. Кінцева версія

Версія нижче - як варіант 3 (включаючи файл журналу та звіти), але має деякі додаткові функції:

  • додає обчислювальний квадратний корінь

    введіть тут опис зображення

  • додає, використовуючи діапазон чисел, а не просто встановлюючи максимум

  • додає можливість запускати лише конкретні типи обчислень (наприклад, лише ділити та множити).
  • запам'ятовує аргументи, які він був запущений в останній раз, коли запускається без аргументів (аргументи повинні бути встановлені лише перший раз ). Якщо під час першого запуску не було встановлено жодних аргументів, сценарій надсилає повідомлення:

    введіть тут опис зображення

Сценарій

#!/usr/bin/env python3
from random import randint
import sys
import subprocess
import time
import os

"""
Use this script to practice head count. Some explanation might be needed:
The script can be used for the following types of calculating:

Type          argument example      explanation
-------------------------------------------------------------------------------
add           a:30-100              to add in numbers from 30-100
subtract      s:10-100              to subtract in numbers from 10-100
multiply      m:10-20               to multiply in numbers from 10-20
divide        d:200-400             to divide in numbers from 200-400
square root   r:1-1000              to find square root in numbers from 1-1000

N.B.
-------------------------------------------------------------------------------
- The argument p: (pause in seconds; break between the assignments) *must* be
  set, for example: p:300 to launch an assignment every 5 minutes
- A calculation type will only run *if* the argument is set for the
  corresponding type. An example: python3 /path/to/script p:60 s:30-60
  will run a subtract- assignment every minute.

Miscellaneous information:
-------------------------------------------------------------------------------
- On first run, arguments *must* be set. After first run, when no arguments
  are used the last set arguments will run, until the script is run with a new
  set of arguments.
- A log file of the last 100 incorrectly answered questions is kept in
  ~/.calculog
- After 10 assignments, the score of the last 10 pops up.
"""

log = os.environ["HOME"]+"/.calculog"
prefs = os.environ["HOME"]+"/.calcuprefs"
levels = sys.argv[1:]

if levels:
    open(prefs, "wt").write(str(levels))
else:
    try:
        levels = eval(open(prefs).read())
    except FileNotFoundError:
        subprocess.call([
            "zenity", "--info",
            '--title=Missing arguments',
            '--text=On first run, the script needs to be run with arguments\n'
            ])

def fix_float(n):
    """
    if the assignment is a division, the script divides the random number by a
    number (integer) it can be divided by. it looks up those numbers, and picks
    one of them (at random). if the number is a prime number the assignment is
    changed into another type
    """
    try:
        divs = [i for i in range(2, n) if n%i == 0]
        pick = randint(1, len(divs))
        div_by = divs[pick-1]
        return [str(n)+" : "+str(div_by), int(n/div_by)]
    except (ValueError, IndexError):
        pass

def fix_sqr(f1, f2):
    """
    If the assignment is calculating a square root, this function finds the sets
    of numbers (integers) that make a couple, within the given range.
    """
    q = f1; r = q**(.5); sets = []
    while q < f2:
        r = q**(.5)
        if r == int(r):
            sets.append([int(r), int(q)])
        q = q+1
    if sets:
        pick = sets[randint(0, len(sets)-1)]
        return ["√"+str(pick[1]), pick[0]]

def get_assignment():
    """
    get a random number within the user defined range, make the assignment and
    the textual presentation
    """ 
    args = ["a:", "s:", "m:", "d:", "r:"]
    indc = []
    for i, item in enumerate(args):
        if item in str(levels):
            indc.append(i)

    index = indc[randint(0, len(indc)-1)]
    name = args[index]

    minmax = [
        [int(n) for n in item.replace(name, "").split("-")] \
        for item in levels if name in item][0]

    assignment = None
    # if the random number is a prime number *and* the assignment a division 
    # or a square root...
    while assignment == None:
        n1 = randint(minmax[0], minmax[1]); n2 = randint(minmax[0], minmax[1])
        assignment = [
            [str(n1)+" + "+str(n2), n1+n2],
            [str(n1)+" - "+str(n2), n1-n2],
            [str(n1)+" x "+str(n2), n1*n2],
            fix_float(n1),
            fix_sqr(minmax[0], minmax[1]),
            ][index]
    # run the interface job
    try:
        answer = int(subprocess.check_output(["/bin/bash", "-c",
            'zenity --entry --title="Think hard:" --text='+'"'+assignment[0]+'"'
            ]).decode("utf-8"))
        if answer == assignment[1]:
            subprocess.Popen(["notify-send", "Coolcool"])
            return "ok"
        else:
            subprocess.Popen([
                "notify-send", "Oooops, "+assignment[0]+\
                " = "+str(assignment[1])])
            open(log, "+a").write(assignment[0]+"\t\t"+str(answer)+"\n")
            try:
                history = open(log).read().splitlines()
                open(log, "wt").write(("\n").join(history[-100:])+"\n")     
            except FileNotFoundError:
                pass 
            return "mistake"
    except (subprocess.CalledProcessError, ValueError):
        return None

if levels:
    pause = [int(arg.replace("p:", "")) for arg in levels if "p:" in arg][0]
    [levels.remove(item) for item in levels if "p:" in item]
    results = []
    while True:
        time.sleep(pause)
        results.append(get_assignment())
        if len(results) >= 10:
            score = results.count("ok")
            subprocess.call([
                "zenity", "--info",
                '--title=Latest scores',
                '--text='+str(score)+' out of 10',
                '--width=160',
                ])
            results = []

Як користуватись

  • Скопіюйте скрипт у порожній файл, збережіть його (знову) як mindpractice.py. Запустіть його за допомогою наступних опцій (як приклади)

    Потрібно встановити:

    p:300                to set the interval between assignments to 5 minutes

    Необов’язково (зробити вибір):

    a:30-100             to add in numbers from 30-100 (optional)
    s:10-100             to subtract in numbers from 10-100
    m:10-20              to multiply in numbers from 10-20
    d:200-400            to divide in numbers from 200-400
    r:1-1000             to find square root in numbers from 1-1000
    
  • Приклад команди:

    python3 '/path/to/mindpractice.py' p:300 d:10-100 s:10-30  r:300-600

    встановити:

    p:300                to set the interval between assignments to 5 minutes
    d:10-100             to divide in numbers from 10-100
    s:10-30              to subtract in numbers from 10-30
    r:300-600            to calculate square roots from 300-600
    

    при цьому додавання та множення не використовуються.

Тоді наступного разу, якщо сценарій запускається із:

python3 '/path/to/mindpractice.py'

Він запам'ятає останні використані аргументи


Використовуйте версію, яка найкраще відповідає вашим потребам ...



Ця версія досі працює чудово. Дуже дякую!
orschiro

1
@orschiro додав розширену версію для розширення труднощів.
Яків Влійм

файл журналу - дуже приємна ідея! На даний момент я намагаюся обвести голову деякими тризначними множеннями та поділами. Вони не такі прямолінійні. :)
orschiro

просто ідея: Іноді я настільки зосереджений на роботі, що ігнорую Think Hardвікно, щоб закінчити роботу раніше (наприклад, закінчити написання речення). Потім я забуваю про вікно. Чи можливо, що через 5 хвилин Think Hardвікно автоматично поверне фокус?
orschiro

1
@orschiro абсолютно! Я також ще жував повністю GUI-версію (не потрібно нічого встановлювати з командного рядка, навіть не перший запуск), але я не впевнений, що вони дозволять нам додати ще метри до відповіді :)
Jacob Vlijm

3

Вступ:

Наступна програма виробляє випадкові цілі вирази, які оцінюються користувачем. Діапазон випадково згенерованих виразів залежить від налаштувань користувача у головному спливаючому вікні. Після натискання Lets Beginкнопки сеанс починається нескінченно, поки користувач не натисне кнопку Скасувати.

введіть тут опис зображення

введіть тут опис зображення

Вихідний код:

#!/usr/bin/env python

# Author: Serg Kolo
# Date: Jan 30,2016
# Purpose: A graphical utility for practicing
#          random arithmetic operations
# Written for: http://askubuntu.com/q/725287/295286

#    Copyright: Serg Kolo , 2016
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation, either version 3 of the License, or
#    (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.

import sys
import time
import random
from PyQt4 import QtGui


class mathApp(QtGui.QWidget):
   def __init__(self):
       super(mathApp,self).__init__()
       self.mainMenu()

   def mainMenu(self):
      self.setGeometry(300, 300, 400, 200)

      self.btn = QtGui.QPushButton("Let's begin",self)
      self.btn.move(20,150)
      self.btn.clicked.connect(self.askQuestions)

      self.lbl1 = QtGui.QLabel(self)
      self.lbl1.move(20,25)
      self.lbl1.setText("Numbers From")


      self.lbl2 = QtGui.QLabel(self)
      self.lbl2.move(20,55)
      self.lbl2.setText("Numbers To")

      self.lbl2 = QtGui.QLabel(self)
      self.lbl2.move(20,85)
      self.lbl2.setText("Repeat (seconds)")

      self.le1 = QtGui.QLineEdit(self)
      self.le1.move(150,20)

      self.le2 = QtGui.QLineEdit(self)
      self.le2.move(150,50)

      self.le3 = QtGui.QLineEdit(self)
      self.le3.move(150,80)

      self.lbl3 = QtGui.QLabel(self)
      self.lbl3.move(20,105)

      self.setWindowTitle('Random Integer Arithmetic')

      self.show()

   def askQuestions(self):
       rangeStart = int(self.le1.text())
       rangeEnd = int(self.le2.text())
       sleepTime = int(self.le3.text())
       done=False
       while not done:
          self.show()
          expression = self.generateOperation(rangeStart,rangeEnd)
          correctAnswer = eval(expression)

          prompt = QtGui.QInputDialog() 
          text,ok = prompt.getText(self,"Don't think too hard",expression) 
          if ok:
             if int(text) == correctAnswer:                
                self.showAnswer("CORRECT,YOU ROCK !")
             else :
                self.showAnswer("Nope");
          else:
              done=True

          if done==True:
              self.close()
          time.sleep(sleepTime)


   def generateOperation(self,start,end):
      a = random.randint(start,end)
      b = random.randint(start,end)
      oplist = ['+','-','/','*']
      op = oplist[random.randint(0,3)]
      expr = str(a) + op + str(b) + ''
      return expr

   def showAnswer(self,result):
       popup = QtGui.QMessageBox()
       popup.setText(result)
       popup.exec_()


def main():
   root = QtGui.QApplication(sys.argv)
   app = mathApp()
   sys.exit(root.exec_())

if __name__ == '__main__':
   main()

Шановний @Serg, я також хочу особисто подякувати вам за розширену версію GUI. Одне запитання, у мене якраз була вправа 15/14 = 1. Я не впевнений, наскільки корисна така вправа. Як ти гадаєш?
orschiro

@orschiro це integer arithmetic. Це означає, що результат є лише цілою частиною, без залишку. Якщо ви хочете, я також можу спробувати реалізувати decimalарифметику. Крім того, будь ласка, дайте мені знати, які саме інші варіанти ви хочете, щоб я реалізував та додав. В даний час я намагаюся практикувати agile developmentметод, і спілкування з клієнтом є ключовим в такому методі. Будь ласка, дай мені знати.
Сергій Колодяжний

це чудово чути! Я хотів би надати вам більше відгуків, наприклад, кращої інтеграції до робочого столу Ubuntu (запускайте сценарій більше у фоновому режимі, тобто мінімізуйте після введення користувачем). Як я можу найкраще надати вам подальший відгук?
orschiro
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.