Ich präsentiere ... den Bierrechner :)

Stellt hier eure Projekte vor.
Internetseiten, Skripte, und alles andere bzgl. Python.
Benutzeravatar
snafu
User
Beiträge: 6738
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Code: Alles auswählen

#!/usr/bin/env python

import sys


def buy_beer(money, price_bootle, deposit_bottle, bring_back=True):
    bottles, rest = divmod(money, price_bottle)
    if not bring_back:
        return bottles, rest
    deposit = bottles * deposit_bottle
    money_after = rest + deposit
    return bottles, rest, deposit, money_after


if __name__ == '__main__':
    try:
        money = float(raw_input('Wieviel Geld in Bier anlegen: '))
        price_bottle = float(raw_input('Preis pro Flasche: '))
        deposit_bottle = float(raw_input('Pfandpreis pro Flasche: '))
    except ValueError:
        print >> sys.stderr, (
            'Bitte nur Zahlen im korrekten Format angeben!\n'
            '(z.B.: 2.70 statt 2,70)')
        exit(1)

    print (
        'Kaufe %d Flaschen, habe noch %0.2f Euro\n'
        'Nach dem Austrinken gibt es %0.2f Euro an Pfand\n'
        'Kontostand nun %0.2f Euro'
        % buy_beer(money, price_bottle, deposit_bottle))
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Das Tool fehlte mir immer bisher :-D

Wunschliste:
- GUI
- Vordefinierter Pfand (für Glasflaschen in D imho 0.08€)
- Vordefinierte Sorten mit Preisen (Kästenpreise?)
- Schnittstelle für eigene Online-Preis-Crawler für den Getränkemarkt seines Vertrauens

Dazu Plugin-System, damit man z.B. so etwas wie den Random-Bier-Chooser proggen kann, der einem bei Entscheidungsschwierigkeiten hilft, eine Sorte zu wählen ;-)

Wenn man dann noch Bewertungssysteme mit einbaut und das ganz womöglich fit macht für den Semantic- und Social-Desktop von KDE, kann man noch einiges rausholen für das komplette Biertrinker-Rundum-Sorglos-Suite :-D
Benutzeravatar
snafu
User
Beiträge: 6738
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Zum Pfand: Hatte ich erst vordefiniert, aber wenn man mal ein Flens oder andere Flaschen mit Plöppverschluss kauft, sind es 15 cent Pfand. ;)

Ich werde mal sehen, ob ich ein paar Sachen einbaue. GUI sehe ich aber vorerst als nachrangig an. Mich freut aber die prompte positive Resonanz. :)

Und hey: Ich finde das Ding ernsthaft praktisch. :D

Vielleicht sollte ich es auch in Pfandtomator oder so umbennen. Es gibt ja durchaus Leute mit exzessivem Cola- oder ClubMate-Verbrauch.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Naja, man könnte ja ein Mapping zwischen Sorte und Flasche einbauen. Daraus bestimmt sich der Pfand :-)

Da man ja so seine bevorzugten Biersorten hat, könnte das schon helfen :-D

Na, GUI wäre eben praktischer für die Eingaben / Einstellungen. Aber klar, hat sicher keine Priorität ;-)
n4p
User
Beiträge: 55
Registriert: Dienstag 10. Juni 2008, 11:05

Es fehlt in meinen Augen eher die Schleife, wie weit man an einem Abend ca. kommt. (vielleicht auch noch mit der Möglichkeit im noch nüchternen Zustand einen Restwert für Bus / Taxi zu hinterlegen).

Ansonsten schließe ich mich natürlich dem Wunsch nach Preislisten (mit Onlineaktualisierung versteht sich) an. :lol:
Benutzeravatar
Damaskus
Administrator
Beiträge: 995
Registriert: Sonntag 6. März 2005, 20:08
Wohnort: Schwabenländle

n4p hat geschrieben:Es fehlt in meinen Augen eher die Schleife, wie weit man an einem Abend ca. kommt. (vielleicht auch noch mit der Möglichkeit im noch nüchternen Zustand einen Restwert für Bus / Taxi zu hinterlegen).
Dito! Und bitte die Auswahlmöglichkeit für Fäßer hinzufügen!

Danke! :wink: :wink:

Gruß
Damaskus
Dauerbaustelle
User
Beiträge: 996
Registriert: Mittwoch 9. Januar 2008, 13:48

Und bitte eine Möglichkeit "Ethanolgehalt" mit "Koffeingehalt" auszutauschen - für die Nicht-Alkoholtrinker hier ;)
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Alkoholfreies Bier mit Koffein?! Das geht ja mal gar nicht! :twisted:
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Benutzeravatar
snafu
User
Beiträge: 6738
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

beercalc.py

beercalc_gui.py

beercalc.ui

Erstmal nur die grafische Umsetzung der bisherigen Funktionen.

Würde wohl ein Hintergrundbild aussehen? Ich dachte daran.
Zuletzt geändert von snafu am Dienstag 26. Mai 2009, 16:00, insgesamt 1-mal geändert.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Postestes das UI-File bitte auch noch? Würds gerne mal antesten! :-)
Benutzeravatar
snafu
User
Beiträge: 6738
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Hyperion hat geschrieben:Postestes das UI-File bitte auch noch? Würds gerne mal antesten! :-)
Ja, ganz vergessen. Hab's dazueditiert. Is aber nix besonderes... In Guis bin ich eh nicht so gut (Gestaltung).
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

lunar hat geschrieben:Da fällt mir dieser kleine Anreiz zur Investition in Bier ein ...
nice :-)
Benutzeravatar
snafu
User
Beiträge: 6738
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Ich stehe jetzt vor einem Problem, das ich mir nicht erklären kann: Das Abspeichern neuer Biere ist auf CLI-Ebene einigermaßen implementiert und ich habe mir einen um Biereigenschaften erweiterten ConfigParser geschrieben. Jetzt möchte ich das Ganze in die grafische Oberfläche einbauen und nutze dafür ein QTableWidget. Der entsprechende Abschnitt der Doku empfiehlt das Abschalten der Sortierung, wenn man Elemente per Loop einfügen will. Aber warum wirft mir das einen Fehler?

Code: Alles auswählen

~$ ./beerconf_gui.py
<class 'PyQt4.QtGui.QTableWidget'>
Traceback (most recent call last):
  File "/home/sebastian/beerconf_gui.py", line 32, in <module>
    window = MainWindow()
  File "/home/sebastian/beerconf_gui.py", line 15, in __init__
    self.init_beers()
  File "/home/sebastian/beerconf_gui.py", line 23, in init_beers
    self.beers.sortingEnabled(False)
AttributeError: sortingEnabled
Das Widget erbt doch von QTableView und folglich wundert mich der AttributeError. Oder bin ich blind und übersehe einen Tippfehler meinerseits?

beerconf_gui.py

beerconf.py

beerconf.ui
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

snafu hat geschrieben:

Code: Alles auswählen

~$ ./beerconf_gui.py
<class 'PyQt4.QtGui.QTableWidget'>
Traceback (most recent call last):
  File "/home/sebastian/beerconf_gui.py", line 32, in <module>
    window = MainWindow()
  File "/home/sebastian/beerconf_gui.py", line 15, in __init__
    self.init_beers()
  File "/home/sebastian/beerconf_gui.py", line 23, in init_beers
    self.beers.sortingEnabled(False)
AttributeError: sortingEnabled
Oder bin ich blind und übersehe einen Tippfehler meinerseits?
Ich glaube schon. Du rufst eine Methode auf, das ist aber ein Attribut!
lunar

Darf man fragen, was die Verrenkungen in "BeerConfig.__init__()" zum Zweck haben? Eine Bibliotheksklasse sollte niemals globale Änderungen zur Folge haben (in diesem Fall die Manipulation des Arbeitsverzeichnisses), zumal du ein paar Zeilen weiter unten doch zeigst, dass du eigentlich weißt, wie man es richtig macht (in dem man absolute Pfade mit "os.path.join()" erzeugt). Außerdem existiert "ConfigParser.read()", so dass du dir den Test auf Existenz auch sparen kannst (der sowieso nicht atomar ist, im schlimmsten Fall leert diese Chose daher die Konfigurationsdatei). Die Ausgabe mit "print" gehört da übrigens ebenfalls nicht hin, Ausgaben aus Bibliotheksklassen sind allenfalls per "logging" ok.

Desweiteren sollte "BeerConfig.beers()" einen Generator zurückgeben, die Liste ist an dieser Stelle schließlich noch nicht nötig. Außerdem würde ich daraus vielleicht eine Eigenschaft und keine Methode machen.

Das Speichern der Konfigurationsdatei hat in "BeerConfig.add_beer()" imho nichts zu suchen, ich würde dafür eine separate Methode erzeugen. Außerdem ist eine Konfigurationsdatei keine Binärdatei, im Mindestens aber solltest du dich für eine der beiden Möglichkeiten entscheiden. Binär speichern und als Text lesen macht Probleme unter Windows. Die Ausnahmebehandlung ist an dieser Stelle imho unelegant, der Einsatz von "ConfigParser.has_section()" würde an dieser Stelle zwei Codezeilen sparen, die keinen Mehrwert bringen und die Lesbarkeit eher verringern.

Im Bezug auf den eigentlichen Fehler solltest du dir in der Beschreibung dieser Eigenschaft mal ganz genau durchlesen, wie die dazugehörigen Getter und Setter wirklich heißen. Für den Aufruf von ".setFixedSize()" in "MainWindow.__init__()" sollte man dich eigentlich hauen ;), eine vernünftige GUI nutzt Layoutmanagement. Die explizite Konvertierung zu "QString()" in Zeile 25 von "beerconf_gui" ist iirc nicht nötig, allerdings bin ich mir da nicht sicher, dass müsstest du ausprobieren. Die UI-Datei per Konstruktor zu übergeben, ist imho keine gute Idee, die UI ist schließlich elementarer Bestandteil des Objekts und eigentlich keine Sache, die der Nutzer der Klasse konfigurieren sollte. Ich würde den Pfad zur UI-Datei in ein Klassenattribut stecken. Und außerdem einen absoluten Pfad dafür nutzen, nicht immer liegt die UI-Datei im aktuellen Arbeitsverzeichnis. So gesehen ist es reines Glück, dass du "BeerConfig" erst nach dem Laden der UI erzeugst, andersrum knallst nämlich (siehe oben).

Btw, du darfst auch "Schleife" sagen ;)
Zuletzt geändert von lunar am Dienstag 26. Mai 2009, 23:13, insgesamt 1-mal geändert.
Benutzeravatar
snafu
User
Beiträge: 6738
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Danke, ich werde mich wohl mal intensiver mit diesem QTableWidget beschäftigen müssen. Denn Items werden trotzdem nicht anzeigt. :(

Code: Alles auswählen

    def init_beers(self):
        self.beers.setSortingEnabled(False)
        for beer in self.beerconfig.beers():
            print beer
            item = QtGui.QTableWidgetItem(QtCore.QString(beer[0]))
            self.beers.setItem(1, 1, item)
        self.beers.setSortingEnabled(True)
Aber für heute ist erstmal gut...
lunar

Naja, du solltest vielleicht jedem Element seine eigene Zeile gönnen ;) Außerdem es ist vielleicht auch erforderlich, dem Widget mittels ".setRowCount()" und ".setColumnCount()" mitzuteilen, wie viele Spalten und Zeilen es denn tatsächlich anzeigen soll.
Benutzeravatar
snafu
User
Beiträge: 6738
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Vielen Dank für die ganzen Tipps, Lunar. Ich bin jetzt auf eine Liste umgestiegen, da eine Tabelle nicht wirklich das war, was ich wollte.

Mit dem Design hat es bei BeerConf ganz gut geklappt. Bei BeerCalc bin ich allerdings auf Probleme gestoßen, die ich beim besten Willen nicht alleine gelöst bekomme. Und zwar möchte ich, dass die Überschriften einen anderen Abstand zur jeweiligen SpinBox haben als die darunter liegenden Buttons.

Dazu habe ich Überschrift + SpinBox zu einem vertikalen Design zusammengefasst und dieses Design anschließend als weiteres vertikales Design mit dem Button verbunden. Das ganze eben dreimal.

Soweit sieht das auch aus wie gewünscht. Nur wenn ich daraus ein komplettes (tabellarisches) Design für's ganze Fenster machen will, haut er mir einen Riesenabstand zwischen Text und SpinBox rein, obwohl `spacing` auf 0 steht:

Bild

Wo liegt hier das Problem?

Archiv mit Dateien
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Ich glaube das Problem liegt daran, dass halt irgend etwas expandiert werden muss.

Ich habe mal ein wenig mit Deiner Datei rumgespielt und folgende Muster bekommen:

Bild

Bild

Bild

Letzteres wäre ja evtl. das, was Dir vorschwebt. Allerdings ist es ja eigentlich ziemlich sinnlos, da der untere Teil ja eben expandiert. Da wäre es wohl besser die Vertikale Größe festzusetzen.

Habe grad festgestellt, dass es noch einfacher geht, indem man die Berechnungsgruppen jeweils in ein VerticalLayout steckt und dann den Spacer direkt darunter einfügt. Darauf dann das Tabellarische Layout anwenden und man hat optisch dasselbe Ergebnis wie Screenshot3.

Generell muss man darauf achten, auch bei den Layouts die layoutSize auf setFixedSize zu stellen.

Vielleicht hilft Dir das ja weiter :-)
Antworten