Существует ли программное обеспечение, которое периодически позволяет мне выполнять умственные арифметические упражнения?

9

Я осознаю свою ленивую натуру, и мне нужно время от времени подталкивать себя к выполнению некоторых основных умственных арифметических действий. Поэтому я ищу программное обеспечение, которое периодически просит меня выполнить короткое умственное арифметическое упражнение (плюс, минус, умножение, деление).

Критерии:

  • Это должно позволить мне настроить интервал времени
  • Он должен интегрироваться в Ubuntu Desktop, то есть быть скрытым в фоновом режиме и отображаться (всплывающим) только во время тренировки
orschiro
источник
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'

Он запомнит последние использованные аргументы


Используйте версию, которая лучше всего соответствует вашим потребностям ...


Якоб Влейм
источник
Эта версия отлично работает до сих пор. Спасибо огромное!
Орширо
1
@orschiro добавил расширенную версию, чтобы отличить сложность.
Джейкоб Влейм
лог файл очень хорошая идея! В настоящее время я пытаюсь разобраться с некоторыми из трехзначных умножений и делений. Они не так просты. :)
Орширо
просто идея: иногда я настолько сосредоточен на работе, что игнорирую Think Hardокно, чтобы закончить работу раньше (например, закончить написание предложения). Я тогда забуду об окне. Возможно ли, чтобы через 5 минут Think Hardокно автоматически восстановило фокус?
Орширо
1
@orschiro абсолютно! Я также все еще жевал полностью GUI-версию (не нужно ничего устанавливать из командной строки, даже после первого запуска), но я не уверен, что они позволят нам добавить больше метра к ответу :)
Джейкоб Влейм
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 это integer arithmetic. Это означает, что результат - только целая часть, без остатка. Если хотите, я мог бы попытаться реализовать decimalарифметику. Также, пожалуйста, дайте мне знать, какие другие опции вы бы хотели, чтобы я внедрил и добавил. В настоящее время я пытаюсь практиковать agile developmentметод, и общение с клиентом является ключевым в таком методе. Пожалуйста, дайте мне знать.
Сергей Колодяжный
это приятно слышать! Я хотел бы предоставить вам больше отзывов, например, лучшую интеграцию в Ubuntu Desktop (запускать сценарии чаще в фоновом режиме, то есть минимизировать после ввода данных пользователем). Как я могу наилучшим образом предоставить вам дополнительную обратную связь?
Орширо