Mathe-Trainingsprogramm in Python mit AGI für Asterisk-Server

4.11.2022

Dieses kleine Mathe-Trainingsprogramm dient zum Üben der Subtraktion von Zahlen. Es wurde auf Python geschrieben und läuft in Verbindung mit AGI auf Asterisk-Telefon-Servern.

Vorgeschichte: Ursprünglich wurde dieses Programm von Ed Guy auf Perl geschrieben und 2004 auf der AstriCon-Konferenz vorgestellt. Ed Guy wollte seiner Tochter ein Programm anbieten, mit dem sie das Subtrahieren von Zahlen üben kann.

Später wurde es auf Python umgeschrieben und auf http://www.asteriskdocs.org/en/2nd_Edition/asterisk-book-html-chunk/asterisk-CHP-9-SECT-4.html vorgestellt. Allerdings ist der Code veraltet und läuft nicht mehr auf Python 3. Zudem fehlen die Sound-Dateien für die Anweisungen, die ich erstellt habe.

Das neue Python-Skript für Python 3: Nachfolgend das angepasste Python-Programm für Python 3 und mit den entsprechenden Verknüpfungen zu den Audio-Dateien. Getestet wurde es auf Asterisk 16.2.1, Python 3.7 und Python 2.7. Beide Python-Versionen sind bereits auf dem Raspbian für den Raspberry vorinstalliert. Das Skript habe ich eine Textdatei kopiert und ihr  den Namen subtraction_game.py vergeben:

#!/usr/bin/python
# adapted for Python 3 from http://www.asteriskdocs.org/en/2nd_Edition/asterisk-book-html-chunk/asterisk-CHP-9-SECT-4.html

import sys
import re
import time
import random

# Read and ignore AGI environment (read until blank line)

env = {}
tests = 0;

while 1:
   line = sys.stdin.readline().strip()

   if line == '':
      break
   key,data = line.split(':')
   if key[:4] != 'agi_':
      #skip input that doesn't begin with agi_
      sys.stderr.write("Did not work!\n");
      sys.stderr.flush()
      continue
   key = key.strip()
   data = data.strip()
   if key != '':
      env[key] = data

sys.stderr.write("AGI Environment Dump:\n");
sys.stderr.flush()
for key in env.keys():
   sys.stderr.write(" -- %s = %s\n" % (key, env[key]))
   sys.stderr.flush()

def checkresult (params):
   params = params.rstrip()
   if re.search('^200',params):
      result = re.search('result=(\d+)',params)
      if (not result):
         sys.stderr.write("FAIL ('%s')\n" % params)
         sys.stderr.flush()
         return -1
      else:
         result = result.group(1)
         #debug("Result:%s Params:%s" % (result, params))
         sys.stderr.write("PASS (%s)\n" % result)
         sys.stderr.flush()
         return result
   else:
      sys.stderr.write("FAIL (unexpected result '%s')\n" % params)
      sys.stderr.flush()
      return -2

def sayit (params):
   sys.stderr.write("STREAM FILE %s \"\"\n" % str(params))
   sys.stderr.flush()
   sys.stdout.write("STREAM FILE %s \"\"\n" % str(params))
   sys.stdout.flush()
   result = sys.stdin.readline().strip()
   checkresult(result)

def saynumber (params):
   sys.stderr.write("SAY NUMBER %s \"\"\n" % params)
   sys.stderr.flush()
   sys.stdout.write("SAY NUMBER %s \"\"\n" % params)
   sys.stdout.flush()
   result = sys.stdin.readline().strip()
   checkresult(result)

def getnumber (prompt, timelimit, digcount):
   sys.stderr.write("GET DATA %s %d %d\n" % (prompt, timelimit, digcount))
   sys.stderr.flush()
   sys.stdout.write("GET DATA %s %d %d\n" % (prompt, timelimit, digcount))
   sys.stdout.flush()
   result = sys.stdin.readline().strip()
   result = checkresult(result)
   sys.stderr.write("digits are %s\n" % result)
   sys.stderr.flush()
   if result:
      return result
   else:
      result = -1

limit=20
digitcount=2
score=0
count=0
ttanswer=5000

starttime = time.time()
t = time.time() - starttime

sayit("/usr/share/asterisk/sounds/subtraction-game/subtraction-game-welcome")

while ( t < 180 ):

   big = random.randint(0,limit+1)
   big += 10
   subt= random.randint(0,big)
   ans = big - subt
   count += 1

   #give problem:
   sayit("/usr/share/asterisk/sounds/subtraction-game/subtraction-game-next");
   saynumber(big);
   sayit("/usr/share/asterisk/sounds/subtraction-game/minus");
   saynumber(subt);
   res = getnumber("/usr/share/asterisk/sounds/subtraction-game/equals",ttanswer,digitcount);

   if (int(res) == ans) :
      score+=1
      sayit("/usr/share/asterisk/sounds/subtraction-game/subtraction-game-good");
   else :
      sayit("/usr/share/asterisk/sounds/subtraction-game/subtraction-game-wrong");
      saynumber(ans);

   t = time.time() - starttime

pct = float(score)/float(count)*100;
sys.stderr.write("Percentage correct is %d\n" % pct)
sys.stderr.flush()

sayit("/usr/share/asterisk/sounds/subtraction-game/subtraction-game-timesup")
saynumber(score)
sayit("/usr/share/asterisk/sounds/subtraction-game/subtraction-game-right")
saynumber(count)
sayit("/usr/share/asterisk/sounds/subtraction-game/subtraction-game-pct")
saynumber(pct)

Aufrufen aus der extensions.conf: Der Teilnehmer wählt in diesem Beispiel die Nummer 345 und los geht es mit dem Mathe-Training.

exten => 345,1,Answer()   
 same => n,AGI(subtraction_game.py)
 same => n,Hangup()

Bedienung: Das Spiel wird demnach durch die Wahl der Nummer 345 aufgerufen. Es werden der Reihe nach zwei Zahlen genannt, die zu subtrahieren sind. Die richtige Lösung ist mit der Telefon-Tastatur einzutippen. Dafür hat man ein paar Sekunden Zeit und erfährt, ob man falsch oder richtig liegt. Nach ein paar Minuten ist das Spiel vorbei und der Nutzer erfährt seinen Punktestand.

Was ist noch alles zu beachten, damit die AGI-Skripte funktionieren? Was grundsätzlich beim AGI-Skripten zu beachten ist, ist nachfolgend anfängerfreundlich erklärt. Dateien, die auf Windows erzeugt wurden, müssen umgewandelt werden, da sonst die Skripte nicht funktionieren. Dort steht auch in welches Verzeichnis die AGI-Skripte zu kopieren sind:

Rotes schwedisches Ericsson Dialog. Die Ziffern sind versetzt angeordnet. Ein kleines Skript für Asterisk löst das Problem.
Schwedische Wählscheibe: AGI-PHP-Skript für Asterisk wandelt die gewählten Nummern um – 1.11.2022: Schwedische Wählscheiben besitzen gegenüber den meisten Wählscheiben auf der Welt eine andere Bedruckung. Die Ziffern sind um eine Stelle entgegen des Uhrzeigersinns verrutscht dargestellt. Wer sich an den aufgedruckten Ziffern eines schwedischen Wählscheibentelefons orientiert, wählt falsch, wenn das Telefon z.B. an einer üblichen Telefonanlage, an einem Asterisk-Server oder an einer FritzBox angeschlossen ist. – weiter

Die Audio-Dateien: Die notwendigen Sounddateien sind auf Englisch und  nachfolgend in einer ZIP-Datei abgelegt: subtraction-game

Wie sie erzeugt werden können, ist nachfolgend beschrieben:

Online lassen sich Audio-Dateien in Formate umwandeln, die für Asterisk geeignet sind. Aber es geht noch viel mehr.
Erzeugen von Telefon-Ansagen in verschiedenen Sprachen – 3.11.2022: Für einen Anrufbeantworter oder meinen Asterisk-Server benötige ich Sprach-Ansagen in verschiedenen Sprachen. Die weiblichen oder männlichen Stimmen sollten professionell und deutlich klingen. Wie mache ich das für private Zwecke ohne einen Cent dafür zu zahlen? Und alles soll möglichst online erstellt werden können. – weiter

Debugging von Python mit der IDE Thonny: Thonny ist wie Python 2.7 und 3.0 bereits auf dem Raspbian Buster mitgeliefert. Allerdings läuft Thonny erst ab Python 3.0 und die Python-Bibliotheken pyst2 laufen nicht auf Python 3.

Debugging mit der IDE Thonny für Python 3.

Auf jeden Fall ist der Raspberry eine geeignete Plattform um Python zu erlernen. Mit Python und AGI erweitern sich die Möglichkeiten, die Asterisk bieten kann, erheblich.

 










Bitte tragen Sie zum Überleben dieser Website bei, schalten Sie Ihren Ad-Blocker ab und laden Sie die Site neu. Vielen Dank!