#! /usr/bin/python

class GZahl:
   """
   /* Klasse stellt eine ganze Zahl bereit
   """
   def __init__(self):
      """
      /* Der Initial-Wert ist 0
      """
      self.Wert=0

   def setWert(self,wert):
      """
      /* Der Wert wird auf wert gesetzt. Ist wert ein REAL, so
      /* werden die Nachkommastellen weggeschnitten, bei anderen
      /* Objekten erfolgt eine Fehlermeldung ber StdIO.
      /* ----------------------------------------------------------
      /* wert : integer : Wert der ganzen Zahl
      """
      try:
         self.Wert=int(wert)
      except:
         print "Objekte der Klasse GZahl knnen nur ganzzahlige Werte annehmen!"

   def getWert(self):
      """
      /* liefert den Wert zurck
      /* -------------------------------------
      /* Rckgabewert : integer
      """
      return self.Wert


if __name__ == "__main__":
   mGZ=GZahl()
   mGZ.setWert("ttt")
   print mGZ.getWert()
#! /usr/bin/python

from xterm import * # nur fr Testumgebung
from gzahl import *
import string

class Bruch:
   """
   /* Klasse Bruch stellt Zhler und Nenner und erforderliche Methoden bereit.
   """
   def __init__(self):
      """
      /* Zaehler und Nenner werden aus der Klasse GZahl gebildet
      """
      self.zaehler=GZahl()
      self.nenner=GZahl()

   def setZaehler(self,wert):
      """
      /* setzt den Zhler. Ist wert ein REAL, so werden die Stellen nach dem
      /* Komma abgeschnitten, ist wert ein anderes Objekt, so wird eine
      /* Fehlermeldung ber StdIO ausgegeben (s. Klasse GZahl)
      /* --------------------------------------------------------------------
      /* wert : integer : Wert fr Zhler
      """
      self.zaehler.setWert(wert)

   def setNenner(self,wert):
      """
      /* setzt den Nenner. Ist wert ein REAL, so werden die Stellen nach dem
      /* Komma abgeschnitten, ist wert ein anderes Objekt, so wird eine
      /* Fehlermeldung ber StdIO ausgegeben (s. Klasse GZahl)
      /* --------------------------------------------------------------------
      /* wert : integer : Wert fr Nenner
      """
      self.nenner.setWert(wert)

   def getZaehler(self):
      """
      /* liefert den Wert des Zhlers
      /* --------------------------------------
      /* Rckgabewert : integer
      """
      return self.zaehler.getWert()

   def getNenner(self):
      """
      /* liefert den Wert des Nenners
      /* --------------------------------------
      /* Rckgabewert : integer
      """
      return self.nenner.getWert()

   def invertieren(self):
      """
      /* vertauscht Zhler und Nenner (Kehrbruch)
      """
      zwi=self.zaehler
      self.zaehler=self.nenner
      self.nenner=zwi

   def erweitern_mit(self,n):
      """
      /* Der Bruch wird mit n erweitert
      /* ---------------------------------------------------
      /* n : integer : Wert, mit dem erweitert werden soll
      """
      self.zaehler.setWert(self.zaehler.getWert()*n)
      self.nenner.setWert(self.nenner.getWert()*n)
      
   def kuerzen_durch(self,n):
      """
      /* Der Bruch wird durch n gekrzt
      /* ---------------------------------------------------
      /* n : integer : Wert, durch den gekrzt werden soll
      """
      if (self.zaehler.getWert()%n==0) and (self.nenner.getWert()%n==0):
         self.zaehler.setWert(self.zaehler.getWert()/n)
         self.nenner.setWert(self.nenner.getWert()/n)
         return 1 # true
      else:
         return 0 # false
      
   def kuerzen(self):
      """
      /* primitiver Algorithmus, der soweit wie mglich krzt
      """
      x=1
      while x:
         N=self.nenner.getWert()
         x=0
         for i in range(2,N+1):
            x = x or self.kuerzen_durch(i)
                                                  

# Testumgebung:

if __name__ == "__main__":
   terminal=XTerm()
   mein_Bruch=Bruch()
   terminal.clear()
   terminal.output("Zhler eingeben: ")
   mein_Bruch.setZaehler(string.atoi(terminal.input()))
   terminal.output("\nNenner eingeben: ")
   mein_Bruch.setNenner(string.atoi(terminal.input()))
   terminal.goto(0,10)
   mein_Bruch.kuerzen()
   terminal.output("\nZhler: "+str(mein_Bruch.getZaehler()))
   terminal.output("\nNenner : "+str(mein_Bruch.getNenner())+"\n")
   mein_Bruch.invertieren()
   terminal.output("\nZhler: "+str(mein_Bruch.getZaehler()))
   terminal.output("\nNenner : "+str(mein_Bruch.getNenner())+"\n")

#! /usr/bin/python
 
from xterm import * # fr Testumgebung
from bruch import *
import string

class Bruchrechner:
   """
   /* stellet das Fachkonzept fr einen Bruchrechner dar
   """
   def __init__(self):
      """
      /* Attribute sind: Bruch1, Bruch2, Ergebnis, Operator (default: +)
      """
      self.bruch1=Bruch()
      self.bruch2=Bruch()
      self.ergebnis=Bruch()
      self.operator='+'

   def setOperator(self,wert):
      """
      /* Der Operator wird auf eine der Operationen + - * : gesetzt
      /* Es erfolgt noch keine Berechnung
      /* ----------------------------------------------------------
      /* wert : character : gewnschte Operation (ohne Fehlerabfragen)
      """
      self.operator=wert

   def getOperator(self):
      """
      /* liefert die ausgewhlte Operation zurck
      """
      return self.operator

   def setBruch(self,zaehler,nenner,Nr):
      """
      /* Bruch1 oder Bruch2 knnen definiert werden. 
      /* --------------------------------------------
      /* zaehler : integer 
      /* nenner  : integer 
      /* Nr      : integer : 1 oder 2  fr Bruch1 oder Bruch2
      """
      if Nr == 1 :
          self.bruch1.setZaehler(zaehler)
          self.bruch1.setNenner(nenner)
      else:
          self.bruch2.setZaehler(zaehler)
          self.bruch2.setNenner(nenner)
          
   def getBruch(self,Nr):
      """
      /* liefert den Bruch als Zahlenpaar zurck 
      /* -----------------------------------------------
      /* Nr: integer : 1,2 oder 3 fr Ergebnisbruch
      /* -----------------------------------------------
      /* Rckgabe : Paar : (integer,integer)
      """
      if Nr == 1 :
          return self.bruch1.getZaehler(), self.bruch1.getNenner()
      if Nr == 2:
          return self.bruch2.getZaehler(), self.bruch2.getNenner()
      if Nr == 3:
          return self.ergebnis.getZaehler(), self.ergebnis.getNenner()

   def erweitern_mit(self,n):
      """
      /* Bruch1 wird mit n erweitert (monadische Operation)
      /* -----------------------------------------------
      /* n : integer
      """
      self.bruch1.erweitern_mit(n)
      
   def kuerzen(self,Nr):
      """
      /* Bruch1, Bruch2 oder ergebnis werden soweit wie mglich gekrzt
      /* --------------------------------------------------------------
      /* Nr : 1,2 oder 3 fr Ergebnisbruch
      """
      if Nr==1:
         self.bruch1.kuerzen()
      if Nr==2:
         self.bruch2.kuerzen()
      if Nr==3:
         self.ergebnis.kuerzen()

   def berechne(self):
      """
      /* Entsprechend der Operations-Vorwahl wird die Berechnung aus den
      /* beiden Brchen durchgefhrt und als Ergebnisbruch gespeichert.
      /* (diadische Operationen: + - * : ). 
      /* Fehlermeldung, wenn Nenner 0 ber StdIO
      """
      if (self.bruch2.getNenner()==0) or (self.bruch1.getNenner()==0):
            print "Fehler! DIVISION durch 0!"
      else:
         if self.operator=='+':
            n=self.bruch1.getNenner()
            self.bruch1.erweitern_mit(self.bruch2.getNenner())
            self.bruch2.erweitern_mit(n)
            self.ergebnis.setZaehler \
                     (self.bruch1.getZaehler()+self.bruch2.getZaehler())
            self.ergebnis.setNenner(self.bruch1.getNenner())
         if self.operator=='-':
            n=self.bruch1.getNenner()
            self.bruch1.erweitern_mit(self.bruch2.getNenner())
            self.bruch2.erweitern_mit(n)
            self.ergebnis.setZaehler \
                     (self.bruch1.getZaehler()-self.bruch2.getZaehler())
            self.ergebnis.setNenner(self.bruch1.getNenner())
         if self.operator=='*':
            self.ergebnis.setZaehler \
                     (self.bruch1.getZaehler()*self.bruch2.getZaehler())
            self.ergebnis.setNenner \
                     (self.bruch1.getNenner()*self.bruch2.getNenner())
         if self.operator==':':
            if self.bruch2.getZaehler()==0:
               print "Fehler! DIVISION durch 0!"
            else:
               self.bruch2.invertieren()
               self.setOperator('*')
               self.berechne()
         self.kuerzen(3)

# Testumgebung:

if __name__ == "__main__":
   terminal=XTerm()
   terminal.clear()
   terminal.output("Zhler1 eingeben: ")
   z1=string.atoi(terminal.input())
   terminal.output("\nNenner1 eingeben: ")
   n1=string.atoi(terminal.input())
   terminal.output("Zhler2 eingeben: ")
   z2=string.atoi(terminal.input())
   terminal.output("\nNenner2 eingeben: ")
   n2=string.atoi(terminal.input())
   terminal.output("Operation + - * : ")
   o=terminal.input()
   terminal.goto(0,10)

   mB=Bruchrechner()
   mB.setOperator(o[0])
   mB.setBruch(z1,n1,1)
   mB.setBruch(z2,n2,2)
   mB.berechne()

   terminal.output("\nErgebnis: "+str(mB.getBruch(3))+"\n")
#! /usr/bin/python

import Tkinter
from Tkconstants import *
from bruchrechner import *

class xBruch:
   """
   /* GUI-Darstellung eines Bruches
   """
   def __init__(self,win):
      """
      /* Zwei Eingabefelder werden bereinander angeordnet (Zhler,Nenner).
      /* ------------------------------------------------------------------
      /* win kennzeichnet das Parent-Objekt, in das der Bruch gelegt wird.
      """
      zWert=Tkinter.StringVar()
      self.zaehler=Tkinter.Entry(win,textvariable=zWert, width=5)
      self.zaehler.pack()
      nWert=Tkinter.StringVar()
      self.nenner=Tkinter.Entry(win,textvariable=nWert, width=5)
      self.nenner.pack()

   def getZaehler(self):
      """
      /* liefert den eingegebenen Wert aus dem Zhler-Eingabefeld 
      """
      self.zaehler.selection_range(0,"end") 
      return (self.zaehler.selection_get())
 
   def getNenner(self):
      """
      /* liefert den eingegebenen Wert aus dem Nenner-Eingabefeld 
      """
      self.nenner.selection_range(0,"end") 
      return (self.nenner.selection_get())

   def setZaehler(self,wert):
      """
      /* Vorbesetzung des Zhler-Eingabefeldes mit einem Wert
      """
      self.zaehler.delete(0,"end")
      self.zaehler.insert(0,wert)         

   def setNenner(self,wert):
      """
      /* Vorbesetzung des Nenner-Eingabefeldes mit einem Wert
      """
      self.nenner.delete(0,"end")
      self.nenner.insert(0,wert)         

  
class xTaste:
   """
   /* GUI-Darstellung einer Taste
   """
   def __init__(self, win, Text, Bef, Seite=TOP):
      """
      /* win kennzeichnet das Parent-Objekt, in das die Taste gelegt wird.
      /* Text : string : Beschriftung der Taste
      /* Bef  : Methodenreferenz : Methode, die beim Drcken der Taste 
      /*                           ausgefhrt werden soll.
      /* Seite: opt. Parameter, um Tasten auch nebeneinander anordnen zu knnen
      """
      Knopf=Tkinter.Button(win, text=Text, command=Bef)
      Knopf.pack(side=Seite, padx=5, pady=12) 

class xRechner:
   """
   /* GUI-Darstellung des Rechners
   """
   def __init__(self,Rechner):
      """
      /* Bei der Objekterzeugung wird ein Fenster mit dem Rechner
      /* geffnet
      /* ---------------------------------------------------------
      /* Rechner: Referenz auf ein Objekt der Klasse Bruchrechner
      """
      self.Rechner=Rechner
      win=Tkinter.Tk()
      Fensterbreite=str(450)
      Fensterhoehe=str(350)
      geometrie=Fensterbreite+"x"+Fensterhoehe+"+0+0"
      win.geometry(geometrie)
      win.title("Bruchrechner")

      Rahmen0=Tkinter.Frame(win, relief=SUNKEN, bd=2)
      Rahmen0.pack(padx=5, pady=9) 
      RahmenX=Tkinter.Frame(win, bd=2)
      RahmenX.pack(padx=5, pady=9) 
      Rahmen1=Tkinter.Frame(Rahmen0, relief=SUNKEN, bd=2)
      Rahmen1.pack(side=LEFT, padx=5, pady=9) 
      Rahmen2=Tkinter.Frame(Rahmen0, relief=SUNKEN, bd=2)
      Rahmen2.pack(side=LEFT, padx=5, pady=9) 
      Rahmen3=Tkinter.Frame(Rahmen0, relief=SUNKEN, bd=2)
      Rahmen3.pack(side=LEFT, padx=5, pady=9) 
      Rahmen4=Tkinter.Frame(Rahmen0, relief=SUNKEN, bd=2)
      Rahmen4.pack(side=LEFT, padx=5, pady=9) 
      Rahmen5=Tkinter.Frame(Rahmen0, relief=SUNKEN, bd=2)
      Rahmen5.pack(side=LEFT, padx=5, pady=9) 

      self.B1=xBruch(Rahmen1)
      self.B2=xBruch(Rahmen3)
      self.B3=xBruch(Rahmen5)

      K0=xTaste(Rahmen4,' = ', self.ist)
      K1=xTaste(Rahmen2,' + ', self.plus)
      K2=xTaste(Rahmen2,' - ', self.minus)
      K3=xTaste(Rahmen2,' * ', self.mal)
      K4=xTaste(Rahmen2,' : ', self.geteilt)
      KY=xTaste(RahmenX,' krzen ',self.kuerzen, "left")
      KX=xTaste(RahmenX,' E N D E ', "exit", "left")
      
   def ist(self):
      """
      /* Methode, die beim Drcken der = Taste aufgerufen wird
      """
      self.Rechner.setBruch(self.B1.getZaehler(),self.B1.getNenner(),1)
      self.Rechner.setBruch(self.B2.getZaehler(),self.B2.getNenner(),2)
      self.Rechner.berechne()
      self.B3.setZaehler(self.Rechner.getBruch(3)[0])
      self.B3.setNenner(self.Rechner.getBruch(3)[1])

   def plus(self):
      """
      /* Methode, die beim Drcken der + Taste aufgerufen wird
      """
      self.Rechner.setOperator('+')

   def minus(self):
      """
      /* Methode, die beim Drcken der - Taste aufgerufen wird
      """
      self.Rechner.setOperator('-')

   def mal(self):
      """
      /* Methode, die beim Drcken der * Taste aufgerufen wird
      """
      self.Rechner.setOperator('*')

   def geteilt(self):
      """
      /* Methode, die beim Drcken der : Taste aufgerufen wird
      """
      self.Rechner.setOperator(':')

   def kuerzen(self):
      """
      /* Methode, die beim Drcken der Krzen-Taste aufgerufen wird
      """
      self.Rechner.setBruch(self.B1.getZaehler(),self.B1.getNenner(),1)
      self.Rechner.kuerzen(1)
      self.B3.setZaehler(self.Rechner.getBruch(1)[0])
      self.B3.setNenner(self.Rechner.getBruch(1)[1])
      
if __name__ == "__main__":
   mRechner=Bruchrechner()
   mWindow=xRechner(mRechner)
   Tkinter.mainloop()
